WanduraDocsBeta
BetaThese docs are in beta and change often. Something wrong, unclear or missing? Tell us.
You are reading an older version of these docs: v1 · Go to the latest (v2)
Change history

History: API reference

Every change to this page, newest first. Expand an entry to see what changed.

← API reference

  1. 4 Oct 2026 · +2 −0 lines
    Show changes
    ⋯
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
      | `POST` | `/api/delivery/v1/playback` | `playback` | [Request playback](playback.md) |
    + | `GET` | `/api/delivery/v1/series` | `metadata:read` | [List series for metadata sync](series-list.md) |
    + | `GET` | `/api/delivery/v1/series/{code}` | `metadata:read` | [Get series metadata](series-get.md) |
      | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](videos-list.md) |
      | `GET` | `/api/delivery/v1/videos/{id}` | `videos:read` | [One open video with a fresh playback link](videos-get.md) |
    ⋯
  2. 2 Oct 2026 · +25 −102 lines
    Show changes
      # API reference
      
    - The Wandura Delivery API lets your backend read the films you are licensed for, request playback for one episode at a time, and sync approved ad creatives. This section documents each endpoint. For the integration flow, start with the [Quickstart](../quickstart.md), [Authentication](../authentication.md) and [Playback](../concepts/playback.md).
    + The reference documents each endpoint of the Wandura Delivery API: parameters, fields, examples, headers and errors, generated from the OpenAPI description. The rules shared by every endpoint — authentication, pagination, ticket lifetime, freshness, retries, rate limits, versioning — are on [Canonical API behaviour](behaviour.md).
      
    - ## Base URL
    + ## Base URL {#base-url}
      
      ```
    ⋯
      ```
      
    - Always call `www.wandura.ai`. The bare domain `wandura.ai` answers every request with a `308` redirect to `www`, and some HTTP clients drop the body or headers of a `POST` when they follow a redirect.
    + Always `www.wandura.ai`. The bare domain answers `308` to `www`, and some HTTP clients drop the body or headers of a `POST` when they follow a redirect.
      
    - ## Endpoints
    + ## Endpoints {#endpoints}
      
      | Method | Path | Scope | Page |
      |---|---|---|---|
      | `GET` | `/api/delivery/v1/catalog` | `metadata:read` | [List licensed catalog](catalog.md) |
    - | `GET` | `/api/delivery/v1/config` | `any` | Get configuration |
    + | `GET` | `/api/delivery/v1/config` | `any` | [Get configuration](config.md) |
      | `GET` | `/api/delivery/v1/creatives` | `creatives:export` | [List creatives](creatives-list.md) |
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
      | `POST` | `/api/delivery/v1/playback` | `playback` | [Request playback](playback.md) |
    - | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](../open-video.md) |
    - | `GET` | `/api/delivery/v1/videos/{id}` | `videos:read` | One open video with a fresh playback link |
    - 
    - `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
    + | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](videos-list.md) |
    + | `GET` | `/api/delivery/v1/videos/{id}` | `videos:read` | [One open video with a fresh playback link](videos-get.md) |
      
    - Any other path under `/api/delivery/v1/`, with any method, returns `404` with a flat JSON body and `error_code` `not_found`. If you get it on a path you expected to work, check the path for a typo.
    + Any other path under `/api/delivery/v1/` answers `404` `not_found`; a real path with the wrong method answers `405`.
      
      Machine-readable contract: the OpenAPI 3 description of every endpoint above is published at [https://docs.wandura.ai/developers/openapi/delivery-v1.json](https://docs.wandura.ai/developers/openapi/delivery-v1.json). Use it to generate a client or to validate your integration. It changes only additively within `/v1`.
      
    - ## Server-to-server only
    - 
    - Call these endpoints from your backend, never from a browser or a mobile app. They do not send CORS headers, and your API key must never ship inside a client.
    - 
    - ## Authentication
    - 
    - Send your API key as a bearer token on every request:
    - 
    - ```
    - Authorization: Bearer <your API key>
    - ```
    - 
    - Each key belongs to one organisation and carries one or more scopes. A missing, unknown or revoked key gets `401`. A valid key that lacks the endpoint's scope gets `403`.
    + ## Server-to-server only {#server-to-server-only}
      
    - | Scope | Grants | How you get it |
    - |---|---|---|
    - | `metadata:read` | [List licensed catalog](catalog.md) | Create it yourself in the partner portal |
    - | `creatives:export` | [List creatives](creatives-list.md), [Get a creative](creatives-get.md) | Create it yourself in the partner portal |
    - | `webhooks:manage` | Not used by any endpoint yet | Create it yourself in the partner portal |
    - | `playback` | [Request playback](playback.md) | Create it yourself in the partner portal (**Stream films in an app**) |
    + Call these endpoints from your backend, never from a browser or an app: they send no CORS headers, and a key inside a client can be extracted. See [Security](../concepts/security.md).
      
    - Organisation members with the **Admin** or **Developer** role create, rotate and revoke keys on the **Developers** page of the partner portal. The full key is shown once, at creation. This includes keys with the `playback` scope: if one leaks, anyone can stream your licensed films, so revoke it immediately. See [Authentication](../authentication.md).
    + ## Requests and responses {#requests-and-responses}
      
    - ## Versioning
    + - Bodies are JSON. Send `Content-Type: application/json` on `POST`.
    + - Film, episode, creative and video IDs are UUID strings.
    + - Times are ISO 8601 UTC strings (`expires_at`), except in the creatives feed, which uses Unix epoch seconds.
    + - Every response carries `Wandura-Version` and `Wandura-API-Status: beta`.
    + - Ignore fields, values and error codes you do not recognise: see [Versioning and API evolution](../concepts/versioning.md#tolerant-reader).
      
    - The API version is part of the path (`/v1`). Within a version, Wandura may add new response fields and new error codes without notice. Ignore fields you do not recognise, and always keep a default branch for unknown error codes. What counts as breaking, and how long old versions are supported: [Versioning and deprecation](../concepts/versioning.md).
    + ## Where the shared rules live {#shared-rules}
      
    - Creative records also carry a `schema_version` field, currently `1`. Additive fields do not change it.
    + | Topic | Page |
    + |---|---|
    + | Keys, scopes | [Authentication](../authentication.md) |
    + | Pagination, tickets, freshness, retries, rate limits, versioning | [Canonical API behaviour](behaviour.md) |
    + | Every error, per endpoint | [Errors](../concepts/errors.md) |
    + | Rate limits under load | [Rate limits](../concepts/rate-limits.md) |
    + | Dated versions, deprecations | [Versioning and API evolution](../concepts/versioning.md) |
      
      ### Beta {#beta}
      
    - The API is in **beta**. Every response from `/v1` carries the header `Wandura-API-Status: beta`. During the beta Wandura may still change behaviour inside `/v1`; changes are listed in the **Changelog** (link at the bottom of every page). Spotted something wrong or missing? Use **Send feedback** at the top of any docs page.
    - 
    - ## Requests and responses
    - 
    - - Request and response bodies are JSON. Send `Content-Type: application/json` on `POST`.
    - - Film, episode and creative IDs are UUID strings.
    - - Playback returns `expires_at` as an ISO 8601 timestamp in UTC. The creatives endpoints return timestamps as Unix epoch seconds.
    - - The creatives endpoints send `Cache-Control: no-store`. Do not cache their responses in shared caches.
    - 
    - ## Pagination
    - 
    - Only [List creatives](creatives-list.md) is paginated. It uses an opaque `cursor` and returns `next_cursor` until there are no more records. [List licensed catalog](catalog.md) returns your whole catalog in one response.
    - 
    - ## Errors
    - 
    - The API uses two error formats. The catalog and playback endpoints return a flat object:
    - 
    - ```json
    - {
    -   "error": "Episode not found or not ready to stream",
    -   "error_code": "not_ready"
    - }
    - ```
    - 
    - | Field | Type | Description |
    - |---|---|---|
    - | `error` | string | Human-readable message. Do not parse it. One exception: a catalog `403` has no `error_code`, and its `error` is exactly `org_suspended` when your organisation is suspended. See [List licensed catalog](catalog.md#errors). |
    - | `error_code` | string | Machine-readable code. Branch on this. Absent on some errors, for example `401`. |
    - | `reason` | string | Present with `not_entitled`. The detailed reason, for logs and support. |
    - 
    - The creatives endpoints wrap every response, success or error, in an envelope with a numeric `code`:
    - 
    - ```json
    - {
    -   "code": 4011,
    -   "message": "Invalid or revoked API key",
    -   "server_time": 1790679032
    - }
    - ```
    - 
    - | Field | Type | Description |
    - |---|---|---|
    - | `code` | integer | `0` on success. A four-digit error code otherwise. |
    - | `message` | string | `"ok"` on success, a human-readable message otherwise. |
    - | `data` | object | Present on success only. |
    - | `server_time` | integer | Server time in Unix epoch seconds. |
    - 
    - Each endpoint page lists its errors. For retry guidance and the full list, see [Errors](../concepts/errors.md).
    - 
    - ## Rate limits
    - 
    - Each organisation has an abuse ceiling per endpoint group, counted over a fixed 60-second window: 10,800 playback requests (about 180 tickets per second), 3,000 catalog requests and 3,000 creatives requests, each on its own counter. Reaching a ceiling usually means a runaway loop. Wandura can raise any of them for your organisation on request, effective within about a minute. The limit headers below appear only on `429` responses.
    - 
    - When you reach it, every endpoint answers `429` with a flat body, including the creatives endpoints:
    - 
    - ```json
    - {
    -   "error": "Too many playback requests for this account. This is an abuse ceiling, not a quota — if a normal integration reaches it, contact us and it will be raised.",
    -   "error_code": "rate_limited"
    - }
    - ```
    - 
    - | Header | Description |
    - |---|---|
    - | `Retry-After` | Seconds until the current window resets. |
    - | `X-RateLimit-Limit` | Requests allowed per window for this endpoint group. |
    - | `X-RateLimit-Window` | Window length in seconds. |
    - 
    - Wait for `Retry-After` before retrying. See [Rate limits](../concepts/rate-limits.md#limits).
    + The API is in **beta**. During the beta Wandura may still change behaviour inside `/v1`, under the [beta rule](../concepts/versioning.md#beta); every change is in the changelog.
  3. 2 Oct 2026 · +1 −0 lines
    Show changes
    ⋯
      | `POST` | `/api/delivery/v1/playback` | `playback` | [Request playback](playback.md) |
      | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](../open-video.md) |
    + | `GET` | `/api/delivery/v1/videos/{id}` | `videos:read` | One open video with a fresh playback link |
      
      `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
    ⋯
  4. 2 Oct 2026 · +2 −1 lines
    Show changes
    ⋯
      |---|---|---|---|
      | `GET` | `/api/delivery/v1/catalog` | `metadata:read` | [List licensed catalog](catalog.md) |
    + | `GET` | `/api/delivery/v1/config` | `any` | Get configuration |
      | `GET` | `/api/delivery/v1/creatives` | `creatives:export` | [List creatives](creatives-list.md) |
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
    ⋯
      | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](../open-video.md) |
      
    - **Rolling out:** `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
    + `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
      
      Any other path under `/api/delivery/v1/`, with any method, returns `404` with a flat JSON body and `error_code` `not_found`. If you get it on a path you expected to work, check the path for a typo.
    ⋯
  5. 2 Oct 2026 · +4 −1 lines
    Show changes
    ⋯
      |---|---|---|---|
      | `GET` | `/api/delivery/v1/catalog` | `metadata:read` | [List licensed catalog](catalog.md) |
    - | `POST` | `/api/delivery/v1/playback` | `playback` | [Request playback](playback.md) |
      | `GET` | `/api/delivery/v1/creatives` | `creatives:export` | [List creatives](creatives-list.md) |
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
    + | `POST` | `/api/delivery/v1/playback` | `playback` | [Request playback](playback.md) |
    + | `GET` | `/api/delivery/v1/videos` | `videos:read` | [List open videos](../open-video.md) |
      
      **Rolling out:** `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
    ⋯
      Any other path under `/api/delivery/v1/`, with any method, returns `404` with a flat JSON body and `error_code` `not_found`. If you get it on a path you expected to work, check the path for a typo.
      
    + Machine-readable contract: the OpenAPI 3 description of every endpoint above is published at [https://docs.wandura.ai/developers/openapi/delivery-v1.json](https://docs.wandura.ai/developers/openapi/delivery-v1.json). Use it to generate a client or to validate your integration. It changes only additively within `/v1`.
    + 
      ## Server-to-server only
      
    ⋯
  6. 2 Oct 2026 · +2 −0 lines
    Show changes
    ⋯
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
      
    + **Rolling out:** `GET /api/delivery/v1/config` — [Get configuration](config.md), callable with any valid key.
    + 
      Any other path under `/api/delivery/v1/`, with any method, returns `404` with a flat JSON body and `error_code` `not_found`. If you get it on a path you expected to work, check the path for a typo.
      
    ⋯
  7. 1 Oct 2026 · +3 −3 lines
    Show changes
    ⋯
      | `creatives:export` | [List creatives](creatives-list.md), [Get a creative](creatives-get.md) | Create it yourself in the partner portal |
      | `webhooks:manage` | Not used by any endpoint yet | Create it yourself in the partner portal |
    - | `playback` | [Request playback](playback.md) | Issued by Wandura only |
    + | `playback` | [Request playback](playback.md) | Create it yourself in the partner portal (**Stream films in an app**) |
      
    - Organisation members with the **Admin** or **Developer** role create, rotate and revoke keys on the **Developers** page of the partner portal. The full key is shown once, at creation. Keys with the `playback` scope are managed by Wandura and cannot be rotated from the portal. See [Authentication](../authentication.md).
    + Organisation members with the **Admin** or **Developer** role create, rotate and revoke keys on the **Developers** page of the partner portal. The full key is shown once, at creation. This includes keys with the `playback` scope: if one leaks, anyone can stream your licensed films, so revoke it immediately. See [Authentication](../authentication.md).
      
      ## Versioning
    ⋯
      ## Rate limits
      
    - Each organisation has an abuse ceiling per endpoint group, counted over a fixed 60-second window: 30,000 playback requests, and 3,000 requests shared by the catalog and creatives endpoints. The ceiling sits far above normal traffic, so reaching it usually means a runaway loop. Wandura can raise it on request. The limit headers below appear only on `429` responses.
    + Each organisation has an abuse ceiling per endpoint group, counted over a fixed 60-second window: 10,800 playback requests (about 180 tickets per second), 3,000 catalog requests and 3,000 creatives requests, each on its own counter. Reaching a ceiling usually means a runaway loop. Wandura can raise any of them for your organisation on request, effective within about a minute. The limit headers below appear only on `429` responses.
      
      When you reach it, every endpoint answers `429` with a flat body, including the creatives endpoints:
    ⋯
  8. 1 Oct 2026 · +5 −3 lines
    Show changes
    ⋯
      | `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Get a creative](creatives-get.md) |
      
    + Any other path under `/api/delivery/v1/`, with any method, returns `404` with a flat JSON body and `error_code` `not_found`. If you get it on a path you expected to work, check the path for a typo.
    + 
      ## Server-to-server only
      
    ⋯
      | Field | Type | Description |
      |---|---|---|
    - | `error` | string | Human-readable message. Do not parse it. |
    + | `error` | string | Human-readable message. Do not parse it. One exception: a catalog `403` has no `error_code`, and its `error` is exactly `org_suspended` when your organisation is suspended. See [List licensed catalog](catalog.md#errors). |
      | `error_code` | string | Machine-readable code. Branch on this. Absent on some errors, for example `401`. |
      | `reason` | string | Present with `not_entitled`. The detailed reason, for logs and support. |
    ⋯
      ## Rate limits
      
    - Each organisation has an abuse ceiling per endpoint group, counted over a fixed time window. The ceiling sits far above normal traffic, so reaching it usually means a runaway loop. The catalog and creatives endpoints share one counter; playback has its own.
    + Each organisation has an abuse ceiling per endpoint group, counted over a fixed 60-second window: 30,000 playback requests, and 3,000 requests shared by the catalog and creatives endpoints. The ceiling sits far above normal traffic, so reaching it usually means a runaway loop. Wandura can raise it on request. The limit headers below appear only on `429` responses.
      
      When you reach it, every endpoint answers `429` with a flat body, including the creatives endpoints:
    ⋯
      | `X-RateLimit-Window` | Window length in seconds. |
      
    - Wait for `Retry-After` before retrying. See [Rate limits](../concepts/rate-limits.md).
    + Wait for `Retry-After` before retrying. See [Rate limits](../concepts/rate-limits.md#limits).
  9. 1 Oct 2026 · +1 −1 lines
    Show changes
    ⋯
      ## Versioning
      
    - The API version is part of the path (`/v1`). Within a version, Wandura may add new response fields and new error codes without notice. Ignore fields you do not recognise, and always keep a default branch for unknown error codes.
    + The API version is part of the path (`/v1`). Within a version, Wandura may add new response fields and new error codes without notice. Ignore fields you do not recognise, and always keep a default branch for unknown error codes. What counts as breaking, and how long old versions are supported: [Versioning and deprecation](../concepts/versioning.md).
      
      Creative records also carry a `schema_version` field, currently `1`. Additive fields do not change it.
    ⋯
  10. 1 Oct 2026 · +4 −0 lines
    Show changes
    ⋯
      Creative records also carry a `schema_version` field, currently `1`. Additive fields do not change it.
      
    + ### Beta {#beta}
    + 
    + The API is in **beta**. Every response from `/v1` carries the header `Wandura-API-Status: beta`. During the beta Wandura may still change behaviour inside `/v1`; changes are listed in the **Changelog** (link at the bottom of every page). Spotted something wrong or missing? Use **Send feedback** at the top of any docs page.
    + 
      ## Requests and responses
      
    ⋯
  11. 29 Sept 2026 · Page created
↑↓ selectEnter openEsc close

Send feedback

Your message goes straight to the Wandura team. It includes the address of this page.

0 / 4000