# Content delivery API reference

> Canonical HTML: https://screenrig.ai/docs/api/protected
> Source SHA-256: e0c997a2ab813502f0d99a41d2ed1d3d6b26dbaf1a3d7e514c1cce0278ff8422

Protected content and release assets. This group has 8 operations, each with its authentication, parameters, request body fields, request template and responses. The [API overview](https://screenrig.ai/docs/api.md) covers services, authentication, requests and retries, problem codes and versioning.

Replace uppercase placeholders. Save a schema-valid JSON body in request.json when required. Cookie examples use a local cookie jar from an authenticated session.

## Protected content and release assets

### GET /screen/ad-decisions/{decision_id}

**Get Ad Decision Content**

Serves the one private object bound to an issued decision. Authority is the live paired identity plus the decision binding; the buyer project and media ID are resolved server-side, never from the caller, and no object key or signed URL is published. A zero-length probe returns metadata only.


Operation: getAdDecisionContent.

- Authentication: runtimeCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| decision_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/screen/ad-decisions/DECISION_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Complete decision-bound private media. | no body; headers: Accept-Ranges, Content-Length, ETag |
| 206 | One standards-correct byte range. | no body; headers: Accept-Ranges, Content-Range, Content-Length, ETag |
| 404 | not_found - unknown decision. | RuntimeProblem (application/problem+json) |
| 410 | decision expired or otherwise not servable. | RuntimeProblem (application/problem+json) |
| 416 | invalid_range. | RuntimeProblem (application/problem+json); headers: Content-Range, Accept-Ranges |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### HEAD /screen/ad-decisions/{decision_id}

**Head Ad Decision Content**

Identical authority and metadata to the GET with no body.


Operation: headAdDecisionContent.

- Authentication: runtimeCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| decision_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |

#### Request template

~~~sh
curl --request HEAD --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/screen/ad-decisions/DECISION_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Metadata only. | no body; headers: Accept-Ranges, Content-Length, ETag |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /media/{media_id}

**Get Stable Protected Media**

Stable immutable media URL shared across playlist revisions. The runtime session identifies the screen and project for authorization and bandwidth accounting.

Every request requires membership in that screen's desired, active, or unexpired transition-grace grant in its current content-access generation, or a media:<id> reference in the current document of a card data key such a grant lists. IDs alone grant no access. ETag is the quoted sha256 of the bytes.

Browser cookie and native session authentication remain on the trusted Player origin; redirects and public object-storage access are not used.


Operation: getStableProtectedMedia.

- Authentication: runtimeCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| media_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/media/MEDIA_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Session-authorized complete private media. Browser Fetch Metadata must describe trusted-player same-origin media/image/video use; authenticated native clients may omit it. | no body; headers: Accept-Ranges, Content-Length, ETag, Content-Disposition |
| 206 | One standards-correct byte range. | no body; headers: Accept-Ranges, Content-Range, Content-Length, ETag |
| 416 | Unsatisfiable, multiple, or malformed range. | RuntimeProblem (application/problem+json); headers: Content-Range, Accept-Ranges |
| 429 | Per-client, screen, or organization protected-media egress limit exceeded. | RuntimeProblem (application/problem+json); headers: Retry-After |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### HEAD /media/{media_id}

**Head Stable Protected Media**

Session-authorized immutable media metadata with the same grant checks as GET and no response body.


Operation: headStableProtectedMedia.

- Authentication: runtimeCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| media_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request HEAD --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/media/MEDIA_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Session-authorized complete private media. Browser Fetch Metadata must describe trusted-player same-origin media/image/video use; authenticated native clients may omit it. | no body; headers: Accept-Ranges, Content-Length, ETag, Content-Disposition |
| 206 | One standards-correct byte range. | no body; headers: Accept-Ranges, Content-Range, Content-Length, ETag |
| 416 | Unsatisfiable, multiple, or malformed range. | RuntimeProblem (application/problem+json); headers: Content-Range, Accept-Ranges |
| 429 | Per-client, screen, or organization protected-media egress limit exceeded. | RuntimeProblem (application/problem+json); headers: Retry-After |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /media/manifests/{manifest_revision}/{media_id}

**Get Protected Media**


Operation: getProtectedMedia.

- Authentication: runtimeCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| manifest_revision | path | required |  |
| media_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/media/manifests/MANIFEST_REVISION/MEDIA_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Session-authorized complete private media. Browser Fetch Metadata must describe trusted-player same-origin media/image/video use; authenticated native clients may omit it. | no body; headers: Accept-Ranges, Content-Length, ETag, Content-Disposition |
| 206 | One standards-correct byte range. | no body; headers: Accept-Ranges, Content-Range, Content-Length, ETag |
| 416 | Unsatisfiable, multiple, or malformed range. | RuntimeProblem (application/problem+json); headers: Content-Range, Accept-Ranges |
| 429 | Per-client, screen, or organization protected-media egress limit exceeded. | RuntimeProblem (application/problem+json); headers: Retry-After |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /screen/manifests/{manifest_revision}/releases/{release_id}/package

**Get Native Webapp Package**

Retrieves the normalized immutable package for one uploaded application release so a paired native player can retain its authorized last-known-good release across process restart and temporary network loss.

The paired-device cookie, exact screen grant, manifest revision, content-access generation, release membership, and ready package metadata are checked on every request. Project tokens, anonymous runtime cookies, release cookies, external iframe primitives, and direct object-storage access never authorize package bytes.


Operation: getNativeWebappPackage.

- Authentication: pairedDeviceCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| manifest_revision | path | required |  |
| release_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/screen/manifests/MANIFEST_REVISION/releases/RELEASE_ID/package'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Complete normalized private package. | no body; headers: Accept-Ranges, Content-Length, Content-Type, Content-Disposition, Cache-Control, ETag, Referrer-Policy, Cross-Origin-Resource-Policy, X-Content-Type-Options, Vary |
| 206 | One standards-correct byte range from the same immutable package. | no body; headers: Accept-Ranges, Content-Range, Content-Length, Content-Type, Content-Disposition, Cache-Control, ETag, Referrer-Policy, Cross-Origin-Resource-Policy, X-Content-Type-Options, Vary |
| 416 | Unsatisfiable, multiple, or malformed range. | RuntimeProblem (application/problem+json); headers: Content-Range, Accept-Ranges |
| 429 | Stable rate_limited problem on a Player-facing runtime or content route, in the runtime document shape (RuntimeProblem). Retry only after the authoritative Retry-After interval. Fixed-window denials also include the applicable RateLimit-Policy and RateLimit members; concurrency and byte-budget denials omit those optional disclosures. | RuntimeProblem (application/problem+json); headers: Retry-After, RateLimit-Policy, RateLimit |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### HEAD /screen/manifests/{manifest_revision}/releases/{release_id}/package

**Head Native Webapp Package**

Returns the same authorization and immutable identity headers as GET without package bytes.


Operation: headNativeWebappPackage.

- Authentication: pairedDeviceCookie OR nativeSessionAuthorization
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| manifest_revision | path | required |  |
| release_id | path | required |  |
| Range | header | optional | V1 accepts one byte range only. |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request HEAD --cookie cookies.txt --cookie-jar cookies.txt 'https://play.screenrig.ai/screen/manifests/MANIFEST_REVISION/releases/RELEASE_ID/package'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Authorized normalized package metadata. | no body; headers: Accept-Ranges, Content-Length, Content-Type, Content-Disposition, Cache-Control, ETag, Referrer-Policy, Cross-Origin-Resource-Policy, X-Content-Type-Options, Vary |
| 206 | Authorized metadata for one byte range. | no body; headers: Accept-Ranges, Content-Range, Content-Length, Content-Type, Content-Disposition, Cache-Control, ETag, Referrer-Policy, Cross-Origin-Resource-Policy, X-Content-Type-Options, Vary |
| 416 | Unsatisfiable, multiple, or malformed range. | no body; headers: Content-Range, Accept-Ranges |
| 429 | Stable rate_limited problem on a Player-facing runtime or content route, in the runtime document shape (RuntimeProblem). Retry only after the authoritative Retry-After interval. Fixed-window denials also include the applicable RateLimit-Policy and RateLimit members; concurrency and byte-budget denials omit those optional disclosures. | RuntimeProblem (application/problem+json); headers: Retry-After, RateLimit-Policy, RateLimit |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /{asset_path}

**Consume Launch Ticket Or Get Release Asset**

Exact-release-host operation. With a ticket query, atomically consumes the single-use 30-second ticket, binds Host/release/screen/content-generation/manifest/grant, sets only the exact-host release-grant cookie, and redirects to the same path without the ticket. Without a ticket, validates that cookie on every GET/HEAD.

The asset_path parameter is greedy (x-screenrig-greedy-path) and is resolved only beneath the ready release root. Runtime/project/device cookies and project bearer tokens never authorize this operation.


Operation: consumeLaunchTicketOrGetReleaseAsset.

- Authentication: releaseLaunchTicket OR releaseGrantCookie
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| asset_path | path | required |  |
| Sec-Fetch-Site | header | optional |  |
| Sec-Fetch-Mode | header | optional |  |
| Sec-Fetch-Dest | header | optional |  |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://r-{release_host_label}.apps.screenrig.ai/index.html'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Exact-host grant-authorized immutable asset. | no body; headers: Referrer-Policy, X-Content-Type-Options, ETag |
| 302 | Ticket consumed once; release-grant cookie issued; ticket removed from Location. | no body; headers: Location, Set-Cookie, Cache-Control, Referrer-Policy |
| 403 | Wrong Host/release/screen/generation/grant, stale/replayed ticket, invalid cookie, contradictory Fetch Metadata, or disallowed method. | Problem (application/problem+json) |
| 404 | Asset absent without exposing release filesystem shape. | Problem (application/problem+json) |


## Sitemap

See the [public documentation sitemap](https://screenrig.ai/sitemap.md).
