The calls a playback client makes
A licensed media API answers four different questions, and it answers each of them on a separate endpoint with its own credentials. The catalog endpoint returns what an account may watch. The playback endpoint returns the material needed to start a title: a manifest URL, a licence endpoint, and usually a short-lived token. The licence endpoint releases decryption keys for that title and that session. The segment or CDN layer serves the encrypted media itself.
A client that authenticates to all four and keeps them in order can start playback and report progress without a player interface. The application owns the first two layers, and the platform CDM owns the licence exchange. That split explains why the traffic is uneven: the app's own calls carry the account authorisation, and the licence POST carries whatever the player was configured to send alongside the CDM message.
Who is asking, and what the server checks
Entitlement is an account question. The app sends a user credential, or a token derived from one, together with the content identifier, and the backend decides whether that account may watch that title in that country at that time. Device limits, subscription tier and concurrent stream counts are enforced here, and none of them can be bypassed by changing a header on a later call.
Licence acquisition is a client question. The licence server checks that the request comes from a recognised content decryption module and that it names a key the account is entitled to receive. A provisioned device supplies the module identity. The content identification in the manifest supplies the key identifiers. The app supplies the endpoint, the token and the timing.
Segments are a delivery question. They are usually plain HTTPS fetches of encrypted bytes with a signed URL or a CDN token in the query string, and the signature expires. A client that caches one segment URL and reuses it an hour later fails at the CDN rather than at the licence server.
The three checks fail independently, and each refusal reads differently in a capture. A JSON error from the app's backend means entitlement. A rejected licence POST means the CDM identity, the token or the key identifier. A CDN error on a segment means a signed URL that has aged out.
The order the calls have to happen in
- The client authenticates the account. A login or refresh call returns a token that the later calls in the flow reuse, and the token has a lifetime shorter than a feature session.
- The client asks for playback material. It sends the content identifier with the account token and receives a manifest URL, a licence URL and a playback session identifier, and sometimes one of those is fetched in a second call.
- The player reads the manifest. The manifest lists the tracks, the protection scheme and the key identifiers that the licence request will name.
- The client posts the licence request. The CDM produces the binary body, and the app attaches the token, the playback session identifier and any custom headers.
- The player fetches segments and reports progress. Control calls for heartbeat, concurrency and playback position run alongside the media requests, and some of them are what refresh the session.
State that has to survive between calls
The flow is stateful, and a client that treats the calls as independent breaks at the second one. Values that matter across steps include the account token and its refresh path, the manifest URL, the licence URL, the playback session identifier, and any CDN token that the player derives per segment.
Time matters as much as state. Entitlement tokens are short lived, licence responses are tied to the session that requested them, and signed segment URLs expire. A headless client needs the same renewal behaviour the app has, including the call it makes when a token expires mid playback. Reproducing that behaviour is the difference between a client that plays one title once and a client that can run inside a product.
Key identifiers add a second dimension. A stream can carry more than one key, and a track can switch keys at a boundary. The CDM batches what it needs into the licence request, so a reconstructed client has to combine the identifiers the same way the player does.
What a product team needs before commissioning work
Interoperability work starts from a working account and a running client, not from a key. The useful first pass is a map of the sequence: which call returns which value, which header or field carries the token, and which of the four layers refuses when something is wrong. That map is enough to plan an integration, a monitoring job, a migration off a discontinued app, or an automated quality check.
A rebuild is testable without CDM keys. An open source DRM implementation can exercise the app's session manager, callback and licence URL wiring, which lets a test verify the app's half of the API specification on a continuous basis. Checking that the entitlement call still returns a licence URL, and that the licence POST still carries the expected headers, catches a service change before it reaches users.
Once the sequence is written down, the deliverable is a client that performs it: a Python or TypeScript module with the token renewal, session tracking and TLS behaviour the server expects, plus documentation of each step and a Postman collection for manual runs. The client is then diffed against the app on the same account and the same title, and the remaining differences are narrowed the same way any request reproduction is narrowed.
Related work
Reviewed 28 September 2026 · SReverse research desk