---
title: "Generate or refresh the project Series Bible."
method: POST
path: "/story-projects/{projectId}/series-bible"
tags: ["Projects"]
---

# Generate or refresh the project Series Bible.

`POST /story-projects/{projectId}/series-bible`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/story-projects/{projectId}/series-bible`
- Auth: HTTP bearer

Writes the Series Bible from the project, sources, plans, scripts, existing document, and optional instructions using the DB sidecar `story_api_series_bible`. Use this when the full bible is missing or incomplete before screenplay generation. It returns at once with `status: "generating"` and writes the Bible in the background (usually a minute or two). Check back with get_series_bible: its `generation.status` is `generating` until the new Bible is saved, then `ready` (with `gateChange`), or `failed` with the reason in `generation.error`. The Bible already saved stays readable, unchanged, until then. Asking again while one is being written returns that one, never a second. Free. For a product project (`kind: product`) the same request writes the product Bible, from what Sleeper learned on the product's public site (learn the product from its site first) and the founder's decisions in the claims ledger: the value promise, personas, positioning, a feature map with each feature's availability and the pages it rests on, the call to action, what may never be claimed, compliance and the brand kit. A feature is never shown as more available than its evidence (the inventory feature it names or was split from; one the site does not list is at most planned, else unknown), a feature split from an inventory feature is also no more available than the features on the pages it cites, an evidence id must name a page that was read or a confirmed claim, and every rejected claim is written into "do not claim" and every sentence elsewhere in the Bible that states it is struck (matched on its words: a paraphrase in other words is not caught, so read the Bible before you use it). Requires `Idempotency-Key`.

## Headers

- `Idempotency-Key` string, required

## Request body

- SeriesBibleGenerateRequest
  - `instructions` string

## Response `200`

The run writing the Bible, at once: `status: "generating"`. Read the Bible (GET) for `generation` until it is `ready` or `failed`.

- SeriesBibleGenerationStarted
  - `status` 'generating', required
  - `projectId` string, required
  - `generation` SeriesBibleGeneration, required: One run writing the Series Bible in the background.
    - `status` 'generating' | 'ready' | 'failed', required
    - `startedAt` string, date-time, required
    - `finishedAt` string, date-time, nullable, required: Null while it is being written.
    - `error` string, nullable, required: Why it stopped, in words for the writer; null unless `failed`.
    - `gateChange` SeriesBibleGateChange, required: Every save returns `gateChange` { before, after, staleCoverage }: what it did to the project's gate. Appending (episodes for a new season, a new character) never re-locks anything. An edit to canon a coverage report scored puts that report out of date (`staleCoverage`) and re-locks what it opened: after full coverage, paid work on every episode already written (coverage, casting, table reads, videos, decks, trailers, publishing) until full coverage passes again. When `after.stage` comes before `before.stage`, tell the user.
      - `before` SeriesBibleGatePosition, required: The project's workspace gate at one moment.
        - `stage` 'premise' | 'premise_coverage' | 'planning' | 'full_coverage' | 'ready', required: The project development stage, in order: develop the premise, pass premise coverage, plan the episode map, pass full Series Bible coverage, then `ready`. The mood board is not a stage: it opens after premise coverage and blocks nothing.
        - `ready` boolean, required
        - `canPlan` boolean, required: Planning seasons and casting at project level.
        - `canStartEpisode` boolean, required
        - `canGenerateProjectMedia` boolean, required: Paid work on every episode already written (coverage, casting, table reads, videos, decks, trailers, publishing) and project media.
        - `reason` string, nullable, required: What to do next when the gate is closed; null when it is open.
      - `after` SeriesBibleGatePosition, required: The project's workspace gate at one moment.
        - `stage` 'premise' | 'premise_coverage' | 'planning' | 'full_coverage' | 'ready', required: The project development stage, in order: develop the premise, pass premise coverage, plan the episode map, pass full Series Bible coverage, then `ready`. The mood board is not a stage: it opens after premise coverage and blocks nothing.
        - `ready` boolean, required
        - `canPlan` boolean, required: Planning seasons and casting at project level.
        - `canStartEpisode` boolean, required
        - `canGenerateProjectMedia` boolean, required: Paid work on every episode already written (coverage, casting, table reads, videos, decks, trailers, publishing) and project media.
        - `reason` string, nullable, required: What to do next when the gate is closed; null when it is open.
      - `staleCoverage` string[], required: The coverage reports that spoke for the Bible before this save and no longer do (`premise` and `full` on a story project; `product`, the one product-Bible report, on a product project). Empty for an append or a visual edit.
  - `alreadyRunning` boolean, required: true: a run was already being written for this project; this is that run, not a new one.

## 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.
- `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/4534f5d25540?raw)
