Bản lưu ngày / Snapshot of 2026-10-12 · 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.
Change history

History: List licensed catalog

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

← List licensed catalog

  1. 7 Oct 2026 · +49 −3 lines
    Show changes
    ⋯
      | `metadata_updated_at` | string (ISO 8601, UTC) or null | When `metadata_version` last changed. |
      | `images` | array | Artwork for the film, one entry per kind Wandura has. A kind Wandura does not have is left out (never a `null` entry), so the array can be empty. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. `poster_url` stays as it is. |
    + | `materials` | array | The film's artwork as media assets in YOUR media space (the space your Player SDK and CMS use; Wandura's shared space if your organisation has none): the latest version of each kind. Identify an asset by `mid` and `title` (`<code>-poster-3-4-v<N>`, `<code>-cover-9-16-v<N>`). `url` is pre-signed on your playback domain and expires at `expires_at`; sign `store_uri` with your own key when you need a fresh link. Empty until Wandura has copied the artwork into your space. `images` and `poster_url` stay as they are. |
      
      ### Episode fields (`episodes[]`)
    ⋯
      | `poster_uri` | string or null | Episode thumbnail reference. Not guaranteed to be a directly loadable URL — use `poster_url`. |
      | `poster_url` | string or null | The episode image as an absolute `https` URL you can load directly, or `null` (then use the film's `poster_url`). |
    + | `poster_signed_url` | string or null | The cover of this episode's video (`vid`) in your media space, as a pre-signed `https` link on your playback domain, valid until `poster_expires_at` (at most 15 minutes) — download the image, do not store the link. `null` when there is no such cover yet or Wandura cannot sign for your domain (then sign `poster_store_uri` yourself). `poster_url` is not affected. |
    + | `poster_store_uri` | string or null | Storage URI of the cover of `vid` in your media space, for signing a fresh link with your own key. `null` when there is no such cover yet. |
    + | `poster_expires_at` | integer or null | When `poster_signed_url` stops working, in Unix epoch seconds (at most 15 minutes ahead). `null` when `poster_signed_url` is `null`. |
    + | `vid` | string or null | Video ID of the episode in YOUR media space — the ID your app loads in the Player SDK and your CMS signs a play token for. If your organisation has its own media space it is the ID of Wandura's copy there (`null` until that copy is ready); otherwise it is the ID in Wandura's shared space. `null` on placeholder rows. |
    + | `vid_ready` | boolean or null | `true` when `vid` is ready to play in your media space. `false` while Wandura is still copying the episode (and on placeholder rows). `null` only if Wandura could not tell, so keep your previous value. |
      | `status` | string | `published`, or `planned` for a placeholder row. |
      | `stream_ready` | boolean | `true` when a ticket can be issued for the episode. Always `false` on placeholder rows. |
    ⋯
              { "kind": "poster_3_4", "lang": null, "url": "https://cdn.example.com/posters/the-heiress-returns-3x4.jpg", "width": 1080, "height": 1440 },
              { "kind": "cover_9_16", "lang": null, "url": "https://cdn.example.com/posters/the-heiress-returns.jpg", "width": 1080, "height": 1920 }
    +       ],
    +       "materials": [
    +         {
    +           "kind": "poster_3_4",
    +           "title": "WD000016-poster-3-4-v1",
    +           "mid": "v0d2f8c1a9e4b7c3d5e6f708192a3b4c5",
    +           "url": "https://your-playback.example.com/materials/WD000016-poster-3-4-v1.jpg?auth_key=1791262800-9f1c2e3d4a5b6c7d-0-3c5e7a9b1d2f4a6c8e0b2d4f6a8c0e2b",
    +           "expires_at": 1791262800,
    +           "store_uri": "tos-media-space/materials/WD000016-poster-3-4-v1.jpg",
    +           "width": 1080,
    +           "height": 1440
    +         },
    +         {
    +           "kind": "cover_9_16",
    +           "title": "WD000016-cover-9-16-v1",
    +           "mid": "v0d2f8c1a9e4b7c3d5e6f708192a3b4c6",
    +           "url": "https://your-playback.example.com/materials/WD000016-cover-9-16-v1.webp?auth_key=1791262800-0a1b2c3d4e5f6071-0-7e9a1c3e5a7c9e1b3d5f7a9c1e3b5d7f",
    +           "expires_at": 1791262800,
    +           "store_uri": "tos-media-space/materials/WD000016-cover-9-16-v1.webp",
    +           "width": 1080,
    +           "height": 1920
    +         }
            ]
          }
    ⋯
            "stream_ready": true,
            "title_i18n": { "en": "Episode 1" },
    -       "subtitles": [{ "lang": "en" }]
    +       "subtitles": [{ "lang": "en" }],
    +       "poster_url": null,
    +       "poster_signed_url": "https://your-playback.example.com/oMOAomiBCg7rGAYIP1f6x4yG7vI2QSgnGaqKs4?auth_key=1791262800-5c6d7e8f9a0b1c2d-0-1f3b5d7f9b1d3f5b7d9f1b3d5f7b9d1f",
    +       "poster_store_uri": "tos-media-space/oMOAomiBCg7rGAYIP1f6x4yG7vI2QSgnGaqKs4",
    +       "poster_expires_at": 1791262800,
    +       "vid": "v25ec7gm0018db1l8tqtgd60242f05e0",
    +       "vid_ready": true
          },
          {
    ⋯
            "poster_uri": null,
            "status": "published",
    -       "stream_ready": false
    +       "stream_ready": false,
    +       "poster_url": null,
    +       "poster_signed_url": null,
    +       "poster_store_uri": null,
    +       "poster_expires_at": null,
    +       "vid": null,
    +       "vid_ready": false
          },
          {
    ⋯
            "poster_uri": null,
            "status": "planned",
    -       "stream_ready": false
    +       "stream_ready": false,
    +       "poster_url": null,
    +       "poster_signed_url": null,
    +       "poster_store_uri": null,
    +       "poster_expires_at": null,
    +       "vid": null,
    +       "vid_ready": false
          }
        ]
    ⋯
  2. 4 Oct 2026 · +38 −3 lines
    Show changes
    ⋯
      | `form` | string or null | `live_action`, `anime`, or `null` if unclassified. New values may be added. |
      | `setting` | string or null | `modern`, `city`, `fantasy`, `campus`, `palace`, or `null` if unclassified. New values may be added. |
    + | `code` | string or null | Wandura series code, for example `WD000016`. Stable and shared across every Wandura system (the playlist in your media space has this name). Use it with GET /api/delivery/v1/series/{code}. |
    + | `title_i18n` | object | Text by language: keys are BCP-47 codes, values are the text, for example `{"en": "The Heiress Returns"}`. Today Wandura fills `en`; more languages may appear. A missing key means no text in that language: fall back to `en`. Empty object when there is no text. |
    + | `synopsis_short_i18n` | object | Text by language: keys are BCP-47 codes, values are the text, for example `{"en": "The Heiress Returns"}`. Today Wandura fills `en`; more languages may appear. A missing key means no text in that language: fall back to `en`. Empty object when there is no text. |
    + | `synopsis_i18n` | object | Text by language: keys are BCP-47 codes, values are the text, for example `{"en": "The Heiress Returns"}`. Today Wandura fills `en`; more languages may appear. A missing key means no text in that language: fall back to `en`. Empty object when there is no text. |
    + | `content_rating` | string or null | Age rating: `all`, `13+`, `16+` or `18+`. `null` when not rated yet. |
    + | `is_completed` | boolean or null | `true` when every planned episode is released, `false` while more are coming, `null` when the planned count is unknown. |
    + | `release_date` | string or null | Original release date, `YYYY-MM-DD`, or `null` when unknown. |
    + | `default_lang` | string or null | Audio language of the film as a BCP-47 code (`en`, `vi`, `pt-BR`), or `null` when unknown. Prefer it over the free-text `language`. |
    + | `tags` | array | Coded genre and theme tags. At most one has `is_main` `true` (the main genre, shown under the title). Can be empty. |
    + | `people` | array | Main cast or characters, leads first. Can be empty. |
    + | `trailer` | object or null | The trailer video, or `null`. `vid` is the video ID in Wandura's media space. |
    + | `metadata_version` | string or null | Hash of the film's metadata (titles, synopses, rating, tags, people, artwork, episodes and their subtitles). Unchanged hash = nothing to update on your side. |
    + | `metadata_updated_at` | string (ISO 8601, UTC) or null | When `metadata_version` last changed. |
      | `images` | array | Artwork for the film, one entry per kind Wandura has. A kind Wandura does not have is left out (never a `null` entry), so the array can be empty. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. `poster_url` stays as it is. |
      
    ⋯
      | `status` | string | `published`, or `planned` for a placeholder row. |
      | `stream_ready` | boolean | `true` when a ticket can be issued for the episode. Always `false` on placeholder rows. |
    + | `title_i18n` | object | Text by language: keys are BCP-47 codes, values are the text, for example `{"en": "The Heiress Returns"}`. Today Wandura fills `en`; more languages may appear. A missing key means no text in that language: fall back to `en`. Empty object when there is no text. |
    + | `subtitles` | array | Subtitle languages available for the episode (the files come with the playback ticket). Empty on placeholder rows. |
    + | `subtitles[].lang` | string | BCP-47 code, for example `en`. |
      
      Within a film, each `episode_no` appears once, so `film_id` + `episode_no` identifies an episode. Episodes are grouped by film ID and sorted by `episode_no` within each film. Take the film order from `films`.
    ⋯
            "form": "live_action",
            "setting": "modern",
    +       "code": "WD000016",
    +       "title_i18n": { "en": "The Heiress Returns" },
    +       "synopsis_short_i18n": { "en": "Cast out on her wedding day, a disowned heiress comes back to take everything." },
    +       "synopsis_i18n": { "en": "Cast out on her wedding day, Mia loses her family, her name and her fortune. Five years later she returns with a new identity and one goal." },
    +       "content_rating": "13+",
    +       "is_completed": false,
    +       "release_date": null,
    +       "default_lang": "en",
    +       "tags": [
    +         { "slug": "revenge", "name": "Revenge", "name_i18n": { "en": "Revenge" }, "type": "genre", "is_main": true },
    +         { "slug": "romance", "name": "Romance", "name_i18n": { "en": "Romance" }, "type": "genre", "is_main": false },
    +         { "slug": "heiress", "name": "Heiress", "name_i18n": { "en": "Heiress" }, "type": "theme", "is_main": false }
    +       ],
    +       "people": [{ "name": "Mia", "role": "lead", "description": "A disowned heiress back for what is hers.", "avatar_url": null }],
    +       "trailer": null,
    +       "metadata_version": "9a0b1c2d3e4f5061728394a5b6c7d8e9",
    +       "metadata_updated_at": "2026-10-03T09:00:00.000Z",
            "images": [
    -         { "kind": "poster_3_4", "url": "https://cdn.example.com/posters/the-heiress-returns-3x4.jpg", "width": 1080, "height": 1440 },
    -         { "kind": "cover_9_16", "url": "https://cdn.example.com/posters/the-heiress-returns.jpg", "width": null, "height": null }
    +         { "kind": "poster_3_4", "lang": null, "url": "https://cdn.example.com/posters/the-heiress-returns-3x4.jpg", "width": 1080, "height": 1440 },
    +         { "kind": "cover_9_16", "lang": null, "url": "https://cdn.example.com/posters/the-heiress-returns.jpg", "width": 1080, "height": 1920 }
            ]
          }
    ⋯
            "poster_uri": null,
            "status": "published",
    -       "stream_ready": true
    +       "stream_ready": true,
    +       "title_i18n": { "en": "Episode 1" },
    +       "subtitles": [{ "lang": "en" }]
          },
          {
    ⋯
  3. 3 Oct 2026 · +6 −1 lines
    Show changes
    ⋯
      | `form` | string or null | `live_action`, `anime`, or `null` if unclassified. New values may be added. |
      | `setting` | string or null | `modern`, `city`, `fantasy`, `campus`, `palace`, or `null` if unclassified. New values may be added. |
    + | `images` | array | Artwork for the film, one entry per kind Wandura has. A kind Wandura does not have is left out (never a `null` entry), so the array can be empty. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. `poster_url` stays as it is. |
      
      ### Episode fields (`episodes[]`)
    ⋯
            "audience": "women",
            "form": "live_action",
    -       "setting": "modern"
    +       "setting": "modern",
    +       "images": [
    +         { "kind": "poster_3_4", "url": "https://cdn.example.com/posters/the-heiress-returns-3x4.jpg", "width": 1080, "height": 1440 },
    +         { "kind": "cover_9_16", "url": "https://cdn.example.com/posters/the-heiress-returns.jpg", "width": null, "height": null }
    +       ]
          }
        ],
    ⋯
  4. 2 Oct 2026 · +2 −0 lines
    Show changes
    ⋯
      | `Wandura-API-Status` | all | API status. `beta` today, on every response, success or error. |
      | `Wandura-Version` | all | The dated API version (YYYY-MM-DD) this response was produced in: the version pinned to your API key, or the one you sent in the `Wandura-Version` request header. Keys created before dated versions existed use `2026-10-02`. |
    + | `Wandura-Request-Id` | all | An opaque id for this request (`req_` followed by 26 characters). Every response carries it, errors included, and error bodies repeat it as `request_id`. Log it, and quote it when you contact Wandura about a request: it finds the exact request in our logs. Do not parse it. |
    + | `Cache-Control` | all | Always `no-store`. Do not cache these responses in shared caches. |
      | `Deprecation` | 200 | Present only when this endpoint, or the dated version serving this response, is deprecated (RFC 9745): `@<unix seconds>` of the deprecation date. Log it in your monitoring. |
      | `Sunset` | 200 | Present only when a deprecated endpoint or dated version has a date when it stops working (RFC 8594), as an HTTP date. |
    ⋯
  5. 2 Oct 2026 · +3 −4 lines
    Show changes
    ⋯
      ## Description
      
    - A film is included when your organisation has an active streaming licence for it, today (UTC) is inside the licence window, and the film is published. For each included film, all published episodes are returned, plus a placeholder row for each planned episode that is not published yet. Films arrive sorted by `display_order`. There is no pagination. See [Catalog](../concepts/catalog.md).
    + A film is included when your organisation has an active streaming licence for it, today (UTC) is inside the licence window, and the film is published. For each included film, all published episodes are returned, plus a placeholder row for each planned episode that is not published yet. Films arrive sorted by `display_order`. Without `limit` and `cursor` you receive the whole catalog in one response; with `limit` you receive pages of films, each with all their episodes, until `next_cursor` is `null`. Pages are not one consistent snapshot: see [Canonical API behaviour · Pagination](behaviour.md#pagination) before you page. See [Catalog](../concepts/catalog.md).
      
      ## Request parameters
    ⋯
      | `cursor` | query | string | No | Optional. The `next_cursor` (or the cursor inside `links.next`) of the previous page. Opaque; pass it back unchanged. With a cursor and no `limit` the page size is 50. |
      | `Wandura-Version` | header | string | No | Optional. A dated API version (YYYY-MM-DD) to use for this request instead of the version pinned to your API key. Unknown or retired values answer 400 with `error_code` `unsupported_version`. |
    - 
    - This endpoint takes no query parameters.
    + | `Wandura-Simulate` | header | string | No | Optional, test organisations only. Asks Wandura to answer with a simulated error so you can test how your app handles it, for example `rate_limited`, `service_unavailable` or `not_entitled:outside_window`. The simulated response has the same status, body and headers as the real one, plus a `Wandura-Simulated` header naming the scenario. It issues no ticket and does not count against your rate limits, except `partial_batch`, whose first item is a real ticket. Simulated responses have their own limit of 300 per minute per organisation. Keys of production organisations ignore this header completely. An unknown value, or a scenario this endpoint does not support, is ignored and the request runs normally. See the Testing guide for the list of scenarios. |
      
      ## Request example
    ⋯
      The two `403` responses carry no `error_code`. Tell them apart by `error`: it is exactly `org_suspended` when your organisation is suspended, and any other text means the key lacks `metadata:read`. This is the one case where you compare `error`; compare the whole string.
      
    - See [Errors](../concepts/errors.md#catalog-errors) for what to do in each case.
    + What to do in each case: [Errors](../concepts/errors.md#catalog-errors).
  6. 2 Oct 2026 · +1 −1 lines
    Show changes
    ⋯
      | 403 | none (`error` is `org_suspended`) | Your organisation's access is suspended. |
      | 429 | `rate_limited` | The rate limit for the catalog was reached. |
    - | 503 | `service_unavailable` | Wandura could not verify the API key in time. The key is not wrong: retry after `Retry-After` seconds, with backoff. |
    + | 503 | `service_unavailable` | Wandura could not verify the API key or read the catalog in time. Nothing is wrong on your side: retry after `Retry-After` seconds, with backoff. |
      
      The two `403` responses carry no `error_code`. Tell them apart by `error`: it is exactly `org_suspended` when your organisation is suspended, and any other text means the key lacks `metadata:read`. This is the one case where you compare `error`; compare the whole string.
    ⋯
  7. 2 Oct 2026 · +11 −1 lines
    Show changes
    ⋯
      |---|---|---|---|---|
      | `Authorization` | header | string | Yes | `Bearer <API key>` for a key with the `metadata:read` scope. |
    + | `limit` | query | integer | No | Optional. Films per page, 1 to 200. Omit it (and `cursor`) to receive the whole catalog in one response. |
    + | `cursor` | query | string | No | Optional. The `next_cursor` (or the cursor inside `links.next`) of the previous page. Opaque; pass it back unchanged. With a cursor and no `limit` the page size is 50. |
    + | `Wandura-Version` | header | string | No | Optional. A dated API version (YYYY-MM-DD) to use for this request instead of the version pinned to your API key. Unknown or retired values answer 400 with `error_code` `unsupported_version`. |
      
      This endpoint takes no query parameters.
    ⋯
      | `synopsis` | string or null | Episode description. Often `null`. |
      | `duration_ms` | integer or null | Duration in milliseconds. |
    - | `poster_uri` | string or null | Episode thumbnail reference. Not guaranteed to be a directly loadable URL. |
    + | `poster_uri` | string or null | Episode thumbnail reference. Not guaranteed to be a directly loadable URL — use `poster_url`. |
    + | `poster_url` | string or null | The episode image as an absolute `https` URL you can load directly, or `null` (then use the film's `poster_url`). |
      | `status` | string | `published`, or `planned` for a placeholder row. |
      | `stream_ready` | boolean | `true` when a ticket can be issued for the episode. Always `false` on placeholder rows. |
    ⋯
      |---|---|---|
      | `Wandura-API-Status` | all | API status. `beta` today, on every response, success or error. |
    + | `Wandura-Version` | all | The dated API version (YYYY-MM-DD) this response was produced in: the version pinned to your API key, or the one you sent in the `Wandura-Version` request header. Keys created before dated versions existed use `2026-10-02`. |
    + | `Deprecation` | 200 | Present only when this endpoint, or the dated version serving this response, is deprecated (RFC 9745): `@<unix seconds>` of the deprecation date. Log it in your monitoring. |
    + | `Sunset` | 200 | Present only when a deprecated endpoint or dated version has a date when it stops working (RFC 8594), as an HTTP date. |
    + | `Link` | 200 | Present with `Deprecation`: `<https://docs.wandura.ai/…>; rel="deprecation"` (and `rel="sunset"`) pointing to the page that explains what to use instead. |
      | `Retry-After` | 429, 503 | Seconds to wait before retrying. Sent with 429 and with retryable 503 responses. |
      | `X-RateLimit-Limit` | 429 | Requests (for playback, tickets) allowed per window for this endpoint group and your organisation. |
    ⋯
      | Status | `error_code` | When |
      |---|---|---|
    + | 400 | `invalid_request` | `limit` is not a whole number from 1 to 200, or `cursor` is not a value this endpoint returned. |
    + | 400 | `unsupported_version` | The `Wandura-Version` header, or the version pinned to your key, is unknown or retired. The body adds `supported_versions` and `latest_version` (and `upgrade_to` when your pin was retired). |
      | 401 | none | The `Authorization: Bearer` header is missing, or the key is unknown or revoked. |
      | 403 | none | The key lacks the `metadata:read` scope. |
    ⋯
  8. 2 Oct 2026 · +14 −5 lines
    Show changes
    ⋯
      | Name | In | Type | Required | Description |
      |---|---|---|---|---|
    - | `Authorization` | header | string | Yes | `Bearer <API key>`. |
    + | `Authorization` | header | string | Yes | `Bearer <API key>` for a key with the `metadata:read` scope. |
      
      This endpoint takes no query parameters.
    ⋯
      | `planned_episodes` | integer or null | Total number of episodes planned. `null` when not set: then the film gets no placeholder rows, and `episodes` lists only its published episodes. |
      | `free_until_episode` | integer or null | Episodes with `episode_no` up to and including this number are free. `0` means no free episode. `null` means no number is set for the film: treat every episode as paid, and ask Wandura if you expected free episodes. |
    - | `audience` | string or null | `women`, `men`, `lgbtq`, or `null` if unclassified. |
    - | `form` | string or null | `live_action`, `anime`, or `null` if unclassified. |
    - | `setting` | string or null | `modern`, `city`, `fantasy`, `campus`, `palace`, or `null` if unclassified. |
    + | `audience` | string or null | `women`, `men`, `lgbtq`, or `null` if unclassified. New values may be added. |
    + | `form` | string or null | `live_action`, `anime`, or `null` if unclassified. New values may be added. |
    + | `setting` | string or null | `modern`, `city`, `fantasy`, `campus`, `palace`, or `null` if unclassified. New values may be added. |
      
      ### Episode fields (`episodes[]`)
    ⋯
      ```
      
    + ## Response headers {#response-headers}
    + 
    + | Header | Responses | Description |
    + |---|---|---|
    + | `Wandura-API-Status` | all | API status. `beta` today, on every response, success or error. |
    + | `Retry-After` | 429, 503 | Seconds to wait before retrying. Sent with 429 and with retryable 503 responses. |
    + | `X-RateLimit-Limit` | 429 | Requests (for playback, tickets) allowed per window for this endpoint group and your organisation. |
    + | `X-RateLimit-Window` | 429 | Window length in seconds. |
    + 
      ## Errors {#errors}
      
    ⋯
      | 403 | none | The key lacks the `metadata:read` scope. |
      | 403 | none (`error` is `org_suspended`) | Your organisation's access is suspended. |
    - | 429 | `rate_limited` | The rate limit for the catalog and creatives endpoints was reached. |
    + | 429 | `rate_limited` | The rate limit for the catalog was reached. |
      | 503 | `service_unavailable` | Wandura could not verify the API key in time. The key is not wrong: retry after `Retry-After` seconds, with backoff. |
      
    ⋯
  9. 1 Oct 2026 · +10 −7 lines
    Show changes
    ⋯
      | Field | Type | Description |
      |---|---|---|
    - | `id` | string (UUID) | Film ID. Use it as `film_ref` in playback. |
    + | `id` | string (UUID) | Film ID. It never changes: use it as your primary key, and as `film_ref` in playback. |
      | `title` | string | Film title. |
    - | `slug` | string | URL-safe film identifier. Also accepted as `film_ref` in playback. |
    + | `slug` | string | URL-safe film identifier, unique across films. Wandura does not change it after the film is created. Also accepted as `film_ref` in playback. |
      | `synopsis_short` | string or null | Short description for cards. Length varies. |
      | `synopsis_full` | string or null | Full description for detail pages. |
      | `genres` | array of strings | Genre labels. Can be empty. |
    - | `language` | string or null | Language of the film. |
    + | `language` | string or null | Language of the film, as free text written by Wandura's content team (for example `en` or `English`). It is not a fixed list of codes: display it, do not parse it. |
      | `poster_url` | string or null | Film poster URL. |
      | `status` | string | Always `published`. |
      | `display_order` | integer | Display position, smallest first. The array is already sorted by it. |
    - | `planned_episodes` | integer or null | Total number of episodes planned. |
    - | `free_until_episode` | integer or null | Episodes with `episode_no` up to and including this number are free. |
    + | `planned_episodes` | integer or null | Total number of episodes planned. `null` when not set: then the film gets no placeholder rows, and `episodes` lists only its published episodes. |
    + | `free_until_episode` | integer or null | Episodes with `episode_no` up to and including this number are free. `0` means no free episode. `null` means no number is set for the film: treat every episode as paid, and ask Wandura if you expected free episodes. |
      | `audience` | string or null | `women`, `men`, `lgbtq`, or `null` if unclassified. |
      | `form` | string or null | `live_action`, `anime`, or `null` if unclassified. |
    ⋯
      | `stream_ready` | boolean | `true` when a ticket can be issued for the episode. Always `false` on placeholder rows. |
      
    - Episodes are grouped by film ID and sorted by `episode_no` within each film. Take the film order from `films`.
    + Within a film, each `episode_no` appears once, so `film_id` + `episode_no` identifies an episode. Episodes are grouped by film ID and sorted by `episode_no` within each film. Take the film order from `films`.
      
      If your organisation has no current licences, both arrays are empty.
    ⋯
      ```
      
    - ## Errors
    + ## Errors {#errors}
      
      | Status | `error_code` | When |
    ⋯
      | 403 | none (`error` is `org_suspended`) | Your organisation's access is suspended. |
      | 429 | `rate_limited` | The rate limit for the catalog and creatives endpoints was reached. |
    + | 503 | `service_unavailable` | Wandura could not verify the API key in time. The key is not wrong: retry after `Retry-After` seconds, with backoff. |
      
    + The two `403` responses carry no `error_code`. Tell them apart by `error`: it is exactly `org_suspended` when your organisation is suspended, and any other text means the key lacks `metadata:read`. This is the one case where you compare `error`; compare the whole string.
    + 
      See [Errors](../concepts/errors.md#catalog-errors) for what to do in each case.
  10. 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