---
title: "Copy a product Bible persona into the cast (free)."
method: POST
path: "/story-projects/{projectId}/cast-canon/from-persona"
tags: ["Projects"]
---

# Copy a product Bible persona into the cast (free).

`POST /story-projects/{projectId}/cast-canon/from-persona`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/story-projects/{projectId}/cast-canon/from-persona`
- Auth: HTTP bearer

A product project holds a cast once it has a story film. Its Bible's personas are the buyers it serves, never cast members: this COPIES one into the cast canon as a person a story film can put on screen. The persona stays in the Bible. The copy's look starts from the persona's appearance and wardrobe when the Bible has them. Someone already on the cast under the name only learns the `aliases` (`alreadyCast: true`). Refused: 409 `cast_precondition_failed` (reason `product_cast_needs_story_film`) when the product has no story film yet; 409 `project_not_product` on a story project; 404 `character_not_found` for a persona the Bible does not have.  Requires `Idempotency-Key`. Scope: `story:write`.

## Headers

- `Idempotency-Key` string, required

## Request body

- CastFromPersonaRequest
  - `persona` string, required: The persona's id in the product Bible ("persona-nora") or its name.
  - `name` string: The name to cast them under. Omitted: the persona's name without the role in brackets.
  - `aliases` string[]: Other names they answer to, the film's cue among them ("NORA").

## Response `200`

The person the persona was copied into.

- CastFromPersonaResponse
  - `projectId` string, required
  - `persona` object, required: The persona copied; it stays in the Bible.
    - `id` string, nullable, required
    - `name` string, required
  - `person` object, required: The cast canon person the persona was copied into.
    - `id` string, nullable, required
    - `name` string, required
    - `aliases` string[], required
    - `lookDirection` string, nullable, required
  - `alreadyCast` boolean, required: Someone on the cast already answered to the name; nobody new was added.
  - `note` string, required

## 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`: Casting cannot run on this project yet, and nothing was quoted or drawn: nobody castable, nobody with a description to draw from, no passing screenplay coverage, or no image model bound (`cast_precondition_failed`, `details.reason` names which) — or the project itself has not reached casting (`project_precondition_failed`, `details.stage` names the stage to finish). The message says what to do.
- `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)
