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

Integrate your app

Markdown
On this page

TL;DR — Your server syncs Wandura's catalog every 15–60 minutes into your own database. When a viewer presses play, your app checks its own paywall, your server asks Wandura for a ticket for that one episode (plus up to two prefetches for the next episodes), and the licensed Player SDK plays it. You never hold Wandura's video keys: every ticket is checked against your licence and recorded by Wandura. Go-live = the checklist in Phase 6. Other model? See Choose an integration model. Checklist and licence price: Before you start.

This guide takes your team from a signed agreement to a live app that streams Wandura films. It follows the order a real integration runs in: what Wandura sets up for you, keys, a catalog sync job in your backend, the playback flow, the optional ad creatives feed, a test plan and a go-live checklist. Each phase links to the reference pages for the detail.

The model is simple. Your app decides whether a viewer may watch an episode (free episodes, coins, subscriptions, VIP). Wandura decides whether your app may stream the film (your licence), signs a short-lived ticket and records the play. Your app never holds the keys to Wandura's video store: your server asks Wandura for a ticket each time.

0 · Setup by Wandura1 · Keys2 · Catalog sync job3 · Playback flow4 · Creatives feed (optional)5 · Test plan6 · Go-live

Who does what

Area Wandura Your team
Films Produces, encodes and protects every film and episode. Keeps titles, synopses, posters, genres, display order and subtitles up to date. Shows them in your app, in the order and with the text you receive.
Rights Grants your organisation a streaming licence per film, with a licence window (a start date, an end date, both or neither), and checks it on every ticket request. Follows any other limits in your contract, for example the countries where your app may show a film.
Viewers and money Nothing. The API has no per-viewer identity. Accounts, sign-in, paywall, free episodes, coins, subscriptions, VIP, refunds and viewer support.
Keys Issues the key that can play video. Lets your developers create read-only keys themselves. Keeps every key on your servers, rotates and revokes keys, never ships a key inside an app.
Player Registers your app IDs and issues the Player SDK licence; your organisation pays for it. Integrates the Player SDK in your apps and follows the Player SDK guide on the portal.
Playback Signs a ticket for one episode on one device, and records the play. Requests a ticket only for episodes the viewer may watch, and hands it to the player.
Usage Counts plays per film from your ticket requests. Marks prefetch requests as prefetches, so they are not counted as plays.

Phase 0: What Wandura sets up for you

Before your developers write any code, Wandura sets up the items below. Ask for each one by name in your team's Wandura Discord channel; the order of the steps is in Get onboarded.

Item What it is What you give Wandura
Organisation Your team's workspace on partner.wandura.ai. Every key and licence belongs to it. Your organisation name and the email of the person who will be its Admin.
Developer access Your backend developers get the Developer role. It opens only the Developers page, where keys are managed. Your organisation Admin can manage keys too. The emails of your developers.
Film licences A streaming licence for each film you may show. Its window can have a start date, an end date, both or neither. The list of films and dates in your agreement.
Playback key An API key with the playback scope. Your developers create it themselves on the Developers page, one per environment. If it leaks, anyone can stream your licensed films, so revoke it immediately. Nothing: you create it yourself.
Player SDK licence Wandura registers your app IDs and issues the Player SDK licence; your organisation pays for it. It comes with access to the Player SDK guide on partner.wandura.ai → Developers → Player SDK. The iOS bundle ID and Android package name your app will ship with, not temporary ones.

How roles work on the portal is explained in Roles.

Licence dates are whole days in UTC, and both the first and the last day are included. A licence without a start date applies from the moment it is granted; one without an end date runs until Wandura ends it. Wandura can also switch a licence off before its end date. You do not need to track dates yourself: the catalog lists only the films whose licence is active today.

Done when: your developers can sign in to partner.wandura.ai and open Developers, you have received the Player SDK licence, and Wandura has confirmed the list of licensed films. Your developers create the playback key themselves in Phase 1.

Phase 1: Keys and environments

Every call goes to one base URL, https://www.wandura.ai, and only from your servers. The endpoints send no CORS headers, and a key shipped inside an app can be extracted. Authentication shows how to send a key.

Use one key per system and per environment, with only the scopes that system needs:

System in your backend Scope Who creates the key
Catalog sync job metadata:read Your developers, on the Developers page
Playback service (the server that requests tickets) playback (with metadata:read: pick Stream films in an app) Your developers, on the Developers page
Marketing sync job (only if you use Phase 4) creatives:export Your developers, on the Developers page

Rules that save you an incident later:

  • Store keys in a secrets manager and read them as environment variables. Never commit them, and never put them in an app.
  • Give staging and production different keys, so you can revoke one without touching the other.
  • If a playback key leaks, anyone can stream your licensed films. Any Admin or Developer of your organisation can rotate or revoke it on the Developers page: revoke it immediately if you think it has leaked. To switch without downtime, create a second playback key, deploy it, then revoke the old one. Wandura is alerted whenever a new playback key is created or rotated.
  • Never log a full key or a play_auth_token. When you talk to Wandura, quote the key prefix shown on the Developers page.

Creating, rotating and revoking keys step by step: Developer keys.

Test and production

There is no sandbox. Staging and production call the same base URL, https://www.wandura.ai, and get the same answers; what keeps test traffic apart is the organisation and the key.

  • Test organisation. Wandura decides whether you test in a separate test organisation. It works like any other organisation: its own members, keys and film licences.
  • Test films. The films you test with are licensed to the organisation you test in. Ask for them in your team's Wandura Discord channel.
  • Test plays. Every ticket request is recorded, test ones included. Put a prefix such as qa- in viewer_ref for test traffic, and tell Wandura which organisation is your test one.

Done when: each backend system has its own key in your secrets manager, and a GET /api/delivery/v1/catalog call from your staging server returns 200.

Phase 2: Catalog sync job

Build a job in your backend that copies the Wandura catalog into your own database. Your app reads films from your database: never from Wandura directly, and never from a second film list that someone maintains by hand.

Your appYour databaseWandura Delivery APIYour sync jobloop[Every 15 to 60 minutes]GET /api/delivery/v1/catalogfilms and episodes (the full catalog)Upsert rows, mark missing rows unavailableHome, film page, episode list

How often

Run the job every 15 to 60 minutes, and let someone trigger it by hand when Wandura tells you about a new release. The catalog sends no change notifications, so polling is how you see changes. Do not call the catalog on app launch: serve it from your server.

No cursor, no pagination

Each response is the complete catalog your organisation may stream at that moment. There is no cursor, page or updated_since parameter. Treat every response as a snapshot and compare it with your copy.

What to store

Store Key Fields to keep Used for
Films films[].id title, slug, synopsis_short, synopsis_full, poster_url, genres, language, audience, form, setting, display_order, planned_episodes, free_until_episode Home, browse filters, film page, your paywall rule
Episodes episodes[].id, or film_id + episode_no episode_no, title, synopsis, duration_ms, poster_uri, status, stream_ready Episode list, "coming soon" tiles, the ticket request
Both — When you last saw the row in a response Detecting withdrawals

Every field is described in the catalog reference. The points that matter for a sync job:

  • Order. Films arrive sorted by display_order. Keep that order; Wandura edits it.
  • Free episodes. Episodes with episode_no up to and including free_until_episode are free. Read it on every sync, because it can change.
  • Coming soon. Rows with "id": null and "status": "planned" stand for episodes that are not published yet. Show them as "coming soon" and never send them to playback.
  • Readiness. Grey out or hide episodes with "stream_ready": false.
  • Artwork and text. poster_url and synopsis_full can be null: show a placeholder image, or nothing. The episode poster_uri is not guaranteed to be a loadable URL, so fall back to the film poster.
  • Subtitles are not in the catalog. They come with each playback ticket; see Phase 3.

Your own publish gate

You decide when a film appears in your app. A simple rule that avoids empty or broken tiles: show a film only when it has a title, a poster and at least its first episode with "stream_ready": true. Keep films that fail the rule in your database and check them again on the next sync.

Withdrawn films and episodes

A film leaves the catalog when your licence for it ends or is switched off, or when the film is withdrawn. An episode leaves the catalog when it is withdrawn. Nothing announces it: the row is simply missing from the next response.

When a row is missing:

  1. Mark it unavailable in your database, and stop showing and selling it. Do not delete it: your viewers' purchases and watch history still point at it.
  2. If it comes back in a later response, for example after a licence renewal, mark it available again.
  3. If the call fails (any status other than 200), keep your previous copy and try again on the next run. Never treat a failed call as an empty catalog.

A stale copy cannot let anyone watch a withdrawn film: every ticket request checks your licence again, and the ticket answer is the one that counts.

Done when: your staging app shows the licensed films in Wandura's order, from your own database, with free episodes, "coming soon" tiles and greyed-out episodes shown correctly.

Phase 3: Playback flow

When a viewer taps an episode, your backend first applies your own paywall. Only if the viewer may watch does it ask Wandura for a ticket.

Wandura streaming networkWandura Delivery APIYour backendYour app (Player SDK)alt[Viewer may not watch][Viewer may watch]ViewerTaps an episodePlayer SDK gives device ID and device public keyPlay request (your session, episode, device values)Your paywall - free, unlocked or VIP?Locked - show your paywallPOST /api/delivery/v1/playback (intent play)Check licence, sign ticket, record playvid, play_auth_token, expires_at, protection, subtitlesCheck protection is private-encryptedvid, play_auth_token, subtitlesPlayer SDK loads the encrypted streamVideo playsUp to 2 requests for the next episodes (intent prefetch)

1. Check your paywall first

Wandura checks only that your organisation may stream the film. It does not know your viewers, so it issues a ticket for any episode of a licensed film. Keeping locked episodes locked is your backend's job: never request a ticket for an episode the viewer has not unlocked.

2. Request the ticket from your server

Your backend calls POST /api/delivery/v1/playback with the playback key and sends the episode (episode_id, or film_ref and episode_no), the two device values from the Player SDK (union_info and drm_kek), your own viewer_ref and "intent": "play". The full request and response are in the playback reference and on Playback.

  • Send the device values exactly as the Player SDK produced them. If an SDK call returns nothing, fix the app rather than sending a placeholder string. See sending the device values.
  • Set viewer_ref to an opaque ID of your own, such as <user-id>:<device-id>. Never put an email address or a name in it.
  • Before returning the answer to the app, check that protection is private-encrypted. If it is anything else, do not play or sell the episode, and contact Wandura.

3. Play on the device

The app passes vid and play_auth_token to the Player SDK and starts playback. The SDK fetches the encrypted stream and its keys by itself. A standard video player cannot play these episodes: it loads the playlist and then stalls. Follow every setup step in the Player SDK guide on the portal (Developers → Player SDK); a missed step often shows up only as a player that never starts.

4. Prefetch the next two episodes

Short dramas are watched back to back, so the next episode should start at once. Right after the current episode starts, your backend requests tickets for up to the next two episodes, with "intent": "prefetch", so the app can load them ahead of time.

  • Each request covers one episode, so this means up to two extra requests. There is no batch request.
  • Apply your paywall to each of them. Do not prefetch an episode the viewer has not unlocked.
  • Skip placeholder rows and episodes with "stream_ready": false.
  • A prefetch is not counted as a play. When the viewer actually moves on to the next episode, that is a new play start: request its ticket with "intent": "play", and prefetch the two after it.
  • Every request, prefetches included, counts toward your organisation's rate limit. Never request tickets for a whole film.

5. Expiry and retry

A ticket is valid for 30 minutes; expires_at gives the exact time. Do not keep tickets between play starts. When the Player SDK reports an error during playback, including an expired ticket:

  1. Request one fresh ticket and reload the player at the current position.
  2. If that request fails, map its error_code to what the viewer sees, using the table below. Retry once, not in a loop.

A prefetched ticket that expired before the viewer reached the episode is simply replaced by a new request.

6. Subtitles

Each ticket response lists the episode's subtitles as WebVTT files, one per language. An empty list means none are attached yet; it is not an error. Subtitle URLs outlive the ticket, so you can cache them per episode; when Wandura replaces a subtitle, its URL changes, so refresh the list from the next ticket. In a web player, download the file with fetch and add the cues yourself, instead of a <track> element with crossorigin. See Subtitles.

What the viewer sees for each answer

Branch on error_code, keep a default branch for codes you do not know, and never show Wandura's error text to viewers.

Answer What it means What the viewer sees What your backend does
Your paywall says locked No call to Wandura Your paywall or unlock screen Nothing
200 Ticket issued The episode plays Check protection, then prefetch
403 not_entitled Your licence for this film is not active right now "This title is no longer available" Stop selling the film, log reason, refresh the catalog
404 not_ready Episode unknown, withdrawn or not ready "Not available yet" Refresh the catalog
503 not_ready No playable version right now "Not available yet, try again later" Retry later
400 invalid_request or invalid_device_info, 409 sdk_required A bug in how your app reads the Player SDK values "Couldn't load this episode" Alert your engineers; do not retry
401, or 403 without error_code Wrong, revoked or unscoped key "Couldn't load this episode" Alert your engineers; check the key
503 service_unavailable Wandura could not verify your key in time; the key is fine "Couldn't load this episode, try again" Retry after Retry-After, with backoff; do not rotate the key
429 rate_limited Too many requests "Busy, try again in a moment" Wait for Retry-After, then find the loop
502 Temporary problem on Wandura's side "Couldn't load this episode" Retry with backoff, then give up

Every code, with its exact body, is listed in Errors.

Done when: on a real iPhone and a real Android phone, a free episode plays with subtitles, a locked episode shows your paywall without any call to Wandura, and the next episode starts without a wait.

Phase 4: Ad creatives feed (optional)

Skip this phase unless your organisation builds ad creatives from Wandura films on partner.wandura.ai. If it does, your marketing systems can sync a record of each approved creative.

  1. Create a key with the creatives:export scope on the Developers page.
  2. Sync incrementally: page through GET /api/delivery/v1/creatives with cursor, keep the largest updated_at as a checkpoint, and pass it as updated_since on the next run.
  3. Store records keyed by creative_id, and overwrite them when they arrive again.
  4. rights.ends_at is 00:00 UTC of the last day of your export rights, and that day is included: stop using a creative after that UTC day ends, at rights.ends_at + 86400. To check a stored creative, call GET /api/delivery/v1/creatives/{id}: 404 with code 4040 means it is no longer available.

Records describe each creative and never include a media URL. Ask Wandura how final video files reach your systems. Details: Creatives.

Phase 5: Test plan

A QA engineer can run this list on a staging build against your staging backend, in the organisation you test in (see Test and production). Use real phones for playback. There is no sandbox, and every ticket request is recorded, test ones included: put a recognisable prefix such as qa- in viewer_ref for test traffic, and tell Wandura which organisation is your test one.

Keys and security

  • Search the built iOS and Android apps for wnd_live_. There must be no match.
  • Backend logs contain no full API key and no play_auth_token.
  • A catalog call without a key returns 401, and one with a key that lacks metadata:read returns 403. Your job raises an alert and keeps its previous copy.

Catalog

  • The films in the app match the licence list confirmed by Wandura.
  • Films appear in the same order as in the API response.
  • Episodes up to free_until_episode open without payment; the next one shows your paywall.
  • Placeholder episodes show "coming soon" and cannot be tapped.
  • Episodes with "stream_ready": false are greyed out or hidden.
  • A film without a poster shows your placeholder image, not an empty box.
  • When one sync run fails (for example, with the network blocked for the job), the catalog in the app stays unchanged.

Playback

  • A free episode plays on a real iPhone and a real Android phone.
  • Subtitles appear, and switching language works. An episode without subtitles plays without an error.
  • A locked episode shows your paywall, and your backend logs show no ticket request for it.
  • After unlocking, the same episode plays.
  • While an episode plays, the backend requests the next two episodes with "intent": "prefetch", and skips any the viewer has not unlocked.
  • Moving on to the next episode starts it quickly and sends a new "intent": "play" request.
  • Pausing for more than 30 minutes and then resuming leads to one fresh ticket and playback from the same position.
  • Switching the phone to airplane mode mid-episode and back again recovers without a crash.
  • A backend test that sends "(null)" as a device value receives 400 invalid_device_info and raises an alert.

Rights ending

  • Ask in your team's Wandura Discord channel to end the licence of one test film in the organisation you test in. After the next sync the film is hidden, and a ticket request for it returns 403 not_entitled, which the app shows as "no longer available".
  • Viewers who had paid for that film see the message agreed with your support team.

Phase 6: Go-live

Checklist

  • Production keys are issued and stored, separate from staging keys.
  • The Player SDK licence covers the bundle ID and package name of the production apps.
  • Wandura has confirmed the licensed films and their licence windows.
  • The catalog sync job runs on schedule in production, with an alert on failure.
  • The paywall reads free_until_episode from your synced catalog.
  • The backend checks protection on every ticket.
  • Every answer in the Phase 3 table maps to a screen, and unknown codes fall into a default branch.
  • Your on-call runbook names who revokes the playback key if it leaks (any Admin or Developer of your organisation) and who tells Wandura.
  • The whole test plan passed on the release build.

What to monitor

Signal Where Why
Ticket success rate, and answers by error_code Your backend metrics A jump in not_entitled usually means a licence ended; in invalid_device_info or sdk_required, that an app release broke the Player SDK wiring; in rate_limited, a retry loop.
5xx answers and ticket latency Your backend metrics Retry with backoff, and tell Wandura if it lasts.
Last successful catalog sync, number of films and of playable episodes Your sync job A stalled job keeps showing withdrawn titles; a sudden drop is worth a message to Wandura.
"Last used" of each key Developers page Finds unused keys you can revoke.

When rights end

  • Licence end date. The last day of the window is included (UTC). From the next day the film is missing from the catalog, and ticket requests for it return 403 not_entitled.
  • Licence switched off early, or organisation suspended. New ticket requests are refused right away. A suspended organisation also gets 403 from the catalog.
  • Sessions already playing. Tickets already issued are never extended. Design the app so that playback can end with a player error at any time, and follow the retry steps in Phase 3.
  • Your side. Stop selling the film, apply your refund policy, and stop using its creatives once the UTC day of rights.ends_at has ended.
  • Renewal. A renewed film comes back in the next sync; mark it available again.

Who to contact

Need Contact
Organisation setup, film licences and dates, the Player SDK licence, a rights-end test Wandura, in your team's Wandura Discord channel
The Developer role for a new developer Your organisation Admin on partner.wandura.ai
Every key, playback keys included: create, rotate, revoke Your developers, on the Developers page
A playback key that may have leaked An Admin or Developer of your organisation revokes it first, then tells Wandura
Repeated 5xx answers or other outages Wandura, in your team's Wandura Discord channel, with the details listed in Support

Updated 1 Oct 2026 · Change history (7)

↑↓ selectEnter openEsc close

Send feedback

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

0 / 4000