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

Playback and tickets

Markdown
On this page

TL;DR — To play an episode, your backend asks POST /playback for a ticket: a token for one episode on one device, valid 30 minutes. Send the two device values from the Player SDK, your own stable viewer_ref, and "intent": "play" when a viewer starts an episode. One call can return up to 3 tickets (the episode and the next two). Reusing a ticket for the same viewer, device and episode is fine until 5 minutes before it expires.

When to request a ticket

  • When a viewer starts an episode: always a request with "intent": "play" for it. That request is what counts the view.
  • Ahead of time for the next one or two episodes, with "intent": "prefetch", in the same request (next or episodes). Prefetches are not views.
  • Once more when the Player SDK reports an error, an expired ticket included.

Never request tickets for a whole film, and never for an episode your paywall has not unlocked: Wandura checks your licence, not your viewers. The lifetime, reuse and batch rules are in one place: Canonical API behaviour · Playback tickets.

Identify the episode

Option Fields Example
By episode ID episode_id "episode_id": "b2a4d6e8-1c3f-4a5b-8d7e-9f0a1b2c3d4e"
By film and number film_ref (film ID or slug) and episode_no (a JSON number from 1) "film_ref": "the-heiress-returns", "episode_no": 3

If you send both, episode_id wins. Use the same form each time for the same episode: ticket reuse matches the episode as you sent it.

Send the device values

Licensed episodes are encrypted, and only the Player SDK can decrypt them. Before each request, your app reads two values from the SDK and sends them to your backend:

Field What it is
union_info The device ID generated by the Player SDK.
drm_kek The device public key generated by the Player SDK. Its private key never leaves the device.
  • Send both or neither. Only one: 400 invalid_request.
  • Send the real SDK output. A value is rejected with 400 invalid_device_info when, after trimming, it is shorter than 8 characters or is (null), null, nil, undefined, nan, <null> or none (any case). fields names it.
  • Neither, for an encrypted episode: 409 sdk_required.

How to read them in the app: Player SDK.

What the ticket contains

Field Description
vid The video ID to load in the Player SDK.
play_auth_token The token for the Player SDK. A secret: see Security.
expires_at When it expires (ISO 8601, UTC).
protection private-encrypted for licensed episodes.
subtitles WebVTT files, one per language; can be empty. See Subtitles.

Check protection on every ticket. Sell paid episodes only when it is private-encrypted. Any other value: do not play it, and tell Wandura.

A batch answers { "items": [...] } in request order, each item with its own status. Every field: Request playback.

intent

Value Meaning Counted as a view
play The viewer just started the episode. Yes
prefetch Your app loads it ahead of time. No
missing or anything else Recorded as unknown, never rejected. Yes

Near your rate limit, prefetch tickets are refused first (429 with "reason": "prefetch_shed") so that play tickets keep flowing. A refused prefetch is not an error for the viewer: request the episode again with "intent": "play" when the viewer gets there. See Rate limits.

viewer_ref

An optional opaque string of yours, at most 256 characters, stored with the ticket for support lookups. Make it stable per viewer and device and free of personal data, for example an HMAC of your user ID plus a hash of your install ID. With it, Wandura can return the same ticket to a repeat request instead of issuing (and counting) a new one. Privacy and retention: Security.

Expiry and recovery

A ticket lives 30 minutes (expires_at). When the Player SDK reports an error during playback, an expired ticket included:

  1. Request one fresh ticket and reload the player at the current position.
  2. If that fails, map its error_code to a viewer message (Errors).

Do not branch on the Player SDK's own error codes (they change between versions) and never retry in a loop. When the app comes back from the background with less than a minute left, replace the ticket before resuming.

Updated 3 Oct 2026 · Change history (9)

↑↓ selectEnter openEsc close

Send feedback

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

0 / 4000