> ## 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.

# Errors and versioning

> ErrorResponse shape, stable codes, pagination, and public API evolution.

## Error shape

Most routes return:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request contains invalid parameters or input.",
    "requestId": "28e5d867-1f87-4ca7-bca9-4ebc09b36ba3",
    "issues": [
      { "path": "limit", "message": "Use a value between 1 and 50." }
    ]
  }
}
```

Every response includes header **`x-request-id`** — include it when reporting problems to your station admin or vendor support.

| Code | HTTP | When |
| - | - | - |
| `UNAUTHENTICATED` | 401 | Missing or invalid token |
| `FORBIDDEN` | 403 | Authenticated but not permitted |
| `VALIDATION_ERROR` | 400 | Invalid input or filter |
| `NOT_FOUND` | 404 | Missing resource or hidden cross-tenant object |
| `MODULE_DISABLED` | 404 | The station has switched off the module behind this resource |
| `METHOD_NOT_ALLOWED` | 405 | Wrong HTTP method |
| `REVISION_CONFLICT` | 409 | Stale `expectedRevision` |
| `IDEMPOTENCY_CONFLICT` | 409 | Idempotency key reused with different payload |
| `RATE_LIMITED` | 429 | Throttled |
| `PROVIDER_UNAVAILABLE` | 503 | Upstream dependency down |
| `INTERNAL_ERROR` | 500 | Unexpected server error |

Playback ingest may return `{ "error": "string" }` for encoder compatibility.

For example, an invalid ingest request can return:

```json theme={null}
{ "error": "The request contains invalid parameters or input." }
```

Examples are illustrative; message wording and validation paths can vary. Listener clients should branch on `error.code`, preserve the request ID for diagnosis, and display a suitable message. `issues` is optional. Each issue has a `path` and `message`, and may add a machine-readable `code`, a short `suggestion` you can show, and `retryAfter` in seconds when the problem is temporary. Playback clients must handle the legacy string instead of expecting `error.code`.

## Recover from errors

| Response | Recovery |
| - | - |
| `400` | Correct the documented input types, bounds, date window, or filters before retrying |
| `401` | Check the credential's station, expiry, revocation, and required scope |
| `403` | Check the operation's required permissions or configured provider |
| `404` | Refresh station discovery; stop displaying stale data from the unavailable resource |
| `405` | Use the endpoint's documented method |
| `409` | Resolve the indicated revision or idempotency conflict; an unchanged request will still conflict |
| `429` | Reduce frequency and use a delayed retry; honor `Retry-After` when present |
| `503` | Retry with increasing delays; show an unavailable state while the provider is down |

Do not retry invalid input or invalid credentials in a tight loop. Use the operation's response list to see which statuses apply; this table is the shared error vocabulary, not a guarantee that every route returns every code. Public media range requests can also return `416` when the requested range cannot be satisfied.

## Contract version

Listener JSON projections include `contractVersion: 1`. Treat unknown fields as forward-compatible unless the version integer changes. Calendar text, media bytes, and playback ingest use their own documented response shapes.

Preserve exact enum values and check optional/nullable fields independently. A successful response with an empty array or a nullable resource is not an error. See [Field types and empty states](/radiotools/api-reference/field-types).

## Pagination and filters

Use documented cursors, sorts, and filters only. Content lists sort by `publishedAt` or `updatedAt` and filter on text and choice delivery fields. Do not assume you can sort or filter other fields.

## GraphQL and the realtime feed

Public GraphQL and the realtime feed complement REST. GraphQL requires the same **tenant token** (`listener:read`) as JSON reads; the realtime feed is anonymous. REST entry points remain in OpenAPI; typed helpers live in the [SDKs](/radiotools/api-reference/sdks).

Each operation page in the sidebar documents route-specific validation and response schemas.

## Choose a recovery action

| Response | Consumer action |
| - | - |
| 400 | Fix the reported input; resending it unchanged will not help |
| 401 or 403 | Check the credential and scope or ask an administrator to restore access |
| 404 | Check the station and resource, then public-offline state and API switches |
| 409 | Read current state and rebuild the intended change with the current revision |
| 429 | Respect the response's retry guidance before trying again |
| 503 or a connection failure | Retry with bounded backoff and preserve the identity of the intended operation |

For an uncertain mutation outcome, check current state before repeating the operation. Retain the same idempotency identity where the operation supports it. Include the request ID, route, HTTP status, and approximate time in support reports, with tokens and confidential payload fields removed.


## Related topics

- [SDKs](/radiotools/api-reference/sdks/index.md)
- [GraphQL](/radiotools/api-reference/graphql.md)
- [Other languages](/radiotools/api-reference/sdks/other-languages.md)
- [TypeScript SDK](/radiotools/api-reference/sdks/typescript.md)
- [API overview](/radiotools/api-reference/overview.md)


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