On this page
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
GET /api/delivery/v1/catalog returns a film when all of these are true at the moment of the request:
- 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.
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.
The catalog contains metadata only. It never contains a video URL; you request playback per episode with POST /playback.
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.
The whole catalog comes back in one response. There is no pagination.
Order
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.
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.
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.
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:
| Field | Value |
|---|---|
id |
null |
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
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.
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.
Genre facets
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.
| Field | Possible values |
|---|---|
audience |
women, men, lgbtq, or null |
form |
live_action, anime, or null |
setting |
modern, city, fantasy, campus, palace, or null |
Films also carry genres, an array of free-text genre labels, and language.
Text and artwork
synopsis_shortis meant for cards andsynopsis_fullfor detail pages. Lengths vary between films, so clamp text in your UI.synopsis_fullcan benull.episodes[].synopsiscan benull. Render nothing when it is.poster_url(film) andposter_uri(episode) can benullwhile artwork is being prepared. Show a placeholder image.
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.
The catalog has its own rate-limit counter, separate from playback and creatives. See Rate limits.
Updated 1 Oct 2026 · Change history (3)