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 is null, never missing.
  • Empty means null. An absent value, null, "", [] and {} all come out as null. false and 0 are values, not empty: filter[entrance-fee][exists]=true includes 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.
  • exists follows the output. exists=true matches exactly the entries where the field is not null. exists=false and ne also match entries whose type does not have the element.
  • Languages. In a project with languages, only text (not JSON text) and markdown values, and the labels of choice options, 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 in elements[].config of /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.

json
"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.

json
"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.

json
"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.

json
"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.

json
"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.

json
"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:

  • date compares calendar dates. A stored or given date-time is reduced to its date, so filter[founded]=1953-07-01 matches "1953-07-01T12:00:00Z".
  • datetime compares instants. filter[next-event]=2026-11-07T18:00:00Z and filter[next-event]=2026-11-07T19:00:00%2B01:00 match the same entries. Always send Z or an offset, and encode + as %2B: an unencoded + becomes a space and the request fails with 400.
  • time compares times of day. filter[opens-at][lt]=09:30 and filter[opens-at][lt]=9:30 are the same; 25:00 is a 400.

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.

json
"difficulty": "easy", "amenities": ["restrooms", "parking", "camping", "visitor-center"]
  • Filter values must be option values of the element; the 400 lists them. Matching is exact, so a parent option does not match its children: filter[activities]=hiking does not find day-hike.
  • For multiple choice, eq means “has this option”, in means “has any of them”, and ne means “does not have it”. Two eq filters 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 null for a single choice and is dropped from a multiple choice (null when 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.

A link field is {url} or {url, label}; the label is left out when empty. URLs are http or https.

json
"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.

json
"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.

json
"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.

json
"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).

json
"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 becomes null. Filters see the same thing: exists, eq and in only 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 support eq (links to this entry) and in, but not ne.
  • config.targetTypes in /types lists 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.

json
"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.

json
"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
json
"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.

json
"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.

json
"rental-phone": "+1 707-555-0135"

Updated

Docs support

How can we help?

A person on our team reads every message. We include the page you are on, so you don't have to explain where.

Or write to hello@spatibase.com. For outages, check System status.

Talk to us

Not sure it’s a fit? Let’s find out

Tell us about your use case and what you need, from data model to security and deployment. In 30 minutes we’ll look at it together and tell you honestly if we can help.

Or write to hello@spatibase.com.