---
title: "Cast the narrator for this deck."
method: POST
path: "/pitch-decks/{jobId}/narrator"
tags: ["Pitch Deck"]
---

# Cast the narrator for this deck.

`POST /pitch-decks/{jobId}/narrator`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/pitch-decks/{jobId}/narrator`
- Auth: HTTP bearer

Casts the voice that narrates THIS deck, or send `voiceId: null` to drop back to the default (the cast canon's NARRATOR, else the table read's, else the default narrator). A deck's narrator speaks every line the narrator carries (chapter narration and lines over black). It resolves in one order: the voice cast for THIS deck (`set_pitch_deck_narrator`), else the cast canon's NARRATOR, else the table read's NARRATOR, else the default narrator. Casting or clearing it is free; on a rendered deck the narrated lines are voiced again in the new voice and the master is re-assembled, at no charge. Allowed while the deck is a draft plan, in review or complete (409 otherwise). Answers the resolved `narrator` and `reassembling`. Requires `Idempotency-Key`. Scope: `story:write`.

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `voiceId` string, nullable, required: Studio voice id, or null to drop back to the default narrator.
  - `provider` 'cartesia' | 'elevenlabs' | 'openai' | 'deepgram' | 'hume' | 'null', nullable: The voice's TTS provider. Inferred when omitted.

## Response `200`

The deck's resolved narrator.

- object
  - `narrator` PitchDeckNarrator, required: A deck's narrator speaks every line the narrator carries (chapter narration and lines over black). It resolves in one order: the voice cast for THIS deck (`set_pitch_deck_narrator`), else the cast canon's NARRATOR, else the table read's NARRATOR, else the default narrator. Casting or clearing it is free; on a rendered deck the narrated lines are voiced again in the new voice and the master is re-assembled, at no charge.
    - `voiceId` string, required: The voice every narrated line is spoken in.
    - `voiceName` string, nullable, required: The voice's name, as the writer is shown it; null when nothing names it. Show this, never the id.
    - `provider` string, required: Its TTS provider.
    - `source` 'override' | 'cast_canon' | 'table_read_voice_map' | 'default', required: Where it comes from: `override` (cast for this deck), `cast_canon` (the canon's NARRATOR), `table_read_voice_map` (the table read's NARRATOR) or `default` (the default narrator).
    - `overridden` boolean, required: True when this deck casts its own narrator.
    - `overrideVoiceId` string, nullable, required: The deck's own casting, as stored.
    - `overrideProvider` string, nullable, required
  - `reassembling` boolean, required: True when a rendered deck's narration is voiced again and its master re-assembled (free).

## Other responses

- `400`: Request payload failed validation. The error message names the offending field.
- `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 pitch deck exists and the request is well-formed, but the deck, its chapter, its cast or its plates are not in a state that allows it (`pitch_deck_state_invalid`), and nothing was reserved: a plan approved outside draft, a take chosen, a chapter edited or rendered outside review/complete, an export before the finish, a finish while a call has no selected take or a footage chapter has not rendered, a text-only chapter asked for footage, a changed chapter asked for one call, a delivery class changed mid-pass, a render the compile blocked, or a finish while the master failed its video coverage (`pitch_deck_video_coverage_failed`, with `details.videoCoverage`). `details.refusal` is `{ code, action, fix }` (see PitchDeckRefusalDetails): `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 chapter a blocked compile could not render. The identical request succeeds once the deck 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/86e084144cef?raw)
