Bản lưu ngày / Snapshot of 2026-10-17 · Xem bản mới nhất / See the latest version
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: Errors

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

← Errors

  1. 4 Oct 2026 · +32 −0 lines
    Show changes
    ⋯
      | 503 | `service_unavailable` | Wandura could not read the catalog in time (`Could not read the catalog in time — retry`). | After `Retry-After` | — | Retry. **Never** treat it as an empty catalog. |
      
    + ### List series {#series-errors}
    + 
    + `GET /api/delivery/v1/series`
    + 
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | `unsupported_version` (flat) | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | `4010` | No `Authorization: Bearer` header. | No | Fix the request. |
    + | 401 | `4011` | Key unknown or revoked. | No | Check the key. |
    + | 403 | `4030` | The key lacks `metadata:read`. | No | Use a key with that scope. |
    + | 403 | `4031` | Your organisation is suspended. | No | Contact Wandura. |
    + | 422 | `4220` | `limit` is not 1–100, `updated_since` is not epoch seconds, or `cursor` is not a value this endpoint returned. | No | Fix the request; restart from your last checkpoint. |
    + | 429 | `rate_limited` (flat) | Catalog limit reached (shared with the catalog). | After `Retry-After` | Wait; sync less often. |
    + | 503 | `5030` | The list is temporarily unavailable. | Backoff | Retry; keep your checkpoint. |
    + | 503 | `5031` | Wandura could not check the key in time. | Backoff | Retry. Do not rotate the key. |
    + 
    + ### Get series metadata {#series-get-errors}
    + 
    + `GET /api/delivery/v1/series/{code}`
    + 
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | `unsupported_version` (flat) | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | `4010` | No `Authorization: Bearer` header. | No | Fix the request. |
    + | 401 | `4011` | Key unknown or revoked. | No | Check the key. |
    + | 403 | `4030` | The key lacks `metadata:read`. | No | Use a key with that scope. |
    + | 403 | `4031` | Your organisation is suspended. | No | Contact Wandura. |
    + | 404 | `4040` | No such series, or your organisation may not stream it (the same answer on purpose). | No | Stop showing it; check the list. |
    + | 429 | `rate_limited` (flat) | Catalog limit reached (shared with the catalog). | After `Retry-After` | Wait. |
    + | 503 | `5030` | The series is temporarily unavailable. | Backoff | Retry. |
    + | 503 | `5031` | Wandura could not check the key in time. | Backoff | Retry. |
    + 
      ### Playback {#playback-errors}
      
    ⋯
  2. 2 Oct 2026 · +3 −5 lines
    Show changes
    ⋯
      ### Request id {#request-id}
      
    - > **Rolling out.** Every response carries a `Wandura-Request-Id` header (for example `req_01J9Z3W2N8V4K7D5QX6T0B1C2M`), and every error body, flat or envelope, a `request_id` field with the same value. Log it, and quote it when you contact support: it finds the exact request in Wandura's logs.
    - 
    - Until it is live, quote the endpoint, the time in UTC to the second, the status, the code and your key prefix.
    + Every response carries a `Wandura-Request-Id` header (for example `req_01J9Z3W2N8V4K7D5QX6T0B1C2M`), and every JSON error body, flat or envelope, a `request_id` field with the same value. Log it, and quote it when you contact support: it finds the exact request in Wandura's logs.
      
      ## Handle errors by code {#handle-by-code}
    ⋯
      | 429 | `rate_limited` | Playback limit reached for every item. With `"reason": "prefetch_shed"`: prefetch is paused near the limit. | After `Retry-After` | Busy (play); nothing (prefetch) | Retry plays; drop prefetches. See [Rate limits](rate-limits.md). |
      | 503 | `service_unavailable` | Wandura could not check the key in time. | After `Retry-After` | Busy | Retry. Do not rotate the key. |
    - | 500 | none (rare) | An unexpected error. | Backoff | Busy | Retry once; report it with the time. |
    + | 500 | none (rare) | An unexpected error. The JSON body carries `request_id`. | Backoff | Busy | Retry once; report it with the request id. |
      
      **Per ticket** (top level for a single episode, or one item of a batch)
    ⋯
      > **Do not take irreversible steps on one answer.** Before you stop selling a film or refund viewers because of `not_entitled` or `not_ready`, confirm it with your next catalog sync: a withdrawn film disappears from the catalog.
      
    - > **Rolling out.** If Wandura cannot check your licence or the episode in time while issuing a ticket, it answers `503` `service_unavailable` (`Could not check the licence or episode right now — retry`) with `Retry-After`, never `404` or `403`. Keep selling, and retry.
    + If Wandura cannot check your licence or the episode in time while issuing a ticket, it answers `503` `service_unavailable` (`Could not check the licence or episode right now — retry`) with `Retry-After`, never `404` or `403`. Keep selling, and retry.
      
      #### `not_entitled` reasons {#not-entitled-reasons}
    ⋯
  3. 2 Oct 2026 · +180 −72 lines
    Show changes
      # Errors
      
    - The Delivery API uses standard HTTP status codes and adds a machine-readable code to most errors. The catalog and playback endpoints return a flat error object with an `error_code` string; the creatives endpoints return an envelope with a numeric `code`. This page lists every error each endpoint returns today, what it means and what to do.
    + > **TL;DR** — Branch on `error_code` (creatives: the numeric `code`), never on the message. Keep a default branch: an unknown code is handled by its HTTP status class (`429` and `5xx` retry, other `4xx` do not). This page lists every status and code each endpoint returns, with what your app shows and what your backend does. When to retry, and how: the [retry policy](../reference/behaviour.md#retries).
      
    - ## Error formats
    + ## Error formats {#error-formats}
      
    - ### Catalog and playback
    + ### Flat format {#flat-format}
      
    + Catalog, playback, configuration and open video use a flat object:
    + 
      ```json
      {
    ⋯
      | Field | Type | Description |
      |---|---|---|
    - | `error` | string | Human-readable message. Log it, but do not parse it, except for the catalog `403` below. |
    - | `error_code` | string | Machine-readable code. Branch on this. Absent on some errors, listed below as "none". |
    - | `reason` | string | Only with `not_entitled`: the detailed reason, for logs and support. |
    - | `fields` | array of strings | Only with `invalid_device_info`: which device values were rejected. |
    - | `protection` | string | Only with `sdk_required`: the protection level of the episode. |
    + | `error` | string | A message for your logs. Do not show it to viewers and do not parse it, except where a row below says the code is in `error`. |
    + | `error_code` | string | The machine-readable code. Branch on it. Absent on a few errors (shown as **none** below). |
    + | `reason` | string | With `not_entitled`, and with `429` `prefetch_shed`: the detail. |
    + | `fields` | array of strings | With `invalid_device_info`: the device values that were rejected. |
    + | `protection` | string | With `sdk_required`: the protection level of the episode. |
    + | `supported_versions`, `latest_version`, `upgrade_to` | | With `unsupported_version`: what you can send instead. |
      
    - ### Creatives
    + A few `4xx` answers carry no `error_code` and put a stable code in `error` instead: `org_suspended`, `app_not_registered`, `collection_not_found` and `video_not_found`. Compare the whole string.
      
    + ### Creatives envelope {#creatives-envelope}
    + 
    + The creatives endpoints wrap errors in an envelope with a numeric `code`. Errors have **no `data`** field:
    + 
      ```json
      {
    ⋯
      ```
      
    - | Field | Type | Description |
    - |---|---|---|
    - | `code` | integer | `0` on success, a four-digit error code otherwise. The first three digits are the HTTP status. |
    - | `message` | string | Human-readable message. Do not parse it. |
    - | `server_time` | integer | Server time in Unix epoch seconds. |
    + `code` is four digits: the first three are the HTTP status. Two creatives answers use the **flat** format instead: `429` `rate_limited` and `400` `unsupported_version`.
      
    - The one exception is `429`: the creatives endpoints return it in the flat format, with `error_code` `rate_limited`. See [Rate limits](rate-limits.md).
    + ### Request id {#request-id}
      
    - ## Handle errors by code
    + > **Rolling out.** Every response carries a `Wandura-Request-Id` header (for example `req_01J9Z3W2N8V4K7D5QX6T0B1C2M`), and every error body, flat or envelope, a `request_id` field with the same value. Log it, and quote it when you contact support: it finds the exact request in Wandura's logs.
      
    - - Branch on `error_code` (or `code` for creatives), not on the HTTP status alone. Several different situations share a status.
    - - Always keep a default branch. Wandura may add new codes within `v1`, and an app without a default branch shows a blank screen when one appears.
    - - Never show `error` or `message` text to viewers. Map codes to your own copy.
    + Until it is live, quote the endpoint, the time in UTC to the second, the status, the code and your key prefix.
      
    - ## Catalog errors
    + ## Handle errors by code {#handle-by-code}
      
    - `GET /api/delivery/v1/catalog`
    + | You received | Do |
    + |---|---|
    + | A code listed on this page | Follow its row. |
    + | An unknown `error_code` with `429` | Wait `Retry-After`, then retry. |
    + | An unknown `error_code` with another `4xx` | Do not retry. Show a generic error and alert your engineers. |
    + | An unknown `error_code` with a `5xx` | Retry with backoff, like `503`. |
    + | No body, or a body that is not JSON | Decide by status class, the same way. |
      
    - | Status | `error_code` | Message | Meaning | What to do |
    + New codes can appear within `v1` at any time; an app without a default branch shows a blank screen when one does. Never show `error` or `message` to viewers: map codes to your own text.
    + 
    + ### `Retry-After` {#retry-after}
    + 
    + Sent with every `429`, and with the `503`s marked "after `Retry-After`" below. Never retry sooner. `503` `not_ready`, creatives `503`s, `502` and `500` carry none: use backoff.
    + 
    + ## Messages for viewers {#viewer-messages}
    + 
    + The "Your app shows" column below uses these four messages. Use your own wording.
    + 
    + | Message | When |
    + |---|---|
    + | **Unavailable** — "This title is no longer available" | The licence is not active. |
    + | **Not yet** — "Not available yet" | The episode is not playable right now. |
    + | **Busy** — "Busy, try again in a moment" | Retried and still failing temporarily. |
    + | **Broken** — "Couldn't load this episode" | A problem in your integration. Alert your engineers. |
    + 
    + ## Every endpoint {#all-endpoints}
    + 
    + ### Every path {#every-path}
    + 
    + | Status | Code | When | Retry? | Do |
      |---|---|---|---|---|
    - | 401 | none | `Missing Bearer API key` | No `Authorization: Bearer` header. | Fix the request. Do not retry. |
    - | 401 | none | `Invalid or revoked API key` | The key is unknown or revoked. | Check the key. Do not retry. |
    - | 403 | none | `This API key does not have the metadata:read scope` | The key lacks the scope. | Use a key with `metadata:read`. |
    - | 403 | none | `org_suspended` | Your organisation's access is suspended. | Contact Wandura. Do not retry. |
    - | 429 | `rate_limited` | | Rate limit reached. | Wait for `Retry-After`. |
    - | 503 | `service_unavailable` | `Could not verify the API key right now — retry` | Wandura could not check the key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
    + | 404 | `not_found` | Unknown path under `/api/delivery/v1/`, any method. No `Wandura-Version` header. | No | Fix the path. |
    + | 405 | none (empty body) | A real path with the wrong method, for example `GET /playback`. The `Allow` header lists the right one. | No | Fix the method. |
      
    - ## Playback errors
    + ### Catalog {#catalog-errors}
      
    - `POST /api/delivery/v1/playback`
    + `GET /api/delivery/v1/catalog`
      
    - | Status | `error_code` | Meaning | What to do |
    - |---|---|---|---|
    - | 400 | none | The body is not valid JSON, or has neither `episode_id` nor `film_ref` with a numeric `episode_no`. | Fix the request. |
    - | 400 | `invalid_request` | Only one of `union_info` and `drm_kek` was sent. | Send both. |
    - | 400 | `invalid_device_info` | A device value looks empty or invalid, for example the string `"(null)"`. `fields` names the bad values. | Fix how your app reads the values from the Player SDK. |
    - | 401 | none | Missing, invalid or revoked API key. | Check the key. Do not retry. |
    - | 403 | none | The key lacks the `playback` scope. | Use a playback key: create one on **Developers** → **Stream films in an app**. |
    - | 403 | `not_entitled` | Your organisation is not licensed to stream this film right now. `reason` gives the detail. | Show your locked or unavailable state. Do not retry. |
    - | 404 | `not_ready` | The episode or film is unknown, not published, or not ready to stream. | Show "not available yet". Refresh your catalog. |
    - | 409 | `sdk_required` | The episode is encrypted and the request had no device values. | Resend with `union_info` and `drm_kek`. |
    - | 429 | `rate_limited` | Rate limit reached. | Wait for `Retry-After`. |
    - | 502 | none | Wandura could not prepare the stream or sign the play token. | Retry with backoff. |
    - | 503 | `not_ready` | No playable version of this episode is available right now. | Show "not available yet". Retry later. |
    - | 503 | `service_unavailable` | Wandura could not check the API key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
    - | 503 | `service_unavailable` | The video provider did not answer in time (playback only). Nothing is wrong with the episode or your key. | Retry after `Retry-After` seconds (2), with backoff. |
    + | Status | Code | When | Retry? | Your app shows | Your backend does |
    + |---|---|---|---|---|---|
    + | 400 | `invalid_request` | `limit` is not 1–200, or `cursor` was changed. | No | — | Fix the request. Restart the walk from page one. |
    + | 400 | `unsupported_version` | The `Wandura-Version` header, or your key's pin, is unknown or retired. | No | — | Send a supported version; see [Migrating versions](../guides/migrating-versions.md). |
    + | 401 | none | Header missing, or key unknown or revoked. | No | — | Check the key. Keep your previous catalog. |
    + | 403 | none | The key lacks `metadata:read`. | No | — | Use a key with that scope. |
    + | 403 | `org_suspended` (in `error`) | Your organisation is suspended. | No | — | Keep your copy, stop selling, contact Wandura. |
    + | 429 | `rate_limited` | Catalog limit reached. | After `Retry-After` | — | Wait, then find the loop. |
    + | 503 | `service_unavailable` | Wandura could not check the key in time. The key is fine. | After `Retry-After` | — | Retry. Never rotate the key for this. |
    + | 503 | `service_unavailable` | Wandura could not read the catalog in time (`Could not read the catalog in time — retry`). | After `Retry-After` | — | Retry. **Never** treat it as an empty catalog. |
      
    - ### `not_entitled` reasons
    + ### Playback {#playback-errors}
      
    - With `not_entitled`, the `reason` field says why. Log it and quote it to support, but do not build different screens for each reason: they all mean "not licensed right now", and new reasons may be added.
    + `POST /api/delivery/v1/playback`. In a batch, the request-level rows answer the whole request; the per-ticket rows come back inside `items[]`, each with its own `status` (and `retry_after` instead of the header).
      
    + **Whole request**
    + 
    + | Status | Code | When | Retry? | Your app shows | Your backend does |
    + |---|---|---|---|---|---|
    + | 400 | none | The body is not JSON, or has neither `episode_id` nor `film_ref` with a numeric `episode_no`. | No | Broken | Fix the request. |
    + | 400 | `invalid_request` | Only one of `union_info` and `drm_kek`, or a malformed batch. | No | Broken | Fix the request. |
    + | 400 | `invalid_device_info` | A device value is empty-looking, for example `"(null)"`, or under 8 characters. `fields` names it. | No | Broken | Fix how the app reads the Player SDK values. Alert. |
    + | 400 | `unsupported_version` | Unknown or retired dated version. | No | Broken | See [Migrating versions](../guides/migrating-versions.md). |
    + | 401 | none | Header missing, or key unknown or revoked. | No | Broken | Check the key. Alert. |
    + | 403 | none | The key lacks `playback`. | No | Broken | Use a playback key. |
    + | 429 | `rate_limited` | Playback limit reached for every item. With `"reason": "prefetch_shed"`: prefetch is paused near the limit. | After `Retry-After` | Busy (play); nothing (prefetch) | Retry plays; drop prefetches. See [Rate limits](rate-limits.md). |
    + | 503 | `service_unavailable` | Wandura could not check the key in time. | After `Retry-After` | Busy | Retry. Do not rotate the key. |
    + | 500 | none (rare) | An unexpected error. | Backoff | Busy | Retry once; report it with the time. |
    + 
    + **Per ticket** (top level for a single episode, or one item of a batch)
    + 
    + | Status | Code | When | Retry? | Your app shows | Your backend does |
    + |---|---|---|---|---|---|
    + | 403 | `not_entitled` | Your organisation may not stream this film right now. `reason` says why (table below). | No | Unavailable | Log `reason`. Stop selling the film once your next catalog sync confirms it is gone. |
    + | 404 | `not_ready` | The episode or film is unknown, not published or not ready. | No | Not yet | Refresh your catalog. |
    + | 409 | `sdk_required` | Encrypted episode and no device values. | No | Broken | Send `union_info` and `drm_kek`. Alert. |
    + | 429 | `rate_limited` | This item could not be admitted (batch only). `reason` `prefetch_shed` for a paused prefetch. | After `retry_after` | Nothing for a prefetch | Retry this item only. |
    + | 502 | none | The stream could not be prepared, or the play token could not be signed. | Backoff | Busy | Retry, then report. |
    + | 503 | `not_ready` | No playable version of the episode right now. No `Retry-After`. | Not now | Not yet | Try again later (next play or sync). |
    + | 503 | `service_unavailable` | The video provider did not answer in time (`The video provider did not answer in time — retry`). | After `Retry-After` (2 s) | Busy | Retry. The episode is not missing. |
    + | 503 | `service_unavailable` | The ticket could not be issued right now (`Could not issue this grant right now — retry`). | After `Retry-After` | Busy | Retry. |
    + 
    + > **Do not take irreversible steps on one answer.** Before you stop selling a film or refund viewers because of `not_entitled` or `not_ready`, confirm it with your next catalog sync: a withdrawn film disappears from the catalog.
    + 
    + > **Rolling out.** If Wandura cannot check your licence or the episode in time while issuing a ticket, it answers `503` `service_unavailable` (`Could not check the licence or episode right now — retry`) with `Retry-After`, never `404` or `403`. Keep selling, and retry.
    + 
    + #### `not_entitled` reasons {#not-entitled-reasons}
    + 
    + Log `reason` and quote it to support, but show the same screen for all of them: new reasons may be added.
    + 
      | `reason` | Meaning |
      |---|---|
    ⋯
      | `entitlement_suspended` | Your licence for this film is suspended. |
      | `streaming_disabled` | Your licence for this film does not include streaming. |
    - | `outside_window` | Today is outside your licence window for this film. |
    + | `outside_window` | Today (UTC) is outside your licence window. |
      
    - ## Creatives errors
    + ### Configuration {#config-errors}
      
    - `GET /api/delivery/v1/creatives` and `GET /api/delivery/v1/creatives/{id}`
    + `GET /api/delivery/v1/config`
      
    - | Status | `code` | Message | Meaning | What to do |
    + | Status | Code | When | Retry? | Your backend does |
      |---|---|---|---|---|
    - | 401 | 4010 | `Missing Bearer API key` | No `Authorization: Bearer` header. | Fix the request. |
    - | 401 | 4011 | `Invalid or revoked API key` | The key is unknown or revoked. | Check the key. Do not retry. |
    - | 403 | 4030 | `This API key does not have the creatives:export scope` | The key lacks the scope. | Use a key with `creatives:export`. |
    - | 403 | 4031 | `org_suspended` | Your organisation's access is suspended. | Contact Wandura. |
    - | 404 | 4040 | `Creative not found` | `GET /creatives/{id}` only. The creative does not exist, belongs to another organisation or is not approved. | Remove it from your active set. |
    - | 422 | 4220 | `limit must be an integer between 1 and 100` | List only. Bad `limit`. | Fix the request. |
    - | 422 | 4221 | `updated_since must be epoch seconds` | List only. Bad `updated_since`. | Fix the request. |
    - | 422 | 4222 | `cursor is not valid` | List only. The cursor was changed or truncated. | Restart from your last checkpoint. |
    - | 429 | none (flat body, `error_code` `rate_limited`) | | Rate limit reached. | Wait for `Retry-After`. |
    - | 503 | 5030 | `The creative feed is temporarily unavailable` | Temporary problem on Wandura's side. | Retry with backoff. |
    - | 503 | 5031 | `Could not verify the API key right now — retry` | Wandura could not check the key in time. The key is **not** wrong. | Retry with backoff. Do not rotate the key. |
    + | 400 | `unsupported_version` | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | none | Header missing, or key unknown or revoked. | No | Check the key. |
    + | 403 | `org_suspended` (in `error`) | Your organisation is suspended. | No | Contact Wandura. |
    + | 429 | `rate_limited` | Configuration limit reached. | After `Retry-After` | Read it less often: at start-up or every few hours. |
    + | 503 | `service_unavailable` | Wandura could not check the key in time. | After `Retry-After` | Retry; keep the configuration you had. |
    + | 503 | `service_unavailable` | Wandura could not read your configuration in time (`Could not read your configuration in time — retry`). | After `Retry-After` | Retry; keep the configuration you had. |
      
    - ## Retry guidance
    + ### List creatives {#creatives-errors}
      
    - | Situation | Retry? |
    - |---|---|
    - | `400`, `401`, `403`, `409`, `422` | No. Fix the request, the key or the licence first. |
    - | `404` / `not_ready` | Not immediately. Refresh your catalog and try again later. |
    - | `429` | Yes, after the number of seconds in `Retry-After`. |
    - | `502`, `503`, other `5xx` | Yes, with exponential backoff and a cap, for example 1 s, 2 s, 4 s, then give up. |
    + `GET /api/delivery/v1/creatives`
      
    - During playback, request a fresh ticket once when the Player SDK fails, then follow this table. See [Playback](playback.md#expiry). For jitter, a retry budget and sample code, see [Smooth playback under load](../guides/smooth-playback.md#retry).
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | `unsupported_version` (flat) | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | `4010` | No `Authorization: Bearer` header. | No | Fix the request. |
    + | 401 | `4011` | Key unknown or revoked. | No | Check the key. |
    + | 403 | `4030` | The key lacks `creatives:export`. | No | Use a key with that scope. |
    + | 403 | `4031` | Your organisation is suspended. | No | Contact Wandura. |
    + | 422 | `4220` | `limit` is not 1–100 (an empty `limit=` counts as 0). | No | Fix the request. |
    + | 422 | `4221` | `updated_since` is not epoch seconds. | No | Fix the request. |
    + | 422 | `4222` | `cursor` is not valid. | No | Restart from your last checkpoint. |
    + | 429 | `rate_limited` (flat) | Creatives limit reached. | After `Retry-After` | Wait; sync less often. |
    + | 503 | `5030` | The feed is temporarily unavailable. | Backoff | Retry; keep your checkpoint. |
    + | 503 | `5031` | Wandura could not check the key in time. | Backoff | Retry. Do not rotate the key. |
      
    - ## Getting help
    + ### Get a creative {#creative-get-errors}
      
    - If an error persists, contact support with the details listed in [Support](../help/support.md).
    + `GET /api/delivery/v1/creatives/{id}`
    + 
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | `unsupported_version` (flat) | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | `4010` | No `Authorization: Bearer` header. | No | Fix the request. |
    + | 401 | `4011` | Key unknown or revoked. | No | Check the key. |
    + | 403 | `4030` | The key lacks `creatives:export`. | No | Use a key with that scope. |
    + | 403 | `4031` | Your organisation is suspended. | No | Contact Wandura. |
    + | 404 | `4040` | No approved creative with this ID for your organisation (also: the ID is not a UUID). | No | Remove it from your active set. |
    + | 429 | `rate_limited` (flat) | Creatives limit reached (shared with the list). | After `Retry-After` | Wait. |
    + | 503 | `5030` | The feed is temporarily unavailable. | Backoff | Retry. |
    + | 503 | `5031` | Wandura could not check the key in time. | Backoff | Retry. |
    + 
    + ### List open videos {#videos-errors}
    + 
    + `GET /api/delivery/v1/videos`
    + 
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | none | `cursor` is not a token this endpoint issued, or `limit` is not 1–200. | No | Fix the request; restart the sweep. |
    + | 400 | `unsupported_version` | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | none | Header missing, or key unknown or revoked. | No | Check the key. |
    + | 403 | none | The key lacks `videos:read`. | No | Use the app's open video key. |
    + | 403 | `app_not_registered` (in `error`) | The key is not bound to an app. | No | Register the app; use that app's key. |
    + | 403 | `org_suspended` (in `error`) | Your organisation is suspended. | No | Contact Wandura. |
    + | 404 | `collection_not_found` (in `error`) | Unknown, unpublished or not granted to you. | No | Check the collection code. |
    + | 429 | `rate_limited` | List limit reached. | After `Retry-After` | Wait; cache the list. |
    + | 500 | none | The list could not be read. | Backoff | Retry; keep serving your previous list. |
    + | 503 | `service_unavailable` | Wandura could not check the key in time. | After `Retry-After` | Retry. |
    + 
    + ### Get one open video {#video-errors}
    + 
    + `GET /api/delivery/v1/videos/{id}`
    + 
    + | Status | Code | When | Retry? | Your backend does |
    + |---|---|---|---|---|
    + | 400 | none | `id` is not a UUID. | No | Use the `id` from the list. |
    + | 400 | `unsupported_version` | Unknown or retired dated version. | No | Send a supported version. |
    + | 401 | none | Header missing, or key unknown or revoked. | No | Check the key. |
    + | 403 | none | The key lacks `videos:read`. | No | Use the app's open video key. |
    + | 403 | `app_not_registered` (in `error`) | The key is not bound to an app. | No | Register the app. |
    + | 403 | `org_suspended` (in `error`) | Your organisation is suspended. | No | Contact Wandura. |
    + | 404 | `video_not_found` (in `error`) | Unknown, not granted, unpublished, archived or not playable yet. | No | Drop it from your list. |
    + | 429 | `rate_limited` | Single-video limit reached (its own counter). | After `Retry-After` | Wait; prefer the cached list. |
    + | 500 | none | The video could not be read. | Backoff | Retry. |
    + | 503 | `service_unavailable` | Wandura could not check the key in time. | After `Retry-After` | Retry. |
    + 
    + ## Related {#related}
    + 
    + - [Canonical API behaviour](../reference/behaviour.md): retry policy, rate limits, freshness.
    + - [Troubleshooting](../production/troubleshooting.md): from a symptom to a fix.
    + - [Support](../help/support.md): what to send when an error persists.
  4. 2 Oct 2026 · +1 −1 lines
    Show changes
    ⋯
      | `502`, `503`, other `5xx` | Yes, with exponential backoff and a cap, for example 1 s, 2 s, 4 s, then give up. |
      
    - During playback, request a fresh ticket once when the Player SDK fails, then follow this table. See [Playback](playback.md#expiry).
    + During playback, request a fresh ticket once when the Player SDK fails, then follow this table. See [Playback](playback.md#expiry). For jitter, a retry budget and sample code, see [Smooth playback under load](../guides/smooth-playback.md#retry).
      
      ## Getting help
    ⋯
  5. 1 Oct 2026 · +2 −1 lines
    Show changes
    ⋯
      | 400 | `invalid_device_info` | A device value looks empty or invalid, for example the string `"(null)"`. `fields` names the bad values. | Fix how your app reads the values from the Player SDK. |
      | 401 | none | Missing, invalid or revoked API key. | Check the key. Do not retry. |
    - | 403 | none | The key lacks the `playback` scope. | Use the playback key Wandura issued to you. |
    + | 403 | none | The key lacks the `playback` scope. | Use a playback key: create one on **Developers** → **Stream films in an app**. |
      | 403 | `not_entitled` | Your organisation is not licensed to stream this film right now. `reason` gives the detail. | Show your locked or unavailable state. Do not retry. |
      | 404 | `not_ready` | The episode or film is unknown, not published, or not ready to stream. | Show "not available yet". Refresh your catalog. |
    ⋯
      | 503 | `not_ready` | No playable version of this episode is available right now. | Show "not available yet". Retry later. |
      | 503 | `service_unavailable` | Wandura could not check the API key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
    + | 503 | `service_unavailable` | The video provider did not answer in time (playback only). Nothing is wrong with the episode or your key. | Retry after `Retry-After` seconds (2), with backoff. |
      
      ### `not_entitled` reasons
    ⋯
  6. 1 Oct 2026 · +1 −1 lines
    Show changes
    ⋯
      | Field | Type | Description |
      |---|---|---|
    - | `error` | string | Human-readable message. Log it, but do not parse it. |
    + | `error` | string | Human-readable message. Log it, but do not parse it, except for the catalog `403` below. |
      | `error_code` | string | Machine-readable code. Branch on this. Absent on some errors, listed below as "none". |
      | `reason` | string | Only with `not_entitled`: the detailed reason, for logs and support. |
    ⋯
  7. 1 Oct 2026 · +2 −2 lines
    Show changes
    ⋯
      | 401 | none | `Invalid or revoked API key` | The key is unknown or revoked. | Check the key. Do not retry. |
      | 403 | none | `This API key does not have the metadata:read scope` | The key lacks the scope. | Use a key with `metadata:read`. |
    - | 403 | none | `org_suspended` | Your organisation's access is suspended. | Contact your Wandura partner contact. Do not retry. |
    + | 403 | none | `org_suspended` | Your organisation's access is suspended. | Contact Wandura. Do not retry. |
      | 429 | `rate_limited` | | Rate limit reached. | Wait for `Retry-After`. |
      | 503 | `service_unavailable` | `Could not verify the API key right now — retry` | Wandura could not check the key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
    ⋯
      | 401 | 4011 | `Invalid or revoked API key` | The key is unknown or revoked. | Check the key. Do not retry. |
      | 403 | 4030 | `This API key does not have the creatives:export scope` | The key lacks the scope. | Use a key with `creatives:export`. |
    - | 403 | 4031 | `org_suspended` | Your organisation's access is suspended. | Contact your Wandura partner contact. |
    + | 403 | 4031 | `org_suspended` | Your organisation's access is suspended. | Contact Wandura. |
      | 404 | 4040 | `Creative not found` | `GET /creatives/{id}` only. The creative does not exist, belongs to another organisation or is not approved. | Remove it from your active set. |
      | 422 | 4220 | `limit must be an integer between 1 and 100` | List only. Bad `limit`. | Fix the request. |
    ⋯
  8. 30 Sept 2026 · +3 −0 lines
    Show changes
    ⋯
      | 403 | none | `org_suspended` | Your organisation's access is suspended. | Contact your Wandura partner contact. Do not retry. |
      | 429 | `rate_limited` | | Rate limit reached. | Wait for `Retry-After`. |
    + | 503 | `service_unavailable` | `Could not verify the API key right now — retry` | Wandura could not check the key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
      
      ## Playback errors
    ⋯
      | 502 | none | Wandura could not prepare the stream or sign the play token. | Retry with backoff. |
      | 503 | `not_ready` | No playable version of this episode is available right now. | Show "not available yet". Retry later. |
    + | 503 | `service_unavailable` | Wandura could not check the API key in time. The key is **not** wrong. | Retry after `Retry-After` seconds, with backoff. Do not rotate the key. |
      
      ### `not_entitled` reasons
    ⋯
      | 429 | none (flat body, `error_code` `rate_limited`) | | Rate limit reached. | Wait for `Retry-After`. |
      | 503 | 5030 | `The creative feed is temporarily unavailable` | Temporary problem on Wandura's side. | Retry with backoff. |
    + | 503 | 5031 | `Could not verify the API key right now — retry` | Wandura could not check the key in time. The key is **not** wrong. | Retry with backoff. Do not rotate the key. |
      
      ## Retry guidance
    ⋯
  9. 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