Bản lưu ngày / Snapshot of 2026-10-06 · 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: Catalog

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

← Catalog

  1. 3 Oct 2026 · +8 −8 lines
    Show changes
    ⋯
      - For episodes use `poster_url` (a loadable `https` URL or `null`, then fall back to the film poster). `poster_uri` is an internal reference, not a loadable URL.
      
    - > **Rolling out.** Each film also carries `images`, its artwork by kind, each entry `{ "kind", "url", "width", "height" }`:
    - >
    - > | `kind` | What it is | `width` / `height` |
    - > |---|---|---|
    - > | `poster_3_4` | 3:4 card poster | pixels, measured from the file |
    - > | `cover_9_16` | 9:16 full-screen cover, the same image as `poster_url` | `null` for now (size not recorded yet) |
    - >
    - > A kind Wandura does not have is left out, so the array can be empty; it never holds a `null` entry. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. New kinds may be added: skip a kind you do not know. `poster_url` stays as it is.
    + Each film also carries `images`, its artwork by kind, each entry `{ "kind", "url", "width", "height" }`:
      
    + | `kind` | What it is | `width` / `height` |
    + |---|---|---|
    + | `poster_3_4` | 3:4 card poster | pixels, measured from the file |
    + | `cover_9_16` | 9:16 full-screen cover, the same image as `poster_url` | `null` for now (size not recorded yet) |
    + 
    + A kind Wandura does not have is left out, so the array can be empty; it never holds a `null` entry. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. New kinds may be added: skip a kind you do not know. `poster_url` stays as it is.
    + 
      ## Freshness {#keeping-your-copy-fresh}
      
    ⋯
  2. 3 Oct 2026 · +9 −0 lines
    Show changes
    ⋯
      - For episodes use `poster_url` (a loadable `https` URL or `null`, then fall back to the film poster). `poster_uri` is an internal reference, not a loadable URL.
      
    + > **Rolling out.** Each film also carries `images`, its artwork by kind, each entry `{ "kind", "url", "width", "height" }`:
    + >
    + > | `kind` | What it is | `width` / `height` |
    + > |---|---|---|
    + > | `poster_3_4` | 3:4 card poster | pixels, measured from the file |
    + > | `cover_9_16` | 9:16 full-screen cover, the same image as `poster_url` | `null` for now (size not recorded yet) |
    + >
    + > A kind Wandura does not have is left out, so the array can be empty; it never holds a `null` entry. Every `url` is an absolute `https` URL on a Wandura host that you can load directly. New kinds may be added: skip a kind you do not know. `poster_url` stays as it is.
    + 
      ## Freshness {#keeping-your-copy-fresh}
      
    ⋯
  3. 2 Oct 2026 · +37 −41 lines
    Show changes
      # Catalog
      
    - The catalog is the list of films and episodes your organisation may stream right now. It is designed to be the only film list your app needs: it carries display order, free-episode rules, genre facets and a per-episode readiness flag, so you do not have to maintain any of these yourself.
    - 
    - ## What is in the catalog
    + > **TL;DR** — `GET /catalog` lists every film and episode your organisation may stream right now, with display order, free-episode rule and a readiness flag per episode. Metadata only, never a video URL. Fetch it whole, or in pages with `limit` and `cursor`. It is the only film list your app needs; a ticket request re-checks everything anyway.
      
    - `GET /api/delivery/v1/catalog` returns a film when all of these are true at the moment of the request:
    + ## What is in the catalog {#what-is-in-the-catalog}
      
    - - Your organisation holds a streaming licence for the film, and that licence is active.
    - - Today falls inside the licence window. Windows are whole days in UTC, and the first and last day are included.
    - - The film is published.
    + A film is listed when, at the moment of the request:
      
    - For those films, it returns every published episode. Films that are still in production, and review cuts shared with you for feedback, never appear in the catalog and cannot be played through the API.
    + - your organisation holds a streaming licence for it, and the licence is active;
    + - today (UTC) is inside the licence window — whole days, first and last day included;
    + - the film is published.
      
    - The catalog contains metadata only. It never contains a video URL; you request playback per episode with [`POST /playback`](playback.md).
    + For those films it lists every published episode, plus a placeholder row for each planned episode not yet published. Films still in production and review cuts never appear and cannot be played through the API. An empty response (`"films": []`) means no licence is active for your organisation right now.
      
    - ## Response shape
    + ## Response shape {#response-shape}
      
    - The response has two flat arrays, `films` and `episodes`. Join them on `episodes[].film_id` = `films[].id`. The full field list is in the [catalog reference](../reference/catalog.md).
    + Two flat arrays, `films` and `episodes`; join them on `episodes[].film_id` = `films[].id`. The response also carries `links` (`self`, `next`, `playback`, `config`). Every field: [List licensed catalog](../reference/catalog.md).
      
    - The whole catalog comes back in one response. There is no pagination.
    + ## Pages {#pages}
      
    - ## Order
    + Without `limit` or `cursor` you receive the whole catalog in one response. With `limit` (1–200 films) you receive one page of films with **all** their episodes, plus `next_cursor` and `links.next`; pass the cursor back unchanged until it is `null`. Pages are **not** one consistent snapshot: the rules for syncing safely are in [Canonical API behaviour · Pagination](../reference/behaviour.md#pagination), and the code in [Catalog sync](../guides/catalog-sync.md).
      
    - `films` arrives sorted by `display_order`, smallest first. Render films in the order you receive them. Wandura edits the order, so do not keep your own ordering table.
    + ## Order {#order}
      
    - `episodes` arrives grouped by film ID, then sorted by `episode_no`. The groups are not in display order, so take the film order from `films`.
    + `films` arrives sorted by `display_order`, smallest first, and across pages too. Render films in that order; Wandura edits it, so keep no ordering table of your own. `episodes` arrives grouped by film, then by `episode_no`; take the film order from `films`.
      
    - ## Free and paid episodes
    + ## Free and paid episodes {#free-and-paid-episodes}
      
    - Episodes with `episode_no` less than or equal to the film's `free_until_episode` are free; the rest are paid. The value differs per film and can change, so read it from the catalog rather than hard-coding it. `0` means no free episode; `null` means no number is set for the film, so treat every episode as paid.
    + Episodes with `episode_no` ≤ the film's `free_until_episode` are free; the rest are paid. `0` means no free episode; `null` means none is set, so treat every episode as paid. The value differs per film and can change: read it on every sync.
      
    - ## Planned episodes
    + ## Planned episodes {#planned-episodes}
      
    - `planned_episodes` is the number of episodes the film will have. When some of them are not published yet, the catalog still includes a row for each missing episode number so you can show a "coming soon" tile. These placeholder rows have:
    + `planned_episodes` is the number of episodes the film will have. For each one not yet published, the catalog includes a placeholder row so you can show "coming soon":
      
      | Field | Value |
    ⋯
      | `status` | `"planned"` |
      | `stream_ready` | `false` |
    - | `title`, `synopsis`, `duration_ms`, `poster_uri` | `null` |
    - 
    - Never send a placeholder row to `POST /playback`: it has no episode ID. If a film has more published episodes than `planned_episodes`, all of them are still returned. When `planned_episodes` is `null`, the film has no placeholder rows.
    - 
    - ## Readiness: `stream_ready`
    + | `title`, `synopsis`, `duration_ms`, `poster_uri`, `poster_url` | `null` |
      
    - `stream_ready: true` means an encrypted version of the episode exists and `POST /playback` can issue a ticket for it. Grey out or hide episodes where it is `false`, rather than letting a viewer tap into an error.
    + Never send a placeholder to `POST /playback`: it has no ID. When `planned_episodes` is `null`, there are no placeholders.
      
    - The flag is a snapshot taken when you fetched the catalog. `POST /playback` checks your licence and the episode again every time, and its answer is the one that counts. A `not_ready` answer for an episode that was `stream_ready: true` is normal, for example after a title is withdrawn.
    + ## Readiness: `stream_ready` {#readiness-stream-ready}
      
    - ## Genre facets
    + `true` means a ticket can be issued for the episode now. Grey out or hide episodes where it is `false`. It is a snapshot of the moment you fetched the catalog: the ticket request checks again, and its answer is the one that counts. A `not_ready` answer for an episode that was `stream_ready: true` is normal, for example right after a withdrawal.
      
    - Each film carries three optional facets for browse screens and filters. `null` means the film has not been classified; show it without that facet rather than guessing.
    + ## Genre facets {#genre-facets}
      
    - | Field | Possible values |
    + | Field | Values (`null` = not classified; new values may be added) |
      |---|---|
    - | `audience` | `women`, `men`, `lgbtq`, or `null` |
    - | `form` | `live_action`, `anime`, or `null` |
    - | `setting` | `modern`, `city`, `fantasy`, `campus`, `palace`, or `null` |
    + | `audience` | `women`, `men`, `lgbtq` |
    + | `form` | `live_action`, `anime` |
    + | `setting` | `modern`, `city`, `fantasy`, `campus`, `palace` |
      
    - Films also carry `genres`, an array of free-text genre labels, and `language`.
    + Films also carry `genres` (free-text labels) and `language` (free text: display it, do not parse it).
      
    - ## Text and artwork
    + ## Text and artwork {#text-and-artwork}
      
    - - `synopsis_short` is meant for cards and `synopsis_full` for detail pages. Lengths vary between films, so clamp text in your UI. `synopsis_full` can be `null`.
    - - `episodes[].synopsis` can be `null`. Render nothing when it is.
    - - `poster_url` (film) and `poster_uri` (episode) can be `null` while artwork is being prepared. Show a placeholder image.
    + - `synopsis_short` for cards, `synopsis_full` for detail pages; lengths vary, clamp them. Either can be `null`.
    + - `poster_url` (film) can be `null` while artwork is prepared: show a placeholder.
    + - For episodes use `poster_url` (a loadable `https` URL or `null`, then fall back to the film poster). `poster_uri` is an internal reference, not a loadable URL.
      
    - ## Keeping your copy fresh
    + ## Freshness {#keeping-your-copy-fresh}
      
    - Cache the catalog on your server and refresh it on a schedule, instead of calling the API on every app launch. A licence that ends or a title that is withdrawn disappears from the next response; remove anything that is no longer listed.
    + A change on Wandura's side (a publication, a withdrawal, a licence that starts or ends) appears in the catalog within 30 seconds. All bounds: [Canonical API behaviour · Freshness](../reference/behaviour.md#freshness). Sync every 15–60 minutes from your server; never call the catalog on app launch.
      
    - A catalog response may be up to 30 seconds old. A title or episode just published or withdrawn, a change to `stream_ready`, or a licence just granted, suspended or past its window shows up within 30 seconds. Wandura runs several servers that each keep their own copy, so two calls within those 30 seconds may return different snapshots.
    + ## Related {#related}
      
    - The catalog has its own rate-limit counter, separate from playback and creatives. See [Rate limits](rate-limits.md).
    + - [Catalog sync](../guides/catalog-sync.md)
    + - [List licensed catalog](../reference/catalog.md)
    + - [When rights end](../production/rights-end.md)
  4. 2 Oct 2026 · +2 −0 lines
    Show changes
    ⋯
      Cache the catalog on your server and refresh it on a schedule, instead of calling the API on every app launch. A licence that ends or a title that is withdrawn disappears from the next response; remove anything that is no longer listed.
      
    + A catalog response may be up to 30 seconds old. A title or episode just published or withdrawn, a change to `stream_ready`, or a licence just granted, suspended or past its window shows up within 30 seconds. Wandura runs several servers that each keep their own copy, so two calls within those 30 seconds may return different snapshots.
    + 
      The catalog has its own rate-limit counter, separate from playback and creatives. See [Rate limits](rate-limits.md).
  5. 1 Oct 2026 · +1 −1 lines
    Show changes
    ⋯
      Cache the catalog on your server and refresh it on a schedule, instead of calling the API on every app launch. A licence that ends or a title that is withdrawn disappears from the next response; remove anything that is no longer listed.
      
    - The catalog and creatives endpoints share one rate-limit counter. See [Rate limits](rate-limits.md).
    + The catalog has its own rate-limit counter, separate from playback and creatives. See [Rate limits](rate-limits.md).
  6. 1 Oct 2026 · +2 −2 lines
    Show changes
    ⋯
      ## Free and paid episodes
      
    - Episodes with `episode_no` less than or equal to the film's `free_until_episode` are free; the rest are paid. The value differs per film and can change, so read it from the catalog rather than hard-coding it.
    + Episodes with `episode_no` less than or equal to the film's `free_until_episode` are free; the rest are paid. The value differs per film and can change, so read it from the catalog rather than hard-coding it. `0` means no free episode; `null` means no number is set for the film, so treat every episode as paid.
      
      ## Planned episodes
    ⋯
      | `title`, `synopsis`, `duration_ms`, `poster_uri` | `null` |
      
    - Never send a placeholder row to `POST /playback`: it has no episode ID. If a film has more published episodes than `planned_episodes`, all of them are still returned.
    + Never send a placeholder row to `POST /playback`: it has no episode ID. If a film has more published episodes than `planned_episodes`, all of them are still returned. When `planned_episodes` is `null`, the film has no placeholder rows.
      
      ## Readiness: `stream_ready`
    ⋯
  7. 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