---
title: "Price, then render, one trailer beat again."
method: POST
path: "/trailers/{jobId}/beats/render-clip"
tags: ["Trailer"]
---

# Price, then render, one trailer beat again.

`POST /trailers/{jobId}/beats/render-clip`

## Request

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

The writer's priced retake: a new 480p take of one call (`callId`) or of every call of the beat. A beat whose plan changed since it rendered is recompiled first (free) and its new calls are priced. Each new take is checked like every take and may earn the call's one automatic retake at our cost (a line not heard or said in another character's voice, or an opening off its planned framing); a moderation refusal is released and never retried. TWO CALLS, PRICE FIRST: sent WITHOUT `confirmed` it prices the render and reserves nothing (`quotedOnly: true`, the `lines`, `credits`); sent again with `confirmed: true` it reserves exactly the quoted lines and queues the takes. The flag is optional rather than a required `true` because a field that must be true to validate cannot separate a confirmed call from an unconfirmed one. A beat whose stored compile is not ready yet is prepared in the background (its lines voiced and its shots planned), which can take a few minutes: ${RENDER_QUOTE_PREPARING_UNIT_SENTENCE} Refused before the price: a text-only beat, a beat not in the cut, a call id the beat does not have (or a call of a changed beat), and a cast member with no body figure — with the action that fixes it in `details.refusal`. Review or complete only. Returns a shareable per-beat `previewUrl`. Requires `Idempotency-Key`. Scope: `artifact:publish` — a read-only key can neither spend nor ask what spending would cost.

## Headers

- `Idempotency-Key` string, required

## Request body

- TrailerRenderClipRequest: Render one beat again (the writer's priced retake), and say whether this call is the price or the purchase.
  - `beatIndex` integer, required: Zero-based index of the beat to render.
  - `callId` string: One of the beat's calls (from the beats read); omit to render a new take of every call of the beat. A beat whose plan changed is recompiled first, and a call id is then refused — render the whole beat.
  - `confirmed` boolean: Omit (or false) to get the price WITHOUT spending anything. Send true only after the writer has seen that price and said go.

## Response `200`

The price (no `confirmed`) or the queued takes, plus a shareable beat preview link. A beat not prepared yet answers `RenderQuotePreparing` (`status: "preparing"`): ask again with the same call and inputs, under a NEW `Idempotency-Key` (the answer under a given key is the one the server keeps).

- union: The beat render-clip quote's answer: its price or its queued takes (`TrailerRenderAnswer`), or — while the beat's compile is being prepared in the background — `RenderQuotePreparing` (`status: "preparing"`).
  - TrailerRenderAnswer: Either the PRICE of a render (plan approval, or a beat rendered again) or the queued render itself — branch on `quotedOnly`. Without `confirmed` nothing is reserved; with `confirmed: true` exactly the quoted lines are held and the calls are queued.
    - `quotedOnly` boolean, required: True when this was a price and NOTHING was spent; false when the render was reserved and queued.
    - `queued` boolean: Confirmed call only.
    - `jobId` string, required
    - `credits` number, required: What a confirmed call reserves (quote), or what it reserved (confirmed).
    - `costLabel` string, nullable: What the whole quote buys, in one label — the shots, the beats they span, their seconds at 480p and the location plates made first, e.g. "Trailer render: 7 shots across 5 beats (58s at 480p)" (quote only).
    - `lines` object[]: Quote only. Every line a confirmed call would reserve: one per call at its voiced seconds, one per location plate the renders make first, and — a plan approval — the automatic-fix allowance (kind `allowance`).
      - `kind` 'call' | 'plate' | 'allowance': `allowance`: a plan approval's automatic-fix allowance (see `autoFixAllowance`).
      - `idempotencyKey` string
      - `label` string
      - `credits` number
      - `callId` string, nullable
      - `plateKey` string, nullable
      - `seconds` number, nullable
    - `calls` union: Quote: the priced calls `[{ beatIndex, callId, take, seconds, audioMode, credits }]`. Confirmed: how many calls were queued.
      - object[]
        - `beatIndex` integer
        - `callId` string
        - `take` integer
        - `seconds` number
        - `audioMode` 'dialogue' | 'ambient' | 'silent'
        - `credits` number
      - integer
    - `captureBeats` object[]: A plan approval's quote only: the beats that play an app capture, never rendered and in no line. A capture beat plays one of the project's app captures (a real screen recording, `ready`) as it was recorded: set it with the beat refine (`compositionKind: 'capture'` and the capture's `captureId`). It plays the whole capture, or only the stretch of it you keep (`captureKeep`: a start and an end, in seconds of the capture); what it plays runs 4 to 30 seconds, so a longer capture plays a kept stretch of it. The capture must be in the trailer's shape. The beat carries no on-screen text (its caption is cleared and none can be set), and is never rendered or retaken, so it costs nothing. A beat that already has rendered shots cannot become one: add a beat for the capture instead.
      - `beatIndex` integer, required
      - `captureId` string, required
      - `seconds` number, required
    - `warnings` string[]: Quote only. Compile warnings worth showing (advisory; nothing blocks on them).
    - `balanceAfter` integer: Quote only. Studio Credits the writer would have left once this is spent: the balance available now (as Billing shows it) minus the price. Negative means they are that many short.
    - `sufficient` boolean: Quote only. True when the available balance covers the price. False means the writer must top up first (the note names the Billing link) — do not confirm; the reserve would refuse.
    - `note` string: The price in the writer's own words, what it would leave (or how short they are, with the top-up link), and how to proceed (quote only).
    - `message` string: Confirmed call only: what was queued.
    - `previewUrl` string: A beat render only: a shareable link to watch the beat's current cut.
    - `autoFixAllowance` object, nullable: A plan approval's quote only: the AUTOMATIC-FIX ALLOWANCE, part of the one approval and included in `credits`. A ceiling the engine draws on to retake the shots the review of the 480p preview flags (and render flagged on-screen text again), reserved with the render; only what the fixes draw is charged and the rest comes back when the loop stops. 0 when the cut has nothing a paid new take could redo (app captures, title cards) or the balance holds only the render; free fixes (re-timing an app capture's narration to its picture) run whatever it holds, and `note` says plainly what is and is not fixed by itself. The 720p finish is a separate approval.
      - `credits` integer, required
      - `note` string, required: The allowance in the writer's words.
    - `planCoverageOverride` PlanCoverageOverride: A render over a failed plan gate on the writer's word: the report it overrode, the plan revision it graded, its score, the bar, and the reasons it gave. A recorded override (on the confirmed approval and on the coverage read) also carries `at` and `by`.
      - `reason` string, required
      - `reportId` string, required
      - `planRevision` integer, required
      - `overallScore` number, nullable, required
      - `gateThreshold` number, required
      - `gateReasons` string[], required
      - `at` string, date-time: Recorded overrides only: when the confirmed approval recorded it.
      - `by` object: Recorded overrides only: who approved it — `api` (the Story API: MCP and the CLI) with the API key or `oauth:…` connection, or `app` (the Writers Lab).
        - `userId` string, required
        - `surface` 'api' | 'app', required
        - `keyId` string, nullable, required
  - RenderQuotePreparing: A plan approval whose price is still being prepared in the background (every chapter or beat voiced and planned): no price yet, and nothing was reserved — confirmed or not. Ask again with the same request after `checkAgainSeconds`; the price comes back once it is ready.
    - `quotedOnly` true, required
    - `status` 'preparing', required
    - `jobId` string, required
    - `progress` string, nullable, required: What is being prepared now, e.g. "Preparing chapters 9 and 10 of 17; 8 of 17 done…".
    - `checkAgainSeconds` integer, required
    - `note` string, required: One line to tell the writer.

## Other responses

- `400`: Request payload failed validation. The error message names the offending field.
- `401`: Missing, malformed, revoked, or expired API key.
- `402`: Not enough Studio Credits to reserve this job (`insufficient_credits`), and nothing was reserved. `details` is InsufficientCreditsDetails: `required` and `available`, and `autoTopup` when auto top-up is on but did not cover it — `pending` (retry in a moment), `over_cap` (raise the monthly spending cap), `too_small` (buy a bigger pack) or `failed`.
- `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.
- `409`: The trailer exists and the request is well-formed, but the trailer, its beat, its cast or its plates are not in a state that allows it (`trailer_state_invalid`), and nothing was reserved: a plan approved outside draft, a take chosen or a beat rendered outside review/complete, an export before the finish, a finish while a call has no selected take, a narrated cut with no narrator, a render the compile blocked, or a finish while the master failed its video coverage (`trailer_video_coverage_failed`, with `details.videoCoverage`). `details.refusal` is `{ code, action, fix }` (see TrailerRefusalDetails): `action` is what unblocks it — `recast_figure`, `add_signature_items`, `recast_voice` or `remake_location_plate` — and `fix` names the MCP tool and CLI command that take it; `details.blocked[]` lists every beat a blocked compile could not render. The identical request succeeds once the trailer is put right.
- `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.

---

[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/64c1102ccb2f?raw)
