> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rivi.software/llms.txt
> Use this file to discover all available pages before exploring further.

# Field types and empty states

> Understand real values, nullable and optional fields, published content schemas, timestamps, units, and freshness.

## Read the schema alongside the examples

Response samples use realistic fictional values, such as `"radio-rivier"`, `25`, `true`, and arrays of published records. Types still matter: a quoted number is a string, a JSON boolean is not a string, and `null` is not an empty string.

| Schema type | Example JSON value | Meaning |
| - | - | - |
| `string` | `"Radio Rivier"` | Text; check any format, enum, length, or pattern constraints |
| `integer` | `25` | A whole number, such as a page limit or elapsed seconds |
| `number` | `16.5` | A number that may include a fractional part |
| `boolean` | `true` | A true/false flag, such as `isPlaying` |
| `array` | `[]` | An ordered collection; an empty array is a valid empty result |
| `object` | `{ "cache": "no-store" }` | Named properties; required fields and allowed extra properties depend on the schema |
| A type plus `null` | `null` | An explicitly absent or unknown value, as described by the field |
| An enum | `"fresh"` | One of the exact documented values, with matching spelling and case |

**Required** and **nullable** are independent. A required nullable property must exist, but its value can be `null`. An optional property can be omitted. For example, a track includes `album` even when its value is `null`, while `artworkUrl` may be missing entirely. Do not manufacture empty strings or zeroes for unknown values.

## Common field formats

| Field | Illustrative value | Interpretation |
| - | - | - |
| `stationSlug` | `"radio-rivier"` | Public station URL slug |
| `stationId` | `"station-rivier"` | Station identifier, distinct from the slug |
| Content `id` | `"5b961af1-c305-4a1e-aed4-b3dfdc72be09"` | UUID of a published record |
| `timezone` | `"Europe/Amsterdam"` | IANA timezone for calendar interpretation |
| `fromDate` / `localDate` | `"2026-10-05"` | Calendar date, not a UTC instant |
| Listener `observedAt` | `"2026-10-05T08:00:00.000Z"` | ISO 8601 timestamp |
| Ingest `observedAt` | `1791187200000` | Unix timestamp in **milliseconds**, not seconds |
| `durationSeconds` | `210` or `null` | Reported track duration in seconds, or unknown |
| `nextCursor` | `null` on the last page | Otherwise an opaque value returned by the endpoint |
| Broadcast `nature` | `"live"` | `live`, `prerecorded`, or `repeat` |
| Slot `weekday` | `1` | Day of the week, from `0` for Sunday to `6` for Saturday |
| Slot `startTime` | `"07:00"` | Wall-clock time in the slot's `timezone` |

## Published content fields

Station administrators define content types. First read `…/schemas`, then match a record's `type` and `schemaVersion` to the definition. Use field **keys** to look up values and field **labels** for display.

An illustrative schema field:

```json theme={null}
{
  "key": "reading_minutes",
  "label": "Reading time",
  "kind": "number",
  "required": false,
  "min": 0,
  "max": 60
}
```

The corresponding published values can mix types:

```json theme={null}
{
  "headline": "Riverside festival opens this weekend",
  "featured": true,
  "reading_minutes": 2,
  "category": "local",
  "event_at": "2026-10-10T10:00:00.000Z"
}
```

These are examples of custom fields, not universal RadioTools fields. The `values` object is intentionally flexible; the station's published schema determines its keys and semantics.

| Field kind | Rendering guidance |
| - | - |
| `text` | Render text and respect `maxLength` when accepting input elsewhere |
| `rich_text` | Use the published rich-text structure; do not assume arbitrary strings are trusted HTML |
| `number` | Preserve numeric values; check `min` and `max` when supplied |
| `boolean` | Preserve true/false; absence is separate from false |
| `datetime` | Interpret the published timestamp and format for the intended timezone |
| `choices` | Match stable choice keys to the published choice labels; when `multiple` is `true`, the value is an array of keys |
| `media` | Resolve published media projections; use their version URLs for bytes |
| `content` | Resolve references according to `targetType`; only published records are available |
| `group` | Render the nested field definitions and respect repeated-entry limits when supplied |

The editorial `document` is a separate ordered block structure. Its blocks include text, headings, quotes, images, galleries, audio, video, embeds, and related records. Use each block's discriminator `type`; the operation schema describes its exact fields. Private and system metadata are excluded from listener delivery.

## Empty and unavailable states

| Field or response | What it means | Client behavior |
| - | - | - |
| `resources.weather: null` | Resource disabled or unavailable, including missing entitlement | Do not request the resource; hide or explain the unavailable feature |
| `resources.realtime: null` | Realtime feed switched off | Poll the HTTP resources instead |
| `profile` value `null` | The station has not set that profile detail | Omit it from your about or contact page |
| Media `variants.card: null` | That image rendition is not available | Fall back to another rendition or the original `url` |
| `records: []`, `types: []`, or `items: []` | Successful read with no matching public entries | Show an empty state |
| `broadcast: null` | No current public broadcast | Show no current program |
| `track: null` with freshness `empty` | No reported track observation | Show no reported track |
| Freshness `stale` | Observation exceeds its freshness threshold | Label the timestamp/age rather than presenting it as current |
| Weather `current: null` | No current reading available | Show unavailable weather; inspect freshness and forecast arrays separately |
| Traffic `incidents: []` with freshness `fresh` | No incidents reported on watched roads | Show clear traffic for that coverage |
| `404 NOT_FOUND` | Station/resource missing, unpublished, offline, disabled, or otherwise unavailable | Stop showing the previous station's projection |
| `404 MODULE_DISABLED` | The station switched off the module behind this resource | Hide the feature until the module is back |

Reported tracks come from external automation. A fresh observation indicates recent metadata, not a guarantee that audio is audible. `elapsedSeconds` and `endsAt` are derived at response time; both are `null` when duration is unknown or the observation is not playing.

## Weather and traffic units

Weather temperatures use **degrees Celsius**, wind speeds use **kilometers per hour**, wind direction uses **degrees**, and precipitation amounts use **millimeters**. `precipitationChance` is a fraction from **0 to 1**: `0.2` means **20%**, not 0.2%.

Traffic incidents can report a `cause`, such as `accident` or `roadworks`, and a `closure`, such as `road`, `exit`, or `lane`; both are `null` when unknown or not applicable. Traffic distances (`lengthMeters`, `jamDistanceMeters`) use **meters**; delays and freshness ages use **seconds**. A nullable incident length or delay means unknown, not zero. Country codes in weather coverage use lowercase values such as `"nl"`.

See [Requests and response handling](/radiotools/api-reference/response-handling) for conditional reads and pagination, or select an HTTP operation to inspect the complete request and response examples.


## Related topics

- [GraphQL schema reference](/radiotools/api-reference/graphql-reference.md)
- [Errors and versioning](/radiotools/api-reference/errors-and-versioning.md)
- [Requests and response handling](/radiotools/api-reference/response-handling.md)
- [Public delivery](/radiotools/api-reference/public-delivery.md)
- [API overview](/radiotools/api-reference/overview.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.