---
title: "Edit a draft pitch deck's intent."
method: POST
path: "/pitch-decks/{jobId}/intent"
tags: ["Pitch Deck"]
---

# Edit a draft pitch deck's intent.

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

## Request

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

Edits the intent of a DRAFT pitch deck: each field given replaces the stored one (`arc` the whole four-stage arc), and the merged intent must be complete and build (the arc's intensity rises to the turn). Editing the intent is free and only while the plan is a draft (approving the plan approves its intent): it saves the new intent and queues plan coverage again for the latest revision — a burst of edits is one coverage run, started once the plan has been left alone for three minutes. The chapters or beats are not re-planned; edit them (their `arcStage`, `advancesQuestion` and `whyItFollows` included) to follow the new intent. A plan planned before intents existed takes a complete intent. Answers the saved intent, the changed plan's `planCoverage` and `arcProblems` — where the chapters now break the new arc (fix them with the chapter refine's `arcStage` and `advancesQuestion`). Refused once the plan is approved (409). Requires `Idempotency-Key`. Scope: `story:write`.

## Headers

- `Idempotency-Key` string, required

## Request body

- VideoIntentEditRequest: An edit to a draft's intent: each field given replaces the stored one (`arc` replaces the whole arc; an `audience` of "" clears it), and the merged intent must be complete and build. Editing the intent is free and only while the plan is a draft (approving the plan approves its intent): it saves the new intent and queues plan coverage again for the latest revision — a burst of edits is one coverage run, started once the plan has been left alone for three minutes. The chapters or beats are not re-planned; edit them (their `arcStage`, `advancesQuestion` and `whyItFollows` included) to follow the new intent.
  - `purpose` string
  - `audience` string
  - `logline` string
  - `theme` string
  - `centralQuestion` string
  - `stakes` string
  - `viewerPromise` string
  - `ending` string
  - `arc` VideoIntentArcEntry[]
    - `stage` 'setup' | 'escalation' | 'turn' | 'closing_question', required: Which stage: the arc is exactly setup, escalation, turn, closing_question, in that order.
    - `purpose` string, required: What this stage does for a first-time viewer.
    - `temperature` string, required: The emotional temperature, in words.
    - `intensity` integer, required: The same temperature on a 1–10 scale. It rises to the turn: the escalation runs hotter than the setup, and the turn is the peak of the first three (the closing question may fall quiet).

## Response `200`

The saved intent.

- VideoIntentEditAck: The saved intent. Nothing was re-planned, rendered or charged.
  - `success` boolean, required
  - `planKind` 'pitch_deck' | 'trailer', required
  - `jobId` string, required
  - `intent` VideoStoryIntent, required: What a deck or trailer is FOR. Every deck and trailer is planned from an explicit intent — what the video is for, its logline, theme, central question, stakes, what a first-time viewer is promised, a four-stage arc (setup, escalation, turn, closing question) and how the ending lands the question. Every chapter or beat names the arc stage it serves (`arcStage`), how it advances the central question (`advancesQuestion`) and, after the first, why it follows the one before it (`whyItFollows`: the visible link — a cause, an answer, a contrast, a match cut, a look, an object, a sound — and what it moves forward; one line, never shown on screen). Plan coverage first writes what a first-time viewer would take away from the plan without seeing the intent (`viewerTakeaway`, with how much of the story the words recited rather than let them work out: `toldVersusShown`, and where they lost the thread: `lostTheThread`), then compares it with the intent: intent clarity, the central question, the buildup and whether the theme is carried each fail the plan on their own, and so do subtext — a plan that recites its plot instead of posing its question — and transitions — a part that follows the one before it for no reason a first-time viewer can feel (`weakTransitions` names the weakest, each with its fix); voices (do the characters speak, rather than the narrator carrying everything) is scored beside them.
    - `purpose` string, required: What this video is for: a pitch sells the series, a showcase shows the world AS the story, a trailer hooks the episode.
    - `audience` string: Who it is for (a pitch's buyer, a trailer's audience). Optional.
    - `logline` string, required: What this show is about, in one sentence.
    - `theme` string, required: What it is really about underneath.
    - `centralQuestion` string, required: The dramatic question the video poses and leaves open.
    - `stakes` string, required: What is at risk, and for whom.
    - `viewerPromise` string, required: What a first-time viewer should feel and want by the end.
    - `arc` VideoIntentArcEntry[], required: The four stages, in order: setup, escalation, turn, closing_question.
      - `stage` 'setup' | 'escalation' | 'turn' | 'closing_question', required: Which stage: the arc is exactly setup, escalation, turn, closing_question, in that order.
      - `purpose` string, required: What this stage does for a first-time viewer.
      - `temperature` string, required: The emotional temperature, in words.
      - `intensity` integer, required: The same temperature on a 1–10 scale. It rises to the turn: the escalation runs hotter than the setup, and the turn is the peak of the first three (the closing question may fall quiet).
    - `ending` string, required: How the final moment lands the central question — posed, sharpened, and left open.
  - `planCoverage` 'queued' | 'current' | 'failed' | 'null', nullable, required: The changed plan's coverage: `queued` for the latest edit (one run per burst of edits, started once the plan has been left alone for three minutes), `current` (already scored or being scored), `failed` (could not be queued). Null when the edit changed nothing.
  - `arcProblems` VideoIntentArcProblem[], required: Where the units now break the new intent's arc: fix them with the chapter or beat refine.
    - `code` 'arc_stage_missing' | 'question_not_advanced' | 'transition_unexplained' | 'arc_out_of_order' | 'arc_stage_unserved' | 'ending_off_question', required
    - `units` integer[], required: The 1-based places in the cut the problem is about (empty for a whole-plan problem).
    - `stage` 'setup' | 'escalation' | 'turn' | 'closing_question': The arc stage it is about, when it is about one.
    - `detail` string, required: The problem and its fix, in one sentence.

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