# Signed playback

A playback link tells a player where the video is. If anyone who finds the link can play it, then the link is the only thing between a paying audience and a free one. Signed playback fixes that. The link carries a token, the token is made for one viewer's session, and it expires.

## Public and signed

Every live stream and asset has one or more **playback ids** (they start `pb_`). The id has a policy.

| Policy | Who can play |
|---|---|
| `signed` | Only someone holding a playback token that Vabu or you signed. This is the default. |
| `public` | Anyone who has the link. Use it for free content such as a trailer or the free part of a show. |

Add or remove one with `POST /v1/streams/playback_ids` and `DELETE /v1/streams/playback_ids/{id}`:

```http
POST /v1/streams/playback_ids
Idempotency-Key: trailer-public-1

{ "resource": "ast_...", "policy": "public" }
```

When you open a session, Vabu prefers a signed playback id, because the token is what ties playback to that session.

## Vabu signs the link for you

This is the normal way. You do nothing about tokens. A session open does it:

1. Vabu checks the viewer's entitlement and limits.
2. It signs a token for the session and puts it in the playback link.
3. Each heartbeat signs a fresh one.

The token holds the playback id, an expiry and an opaque viewer id. The viewer id is a keyed hash made for Vabu's own use, such as an on-screen watermark. It never contains the customer id you chose. Read [playback and sessions](https://docs.vabu.live/concepts/playback-and-sessions.md) for the flow.

## How long a link lasts

A token lives for the session's length plus 10 minutes, so about 11 minutes. That grace period keeps a stream playing through a short network drop. It also means access does not stop to the second.

| What you do | What happens to a link already in a viewer's player |
|---|---|
| Revoke the entitlement | New sessions are refused at once. The link in use keeps working until its token expires, at most about 11 minutes. The session ends at its next heartbeat. |
| Revoke a customer token key | New sessions with that key stop at once. Links already issued work until they expire. |
| Share the link with a friend | It works for the rest of its token, then stops. The friend cannot get a new one without an entitlement. |

Short links are the reason a shared link is not a way around payment. Combine them with [device limits](https://docs.vabu.live/guides/streams/paid-access.md#limit-devices) so one ticket means one screen.

## Sign tokens yourself

Some products need to decide access on their own, with Vabu off the viewer's path. Then you sign playback tokens yourself with a **signing key**.

```http
POST /v1/streams/signing_keys
```

The response holds a `key_id` and a `private_key`. The private key is shown once, and Vabu keeps only a fingerprint of it. Sign tokens with `RS256`, put the `key_id` in the token header as `kid`, set `sub` to the playback id and `aud` to `v`, and add an `exp`. List keys with `GET /v1/streams/signing_keys` and revoke one with `DELETE /v1/streams/signing_keys/{id}`.

This is only for accounts with their own video environment. For everyone else the call returns `409 dedicated_environment_required`, because a key shared between customers could sign playback for another customer's streams. Ask your Vabu contact if you need it.

## Errors

| Code | HTTP | Meaning |
|---|---|---|
| `signing_not_configured` | 409 | Playback signing is not set up for the account. Contact Vabu. |
| `no_playback_id` | 409 | The stream or asset has no playback id yet. Create one. |
| `dedicated_environment_required` | 409 | Signing keys are not available for this account. |
| `resource_not_found` | 404 | The stream or asset is not yours. |
