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

Testing

Markdown
On this page

TL;DR — There is no sandbox: tests call https://www.wandura.ai. Keep test traffic in your test organisation (sample films only, plays never counted) and trigger any error on demand with the Wandura-Simulate header. Run your CI against a mock built from the OpenAPI file. Never load-test production. Then run the test plan below on real phones.

Where to test

Layer Use Counts as views?
Unit and CI tests A mock server generated from the OpenAPI file, for example prism mock https://docs.wandura.ai/developers/openapi/delivery-v1.json, or the fakes in the examples No (nothing reaches Wandura)
Integration tests Your test organisation's keys, against production No
Acceptance on real phones Your test organisation, then a final check in production Production: yes

Test organisation

Every partner gets one test organisation next to its production one. Wandura creates it on request in your team's Discord channel and adds your Admins and Developers to it. On partner.wandura.ai, switch to "Your organisation (test)" and create keys under Developers as usual. The examples on this page call such a key WANDURA_TEST_KEY.

Test keys call the same production URL, https://www.wandura.ai, and behave exactly like production keys, with three differences:

  1. Not counted. Its plays are never counted as views, usage or revenue.
  2. Sample films only. It can only stream Wandura's sample films ninety-days and the-fire-clause (short episodes, with English subtitles). Open video is not available in a test organisation.
  3. Simulated errors. It may send the Wandura-Simulate header (below). Production keys ignore that header completely.

GET /config tells you which kind of key you hold:

{
  "key": { "scopes": ["metadata:read", "playback"], "test_organisation": true }
}

Real states, on request. For what simulation cannot show (for example a key that really stops working, or a licence that really ends), ask in your channel: Wandura can suspend your test organisation, suspend or end the licence of a sample film, switch streaming off, or lower your playback limit to test 429 for real. Changes take effect within 30 seconds. The test organisation's playback limit is 600 tickets per minute.

Simulated errors

With a test key, send Wandura-Simulate: <scenario>. You get the same status, body and headers as the real error, plus Wandura-Simulated: <scenario> on the response. A simulated answer issues no ticket and does not count against your limits; simulated answers are themselves limited to 300 per minute per organisation. The key, scope and version checks still run first, so a bad key still answers 401. If the response has no Wandura-Simulated header, nothing was simulated (unknown name, or a scenario that does not apply to that endpoint) and the request ran normally.

Scenario Endpoints You get
rate_limited playback, catalog, config 429 rate_limited with Retry-After, X-RateLimit-Limit, X-RateLimit-Window
prefetch_shed playback 429 rate_limited, "reason": "prefetch_shed"
service_unavailable playback, catalog, config 503 service_unavailable, Retry-After: 1
service_unavailable:provider playback 503 service_unavailable (video provider), Retry-After: 2
service_unavailable:catalog catalog 503 service_unavailable (Could not read the catalog in time — retry)
server_error playback, catalog, config 500 with a JSON body carrying request_id, as for a real unexpected error
unsupported_version playback, catalog, config 400 unsupported_version with supported_versions, latest_version, upgrade_to
not_entitled playback 403 not_entitled, reason entitlement_not_found
not_entitled:<reason> playback 403 not_entitled with reason entitlement_suspended, streaming_disabled, outside_window or org_suspended
org_suspended playback, catalog, config Playback: as not_entitled:org_suspended; catalog and config: 403 with error org_suspended
not_ready playback 404 not_ready
not_ready:no_rendition playback 503 not_ready
sdk_required playback 409 sdk_required with protection
partial_batch playback, batch of 2–3 Item 0 is a real ticket (not counted, as in any test organisation); later items 503 with retry_after: 2, or 429 prefetch_shed
empty_catalog catalog 200 with empty films and episodes
version_deprecated catalog, config A real 200 plus Deprecation, Sunset and Link headers

In a batch, a per-episode scenario answers 200 { "items": [...] } with the error on each item, exactly like a real batch.

What cannot be simulated: an expired Player SDK licence (it lives on the device).

Example: rate_limited

curl -s -i https://www.wandura.ai/api/delivery/v1/catalog \
  -H "Authorization: Bearer $WANDURA_TEST_KEY" \
  -H "Wandura-Simulate: rate_limited"
HTTP/2 429
retry-after: 1
x-ratelimit-limit: 600
x-ratelimit-window: 60
wandura-simulated: rate_limited
{
  "error": "Too many catalog requests for this account. This is an abuse ceiling, not a quota — if a normal integration reaches it, contact us and it will be raised.",
  "error_code": "rate_limited"
}

Example: not_entitled:outside_window

No device values are needed: nothing is issued.

curl -s https://www.wandura.ai/api/delivery/v1/playback \
  -H "Authorization: Bearer $WANDURA_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Wandura-Simulate: not_entitled:outside_window" \
  -d '{ "film_ref": "ninety-days", "episode_no": 1, "intent": "play" }'
{
  "error": "outside_window",
  "error_code": "not_entitled",
  "reason": "outside_window"
}

Example: partial_batch

Item 0 is a real ticket, so send the device values of a real device (see Quickstart · Part B).

curl -s https://www.wandura.ai/api/delivery/v1/playback \
  -H "Authorization: Bearer $WANDURA_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Wandura-Simulate: partial_batch" \
  -d '{ "film_ref": "ninety-days", "episode_no": 1, "next": 2, "intent": "play",
        "union_info": "'"$UNION_INFO"'", "drm_kek": "'"$DRM_KEK"'", "viewer_ref": "qa-viewer-1:device-1" }'
{
  "items": [
    { "request": { "film_ref": "ninety-days", "episode_no": 1 }, "status": 200, "vid": "v0d2f8c1a9e4b7", "play_auth_token": "placeholder-play-token", "expires_at": "2026-10-02T12:30:00.000Z", "protection": "private-encrypted", "subtitles": [] },
    { "request": { "film_ref": "ninety-days", "episode_no": 2 }, "status": 503, "error": "The video provider did not answer in time — retry", "error_code": "service_unavailable", "retry_after": 2 },
    { "request": { "film_ref": "ninety-days", "episode_no": 3 }, "status": 429, "error": "Prefetch requests are paused while your playback traffic is close to its ceiling — tickets for viewers who pressed play are still issued. Retry the prefetch after Retry-After, or request it when the viewer plays.", "error_code": "rate_limited", "reason": "prefetch_shed", "retry_after": 1 }
  ]
}

What you can reproduce with any key

Scenario How
401 No key, or a revoked one (refused within about a second of revoking).
403 scope A key with only metadata:read, calling POST /playback.
400 invalid_device_info A device value of "(null)" or under 8 characters.
400 invalid_request Only one device value, or a malformed batch.
409 sdk_required Neither device value.
404 not_ready An unknown episode_id, or next: 2 on the last episode.
400 unsupported_version Wandura-Version: 1999-01-01.
Creatives 404 4040, 422 An unknown ID; a bad limit or cursor.
Expired ticket Pause playback for more than 30 minutes.

Load tests

Do not load-test production. To test your own system under load, mock Wandura. To test 429 handling against Wandura, use Wandura-Simulate: rate_limited, or ask for a lower limit on your test organisation.

Test plan

Run it on a release build, on a real iPhone and a real Android phone.

Keys and security

  • No wnd_live_ in the built apps.
  • No full key, play_auth_token or raw device value in your logs (Observability).
  • Catalog without a key: 401; with a key lacking metadata:read: 403. Your job alerts and keeps its copy.

Catalog

  • The films shown match the licences Wandura confirmed, in the API's order.
  • Free episodes open without payment; the next one shows your paywall.
  • Placeholders show "coming soon" and cannot be tapped; stream_ready: false episodes are greyed out.
  • With the sync job's network blocked for one run, the catalog in the app does not change.

Playback

  • A free episode plays, with subtitles; switching language works; an episode without subtitles plays.
  • A locked episode shows your paywall and makes no Wandura request.
  • Starting an episode sends one request (play + unlocked prefetches); moving on starts the next at once and sends a new play.
  • Pausing more than 30 minutes, then resuming, leads to one fresh ticket and playback from the same position.
  • Airplane mode mid-episode and back: recovery without a crash.
  • 429, 503, 500, not_entitled, not_ready and partial_batch, simulated with Wandura-Simulate, each show the right screen.

Rights ending

  • Ask Wandura to end the licence of one sample film in your test organisation. After the next two syncs it is hidden, and a ticket request answers 403 not_entitled.

Updated 2 Oct 2026 · Change history (2)

↑↓ selectEnter openEsc close

Send feedback

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

0 / 4000