---
title: "Read every trailer beat's render state and credit trail."
method: GET
path: "/trailers/{jobId}/render-states"
tags: ["Trailer"]
---

# Read every trailer beat's render state and credit trail.

`GET /trailers/{jobId}/render-states`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/trailers/{jobId}/render-states`
- Auth: HTTP bearer

Returns every beat's clip and text render state as the queue, the manifest and the credit ledger actually see it, with each attempt's own credit trail. Where GET /trailers/{jobId}/beats shows the plan, the takes and the cut, THIS shows why a beat reads `queued` / `running` / `ready` / `failed` / `never_submitted` and whether an attempt cost money. Each `state` is DERIVED, never asserted — `ready` (the asset is in the manifest, the only state that means done), `queued` / `running` (the queue still holds the recorded job id), `completed` (the queue finished but the asset is NOT in the manifest: the worker ran and wrote nothing durable), `failed` (the queue marked it failed/cancelled/expired; `error` carries the worker's payload), `missing` (a job id was recorded but the queue has no such job), `unknown` (the queue could not be reached — say "unknown", never guess), `never_submitted` (no job id and no asset). `attempt` is the recorded attempt INDEPENDENT of the asset — a re-render over an existing still reads `state: ready` while the new attempt is still queued — with its own queue state, error, `creditIdempotencyKey`, `providerTaskId`, `providerModelId` and its `timeline` (submitted → enqueued → provider-started → completed → persisted). `credits` is THE CREDIT TRAIL for the beat, newest first: each row's `reason` is its current ledger position — `RESERVE` (held, the worker still owes the render), `CONSUME_PROVISION` (settled: the render landed and the credits are spent), `RELEASE` (returned: the attempt died before spending). A read: it never compiles, renders, voices or makes a plate. Scope: `story:read`.

## Response `200`

Every beat's clip and text render state and credit trail.

- TrailerBeatRenderStatus[]: Every beat's clip render state, derived from the queue, the manifest and the credit ledger, plus each attempt's credit trail (reads only: it never compiles, renders, voices or makes a plate). A beat's words never render: the master draws them. One entry per beat, in the order the cut plays them.
  - `beatIndex` integer, required
  - `clip` TrailerBeatRenderState, required: One beat's clip, as the queue, the manifest and the credit ledger actually see it. Every `state` is DERIVED, never asserted: `ready` is the only one that means done.
    - `kind` 'clip', required
    - `state` 'ready' | 'queued' | 'running' | 'completed' | 'failed' | 'missing' | 'unknown' | 'never_submitted', required: `ready` (the asset is in the manifest — the only state that means done); `queued` / `running` (the queue still holds the recorded job id); `completed` (the queue finished but the asset is NOT in the manifest: the worker ran and wrote nothing durable); `failed` (the queue marked it failed/cancelled/expired; `error` carries the worker's payload); `missing` (a job id was recorded but the queue has no such job); `unknown` (the queue could not be reached — say "unknown", never guess); `never_submitted` (no job id and no asset).
    - `queueJobId` string, nullable, required: The pg-boss job id backing this state, when one was recorded at submit.
    - `assetUrl` string, nullable, required: The asset in the manifest, when the render actually landed.
    - `error` string, nullable, required: The queue row's failure payload, when state is `failed`.
    - `attempt` TrailerBeatRenderAttempt, required: THE RECORDED RENDER ATTEMPT for one beat's clip or text layer, independent of any asset. A re-render over an existing asset would otherwise be invisible: the asset reads `ready` while the new attempt is still in the queue.
      - `queueJobId` string, required
      - `state` 'queued' | 'running' | 'completed' | 'failed' | 'missing' | 'unknown', required
      - `error` string, nullable, required
      - `creditIdempotencyKey` string, nullable, required: The submission's identity: the credit line idempotency key reserved at submit.
      - `providerTaskId` string, nullable, required: The provider's own task id, when the worker recorded one (the video path).
      - `providerModelId` string, nullable, required: The provider model that accepted the task.
      - `timeline` TrailerBeatRenderTimeline, required: THE TIMESTAMPED LEDGER for one render attempt: submitted → enqueued → provider-started → completed → persisted. Each stamp is ISO or null (null = that stage was never reached, or the record predates the field).
        - `submittedAt` string, nullable, required
        - `enqueuedAt` string, nullable, required
        - `startedAt` string, nullable, required
        - `completedAt` string, nullable, required
        - `persistedAt` string, nullable, required
    - `credits` object[], required: THE CREDIT TRAIL for this beat's recorded attempts, newest first: each row is one attempt's current ledger position — `RESERVE` (held), `CONSUME_PROVISION` (settled), `RELEASE` (returned).
      - `reason` string, required
      - `delta` number, required
      - `label` string, nullable, required
      - `createdAt` string, required

## Other responses

- `401`: Missing, malformed, revoked, or expired API key.
- `403`: API key is valid but lacks the scope, is blocked by IP allowlist, or the account is disabled.
- `404`: The named project or source does not exist or is owned by another account.
- `429`: Rate limit for this API key + IP + route family was exceeded.
- `500`: The API failed unexpectedly. Safe to retry with the same Idempotency-Key.

## Changes

- **2026-10-20** `4534f5d25540`: 1 breaking, 1 info
  - removed the required property `items/text` from the response with the `200` status
  - removed the `text` enum value from the `items/clip/kind` response property for the response status `200`

[Operation history](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/changes/trailers/:jobId/render-states/get.md)

---

[API](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api.md) · [All operations](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/revisions/4534f5d25540?raw)
