Field values
Every entry’s fields object has one key per element (field) of its type, keyed by the element’s apiKey. This page gives the JSON shape, empty behaviour and filter operators of all 17 element kinds as the Content Delivery API returns them. Query syntax is in Content Delivery API: filters.
Summary of all element kinds
Each element kind has one fixed JSON shape in Content Delivery API output, and every kind uses null for empty.
| Kind | JSON in Delivery output | Filter operators |
|---|---|---|
text |
string; with the JSON editor: the parsed JSON value | eq, ne, in, contains, exists; with the JSON editor: exists |
markdown |
string (Markdown, asset URLs absolute) | eq, ne, in, contains, exists |
number |
number | eq, ne, gt, gte, lt, lte, in, exists |
boolean |
true or false |
eq, ne, exists |
date |
string (YYYY-MM-DD, ISO date-time or HH:MM); range: {start, end} |
eq, ne, gt, gte, lt, lte, in, exists; range: exists |
choice |
string; multiple: array of strings | eq, ne, in, exists |
link |
{url, label?} |
eq, ne, in, contains, exists |
images |
array of asset objects | exists |
files |
array of asset objects | exists |
contact |
{name?, email?, phone?, website?, address?} |
contains, exists |
color |
string #rrggbb |
eq, ne, in, exists |
reference |
{id, type, title}; multiple: array of them |
eq, ne, in, exists; multiple: eq, in, exists |
geo |
GeoJSON FeatureCollection | exists |
identifier |
string | eq, ne, in, contains, exists |
embed |
{url, provider, embedUrl} |
exists |
location |
{lng, lat, address?} |
exists |
phone |
string | eq, ne, in, contains, exists |
The web app’s names for these kinds are listed in Elements.
Rules that apply to every kind
These rules hold for all element kinds in Content Delivery API output:
- Published copy only. Values change in the API when the entry is published, never when a draft is saved.
- Every effective element is present. Inherited elements come first, then the type’s own, in model order (as in
/types). A field without a value isnull, never missing. - Empty means
null. An absent value,null,"",[]and{}all come out asnull.falseand0are values, not empty:filter[entrance-fee][exists]=trueincludes an entry with"entrance-fee": 0. - Hidden elements. Archived elements and elements no longer assigned to the type are left out of
fields. Their stored values are kept and reappear if the element is assigned again. existsfollows the output.exists=truematches exactly the entries where the field is notnull.exists=falseandnealso match entries whose type does not have the element.- Languages. In a project with languages, only
text(not JSON text) andmarkdownvalues, and the labels ofchoiceoptions, depend on the language you ask for (locale); a missing translation falls back to the default language. Every other kind is the same in all languages, and so is a choice’s stored value. - Settings live in
/types. Units, option labels, allowed shapes and other settings are inelements[].configof/types, not in the value.
text
A text field is a string. Single-line text is trimmed when saved; multi-line text keeps its line breaks. Minimum and maximum lengths are checked when saving and do not affect output.
"opening-hours": "Mon-Fri 9:00-18:00\nSat 9:00-17:00\nSun 10:00-16:00"
With config.editor: "json", the stored text is parsed and delivered as JSON: an object, array, number, string or boolean. If the stored text is not valid JSON, the field is null. Only exists is supported; it is true when the text parses to something other than null.
"specs": {"trailMiles": 9, "dogs": true, "lots": ["Ecola Point", "Indian Beach"]}
Filters on plain text: eq, ne and in are exact and case-sensitive; contains is a case-insensitive substring, with % and _ taken literally. filter[subtitle]=forested headland above cannon beach finds nothing if the stored text is capitalised, while filter[subtitle][contains]=HEADLAND finds it.
markdown
A markdown (rich text) field is a Markdown string as written in the editor. Links to the project’s own files in [](...), , reference definitions ([x]: ...) and src= or href= attributes are rewritten to absolute URLs, so the text works on another site. Other text is unchanged.
"description": "See the [trail map](https://api.spatibase.com/assets/350f422e-2ab1-41ed-b8d7-90a9939f2d2b/trail-map.pdf).\n\n<img src=\"https://api.spatibase.com/assets/d959ef72-8b3c-4f0e-a1d2-7c5e9b4f6a13/logo.svg\" alt=\"\">"
Filters behave as for plain text, on the raw Markdown source.
number
A number field is a JSON number. The unit (for example "USD"), minimum, maximum and whole-number setting are in config (unit, min, max, integer), not in the value.
"rating": 4.9, "entrance-fee": 0
Filter values must be numeric (4.8, -1, 1e3), and comparison is numeric.
boolean
A boolean field is true or false. Filter values must be true or false. filter[open-now]=false matches only entries that store false, not empty ones; use filter[open-now][exists]=false for those.
"open-now": false
date
A date field is the stored string in a form set by config.mode:
| Mode | Value | Example |
|---|---|---|
date (default) |
YYYY-MM-DD |
"founded": "1932-05-01" |
datetime |
ISO 8601 date-time as saved. The web app saves UTC (...Z); imports and the Content Management API keep the offset they were given |
"next-event": "2026-11-07T18:00:00.000Z", "next-event": "2026-11-07T10:00:00-08:00" |
time |
HH:MM or HH:MM:SS, 24-hour, no date or zone |
"opens-at": "09:00" |
With config.range: true the value is {start, end} in the same form. Key order in the JSON is not meaningful. A range can only be filtered with exists.
After a mode switch the value follows the field’s current mode; stored values are unchanged. In date mode a stored date-time gives its date (the first 10 characters, no time zone conversion). A value that doesn’t fit the mode (a date or date-time in time mode, a time in date or datetime mode) is null; a date without a time stays valid in datetime mode. A range applies this to both ends and is null if either end doesn’t fit.
"season": {"start": "2027-05-01", "end": "2027-10-15"}, "visiting-hours": {"start": "06:00", "end": "22:00"}
Filters on single values compare typed values, not strings:
datecompares calendar dates. A stored or given date-time is reduced to its date, sofilter[founded]=1953-07-01matches"1953-07-01T12:00:00Z".datetimecompares instants.filter[next-event]=2026-11-07T18:00:00Zandfilter[next-event]=2026-11-07T19:00:00%2B01:00match the same entries. Always sendZor an offset, and encode+as%2B: an unencoded+becomes a space and the request fails with400.timecompares times of day.filter[opens-at][lt]=09:30andfilter[opens-at][lt]=9:30are the same;25:00is a400.
choice
A choice field is the chosen option’s value, not its label. With config.multiple: true it is an array of distinct values in the order chosen. Options can form a tree up to 4 levels deep, and any node, parent or child, can be chosen; labels and the tree are in config.options of /types.
"difficulty": "easy", "amenities": ["restrooms", "parking", "camping", "visitor-center"]
- Filter values must be option values of the element; the
400lists them. Matching is exact, so a parent option does not match its children:filter[activities]=hikingdoes not findday-hike. - For multiple choice,
eqmeans “has this option”,inmeans “has any of them”, andnemeans “does not have it”. Twoeqfilters on the same key need both options. - The shape follows the element’s current setting: after multiple choice is switched on, a value saved earlier comes out as a one-item array; after it is switched off, a list comes out as its first known option.
- Only current options count. A value that is no longer an option (removed or renamed while entries used it) comes out as
nullfor a single choice and is dropped from a multiple choice (nullwhen nothing is left);filter[<key>][exists]matches the same way. The stored value is kept, so it comes back if the option does. Vector tiles follow the same rule.
link
A link field is {url} or {url, label}; the label is left out when empty. URLs are http or https.
"website": {"url": "https://www.nps.gov/redw/", "label": "National Park Service"}
eq, ne and in compare the URL exactly; contains searches the URL and the label, case-insensitively.
images and files
An images or files field is an array of asset objects in the order the editor arranged them. images only accepts web images (JPEG, PNG, GIF, WebP, AVIF, SVG); files accepts any file, optionally limited by config.allowedFormats (for example [".pdf"]). Assets deleted from the media library are dropped, and when none are left the field is null.
"brochure": [{"id": "350f422e-2ab1-41ed-b8d7-90a9939f2d2b", "url": "https://api.spatibase.com/assets/350f422e-2ab1-41ed-b8d7-90a9939f2d2b/trail-map.pdf", "filename": "trail-map.pdf", "mimeType": "application/pdf", "size": 125, "width": null, "height": null, "alt": ""}]
| Key | Meaning |
|---|---|
id |
the asset’s UUID |
url |
absolute file URL; images accept resize parameters (Assets and images) |
filename, mimeType |
the file name and media type |
size |
size in bytes |
width, height |
pixels for images, as displayed (after EXIF rotation); null for other files |
alt |
alt text from the media library, "" if none |
Only exists is supported.
contact
A contact field is an object with only the non-empty keys among name, email, phone, website and address. address is itself an object with any of street, city, region, postalCode and country.
"contact": {"name": "Arcata store", "email": "arcata@example.com", "phone": "+1 707-555-0134", "website": "https://example.com/arcata", "address": {"street": "855 G Street", "city": "Arcata", "region": "CA", "postalCode": "95521", "country": "United States"}}
contains searches all parts at once (filter[contact][contains]=arcata); eq is not supported.
color
A color field is a lowercase hex color, #rrggbb; input such as #16A34A is stored lowercase. Filter values must be #rrggbb and match case-insensitively. Encode # as %23 in URLs: filter[brand-color]=%2316a34a.
"brand-color": "#16a34a"
reference
A reference field is a stub of the linked entry, {id, type, title}, using the target’s published title and type apiKey. With config.multiple: true it is an array of stubs. include=references replaces stubs with full entry objects, one level deep (Expand references).
"region": {"id": "66f36784-bb65-4de3-a745-bfd294cdf017", "type": "region", "title": "Northern California Coast"}, "parks": [{"id": "822eecd4-c73c-4bc2-8289-6232512259eb", "type": "national-park", "title": "Redwood National Park"}]
- A target that is unpublished, deleted or of a switched-off type is hidden: a single reference becomes
null, a multiple reference drops it, and an empty list becomesnull. Filters see the same thing:exists,eqandinonly match visible targets. - Filter values are entry ids (UUIDs).
filter[region]=<regionId>finds everything that links to one entry, such as all stores and parks in a region. Multiple references supporteq(links to this entry) andin, but notne. config.targetTypesin/typeslists the allowed target types; their subtypes are allowed too.
geo
A geo (map shapes) field is a GeoJSON FeatureCollection with one or more shapes, independent of the entry’s main location. Each feature has a geometry (Point, LineString, Polygon or a Multi* form, [lng, lat], 7 decimals) and properties with an optional label and, when the element uses map feature types, a featureType apiKey. Names, icons and colors of feature types come from /feature-types. No shapes means null.
"parking": {"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [-124.0912, 41.2843]}, "properties": {"label": "Kuchel Visitor Center", "featureType": "parking"}}]}
Geo fields are not used by bbox or near and are not in vector tiles. Only exists is supported; it is true when there is at least one shape.
identifier
An identifier field is a string of letters, digits, ., _ and - (at most 64 characters by default), unique per element across the project’s entries. Use it for slugs and external ids. Filters work as for plain text: filter[slug]=redwood-national-park.
"slug": "redwood-national-park"
embed
An embed field is {url, provider, embedUrl}: the pasted URL, the detected provider, and an iframe-ready URL. config.providers may restrict which providers editors can use.
provider |
embedUrl |
|---|---|
youtube |
https://www.youtube-nocookie.com/embed/<id> |
vimeo |
https://player.vimeo.com/video/<id>, with ?h=<hash> for unlisted videos |
spotify |
https://open.spotify.com/embed/<track, album, playlist, episode, show or artist>/<id>, or null for other Spotify pages |
soundcloud |
https://w.soundcloud.com/player/?url=<encoded track URL> |
other |
null; link to url instead |
"video": {"url": "https://www.youtube.com/watch?v=HkCrhLf-ksY", "provider": "youtube", "embedUrl": "https://www.youtube-nocookie.com/embed/HkCrhLf-ksY"}
embedUrl is also null when no player address can be built from the URL, for example a YouTube playlist or a SoundCloud home page. Only exists is supported.
location
A location field is a single point with an optional address: {lng, lat} or {lng, lat, address}. Longitudes are wrapped into -180 to 180 and both values are rounded to 7 decimals. This is a field, not the entry’s main location, so it is not used by bbox, near, GeoJSON geometry or tiles.
"starting-point": {"lng": -124.0912, "lat": 41.2843, "address": "Kuchel Visitor Center, Orick, CA 95555"}
Only exists is supported.
phone
A phone field is the number as typed, trimmed and with runs of spaces collapsed: digits, spaces and + ( ) . - /, 5 to 25 characters with at least 5 digits. It is not normalised to a standard format, so contains on the digits you know is the most reliable filter: filter[rental-phone][contains]=707.
"rental-phone": "+1 707-555-0135"
Related
Updated