---
title: "Edit ONE Series Bible character, not the whole array."
method: PATCH
path: "/story-projects/{projectId}/series-bible/characters"
tags: ["Projects"]
---

# Edit ONE Series Bible character, not the whole array.

`PATCH /story-projects/{projectId}/series-bible/characters`

## Request

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

Changes only the fields in `content` on one character (found by id, or any name the Bible or the cast canon knows them by) and leaves every other character exactly as stored, under the same lock as every Bible save. `expectedVersion` (the `currentVersion` you read) makes it a compare-and-swap: when the Bible changed since, nothing is saved and it is a 409 `series_bible_version_conflict`. `create: true` adds the character when nobody answers to the name (else 404 `character_not_found`). A note about how someone LOOKS belongs on PATCH /story-projects/{projectId}/cast-look, which never touches the Bible. 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. Free. Scope: `story:write`.

## Request body

- SeriesBibleCharacterUpdateRequest
  - `character` string, required: The character's id, or any name the Bible or the cast canon knows them by.
  - `content` object, required: The fields to change; every other field and every other character stay as stored. `name` renames.
    - `name` string
    - `role` string
    - `want` string
    - `wound` string
    - `arc` string
    - `voice` string
    - `relationships` string
    - `appearance` string
    - `wardrobe` string
    - `movement` string
  - `expectedVersion` integer: Compare-and-swap: the Bible `currentVersion` you read. Omitted: edit whatever is saved now.
  - `create` boolean: Add the character when nobody answers to the name.

## Response `200`

The character as saved and the Bible version.

- SeriesBibleCharacterResult
  - `projectId` string, required
  - `currentVersion` integer, required: The Bible's version; send it as `expectedVersion` to edit safely.
  - `character` SeriesBibleCharacter, required
    - `id` string, required
    - `name` string, required
    - `role` string, required
    - `want` string, required
    - `wound` string, required
    - `arc` string, required
    - `voice` string, required
    - `relationships` string, required
    - `appearance` string, required: Binding visual identity details that supplement the canonical avatar and model sheet.
    - `wardrobe` string, required: Canonical wardrobe silhouette, materials, colors, and permitted changes.
    - `movement` string, required: Posture, gait, gesture vocabulary, and recurring physical behavior.
  - `created` boolean
  - `gateChange` SeriesBibleGateChange: 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.

## 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`: Nobody in the project's cast canon or Series Bible answers to that name (`character_not_found`), or the project is not yours (`project_not_found`). Nothing was changed or charged.
- `409`: The Series Bible changed since the version the edit was based on (`series_bible_version_conflict`; `details.expectedVersion`, `details.currentVersion`), so nothing was saved. Read it again and retry; `project_precondition_failed` when the edit touched the episode map before the project reached planning.
- `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)
