---
title: "Read how one beat's words play."
method: GET
path: "/trailers/{jobId}/beats/{beatIndex}/text-preview"
tags: ["Trailer"]
---

# Read how one beat's words play.

`GET /trailers/{jobId}/beats/{beatIndex}/text-preview`

## Request

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

Free and read-only: the spec the trailer's master draws for the beat's words (compiled from their style, or the beat's direction), the beat's length, the `window` a preview plays (the beat and a second of each neighbour, in seconds of the master), when the words are on screen (`words`), `notes` for what they could not keep as asked, and a shareable `previewUrl`. A beat with no words is refused (409). The 480p MP4 of the window is POST …/text-preview/render. Scope: `story:read`.

## Response `200`

The beat's words as the master draws them.

- TrailerTextPreview: One beat's words as the master draws them. Free and read-only.
  - `beatIndex` integer, required
  - `beatNumber` integer, required
  - `style` 'statement' | 'thought' | 'typed' | 'reveal' | 'label' | 'stat' | 'directed', required
  - `spec` object, required: The motion-text spec the master draws (compiled from the style, or the beat's direction).
  - `durationSeconds` number, required
  - `window` TrailerTextPreviewWindow, required: What a preview plays, in seconds of the master: the beat, and a second of each neighbour.
    - `fromSeconds` number, required
    - `toSeconds` number, required
    - `beatFromSeconds` number, required
    - `beatToSeconds` number, required
  - `words` TrailerTextWordsWindow, required: When the words are on screen, in seconds from the beat's first frame: they start coming in, are fully in, start going, are gone.
    - `enterAt` number, required
    - `readFrom` number, required
    - `exitAt` number, required
    - `goneAt` number, required
  - `notes` string[], required
  - `previewUrl` string, nullable, required: A shareable link to watch the beat.

## 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.
- `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.

## Changes

- **2026-10-20** `4534f5d25540`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/changes/trailers/:jobId/beats/:beatIndex/text-preview/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/86e084144cef?raw)
