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.
API reference

Request playback

Markdown
On this page

Issues a short-lived playback ticket for one episode. Your backend calls this each time a viewer starts an episode and passes the result to the Player SDK on the viewer's device.

POST /api/delivery/v1/playback

Scope: playback (create it yourself on Developers → Stream films in an app; if it leaks, anyone can stream your licensed films, so revoke it immediately)

Description

Wandura checks, on every request, that your organisation is active and that your streaming licence for the episode's film is active and inside its window. It then returns a play token bound to the viewer's device. Licensed episodes are encrypted and play only through the Player SDK, so you must send the device values union_info and drm_kek. See Playback.

Call it only from your backend. The endpoint sends no CORS headers.

Request parameters

Name In Type Required Description
Authorization header string Yes Bearer <API key> for a key with the playback scope.
Content-Type header string Recommended application/json. The body must be JSON.
episode_id body string (UUID) One of episode_id or film_ref + episode_no The episode's id from the catalog. Takes precedence if you also send film_ref.
film_ref body string With episode_no, if no episode_id The film's id or slug.
episode_no body integer With film_ref, if no episode_id Episode number, starting at 1. Must be a JSON number, not a string.
union_info body string Yes, for encrypted episodes Device ID generated by the Player SDK on the viewer's device. Send together with drm_kek.
drm_kek body string Yes, for encrypted episodes Device public key generated by the Player SDK. Send together with union_info.
intent body string No play when the viewer tapped the episode, prefetch when your app loads it ahead of a tap. Prefetch requests are not counted as plays. A missing or other value is recorded as unknown, never rejected, and counted as a play.
viewer_ref body string No Your own opaque session or device identifier, stored with the ticket for support lookups. Do not include personal data.

union_info and drm_kek are rejected with 400 invalid_device_info when, after trimming spaces, a value is shorter than 8 characters or is one of (null), null, nil, undefined, nan, <null> or none (in any letter case).

Request example

curl -s -X POST https://www.wandura.ai/api/delivery/v1/playback \
  -H "Authorization: Bearer $WANDURA_PLAYBACK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "film_ref": "the-heiress-returns",
    "episode_no": 1,
    "union_info": "<device ID from the Player SDK>",
    "drm_kek": "<device public key from the Player SDK>",
    "intent": "play",
    "viewer_ref": "u_48213:dev_9a7c"
  }'

Response

200 OK

Field Type Description
vid string Video ID to load in the Player SDK.
play_auth_token string Play token to hand to the Player SDK. Keep it secret and do not log it.
expires_at string (ISO 8601, UTC) When the ticket expires: 30 minutes after it was issued.
protection string Protection level of what you received. private-encrypted for licensed episodes. Only sell paid episodes when it is private-encrypted.
subtitles array Subtitles attached to the episode. Empty when none are attached.
subtitles[].lang string Language code, for example en, vi or pt-BR.
subtitles[].url string URL of the subtitle file. Not tied to the ticket's expiry.
subtitles[].format string Always webvtt.

Subtitles are returned in lang order.

Response example

{
  "vid": "v0d2f8c1a9e4b7",
  "play_auth_token": "eyJhbGciOi...placeholder...",
  "expires_at": "2026-10-01T12:30:00.000Z",
  "protection": "private-encrypted",
  "subtitles": [
    { "lang": "en", "url": "https://cdn.example.com/subtitles/heiress-ep1-en.vtt", "format": "webvtt" },
    { "lang": "vi", "url": "https://cdn.example.com/subtitles/heiress-ep1-vi.vtt", "format": "webvtt" }
  ]
}

Errors

Status error_code When
400 none The body is not valid JSON, or has neither episode_id nor film_ref with a numeric episode_no.
400 invalid_request Only one of union_info and drm_kek was sent.
400 invalid_device_info A device value looks empty or is too short. The fields array names it.
401 none The Authorization: Bearer header is missing, or the key is unknown or revoked.
403 none The key lacks the playback scope.
403 not_entitled Your organisation may not stream this film right now. reason is one of org_suspended, entitlement_not_found, entitlement_suspended, streaming_disabled, outside_window.
404 not_ready The film or episode is unknown, not published, or not ready to stream.
409 sdk_required The episode is encrypted and the request had no device values. The body also carries protection.
429 rate_limited The playback rate limit was reached. See Retry-After.
502 none The stream could not be prepared or the play token could not be signed. Retry with backoff.
503 not_ready No playable version of the episode is available right now.
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 The video provider did not answer in time (The video provider did not answer in time — retry). The episode is not missing: retry after Retry-After seconds, with backoff.

Example 403:

{
  "error": "outside_window",
  "error_code": "not_entitled",
  "reason": "outside_window"
}

See Errors for what to do in each case.

Updated 1 Oct 2026 · Change history (3)

↑↓ selectEnter openEsc close

Send feedback

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

0 / 4000