Endpoints

Private Playback

Mint a short-lived, origin-bound grant, then stream the exact private source bytes. Media authorizes by grant secret, not the bearer token; an allowlisted Origin is required on mint, revoke, and media requests. Media responses are binary with no JSON envelope.

POST/v1/runtimes/:runtimeId/private-playback-grantsMint one short-lived, origin-bound grant for exact private source bytes.

studio.private-playback-grant.v1

Grant Response

response
grantIdstring

Grant identity, also embedded in mediaPath.

sourceobject

Exact session, revision, artifact, content id, bytes, and duration.

mimeTypestring

One of nine allowed audio/video types; nothing else is served.

timestampOrigin{ kind: "source_media_zero", offsetMs: 0 }

Playback time zero is source time zero.

mediaPathstring

Relative media URL embedding the grant secret.

expiresAtstring

Ten minutes after issue.

Request
curl -X POST http://127.0.0.1:4312/v1/runtimes/$RUNTIME_ID/private-playback-grants \
  -H "Authorization: Bearer $TOKEN" \
  -H "Origin: $ORIGIN" \
  -H "Content-Type: application/json" \
  -d '{
  "schema": "studio.private-playback-grant-request.v1",
  "source": {
    "revisionId": "source-revision:6800f536f61f5d73dc474443cf0469c823ae94a984a209192940fc28b94afa09",
    "artifactId": "artifact:9f49fcb0eb07542cf19ca6e6e70d4d8aab491ff85abe2bd09658666ae5e4ae70",
    "contentId": "sha256:e141cd9d0a693f70d7e069deb4bf2b300af64a1a89b0b8e806e7aae6be1c924e"
  }
}'
201Response
{
    "schema": "studio.private-playback-grant.v1",
    "grantId": "private-playback-grant:2461c035-c98b-4a83-af69-8425e6327cc2",
    "runtimeId": "runtime:da4ff907-4240-42c7-8f14-deb6e2ce236a",
    "source": {
        "sessionId": "source-session:50e48113837e62499233f29f53ab91f5ed591d39bda98879effb02364e2a03a2",
        "revisionId": "source-revision:6800f536f61f5d73dc474443cf0469c823ae94a984a209192940fc28b94afa09",
        "artifactId": "artifact:9f49fcb0eb07542cf19ca6e6e70d4d8aab491ff85abe2bd09658666ae5e4ae70",
        "contentId": "sha256:e141cd9d0a693f70d7e069deb4bf2b300af64a1a89b0b8e806e7aae6be1c924e",
        "bytes": 329662,
        "durationMs": 47200
    },
    "mimeType": "audio/mp4",
    "timestampOrigin": {
        "kind": "source_media_zero",
        "offsetMs": 0
    },
    "mediaPath": "/v1/private-source-media/private-playback-grant%3A2461c035-c98b-4a83-af69-8425e6327cc2/C8-YHWaCCQbC5Sv99XeK4i8jLDAFUo5wjHATeyJ8i48",
    "issuedAt": "2026-07-19T17:39:56.085Z",
    "expiresAt": "2026-07-19T17:49:56.085Z"
}
POST/v1/runtimes/:runtimeId/private-playback-grants/:grantId/revocationsRevoke an active playback grant before it expires.

studio.private-playback-grant-revoked.v1

Revocation Request

application/json
schema"studio.private-playback-grant-revocation.v1"required

Literal schema tag; the path already names the grant.

Request
curl -X POST http://127.0.0.1:4312/v1/runtimes/$RUNTIME_ID/private-playback-grants/$GRANT_ID/revocations \
  -H "Authorization: Bearer $TOKEN" \
  -H "Origin: $ORIGIN" \
  -H "Content-Type: application/json" \
  -d '{
  "schema": "studio.private-playback-grant-revocation.v1"
}'
200Response
{
    "schema": "studio.private-playback-grant-revoked.v1",
    "grantId": "private-playback-grant:2461c035-c98b-4a83-af69-8425e6327cc2",
    "runtimeId": "runtime:da4ff907-4240-42c7-8f14-deb6e2ce236a",
    "state": "revoked",
    "revokedAt": "2026-07-19T17:39:56.087Z"
}
GETHEAD/v1/private-source-media/:grantId/:secretStream granted media bytes with HTTP Range support. Binary response, no JSON envelope. Origin required; grant-secret path auth (not bearer). 200 full / 206 Range; failures 403/404/410/416.

binary media stream

Request
curl -I http://127.0.0.1:4312/v1/private-source-media/$GRANT_ID/$SECRET \
  -H "Origin: $ORIGIN" \
  -H "Range: bytes=0-1023"
206Responseillustrative
HTTP/1.1 206 Partial Content
Content-Type: audio/mp4
Content-Length: 8
Content-Range: bytes 0-7/329662
Accept-Ranges: bytes
Cache-Control: private, no-store, max-age=0
Access-Control-Allow-Origin: $ORIGIN

(binary media octets; not shown)

# Auth: allowlisted Origin required. Path :grantId/:secret authorizes the stream
# (not the bearer token). Full GET without Range returns 200 with the same header
# family. HEAD returns the same status and headers with an empty body.
# Failures use the JSON error envelope: 403 missing/disallowed Origin, 404 unknown
# or wrong secret, 410 revoked or expired, 416 unsatisfiable Range, 400 any query
# string, 405 non-GET/HEAD.
# Private loopback bytes only. Not a CDN URL and not publication.