> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voyager.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Cast

> Save characters, locations and props as workspace Cast cards and pass up to four of them to an image or video job for consistent shots.

A **Cast card** is a saved character, location or prop: a name, a short description of what never changes, and up to 8 reference images. Pass cards to an image or video job with `input.cast` and Voyager puts their best references into the model's reference field and describes them in the prompt, so the same person, place or object looks the same from shot to shot.

Cast cards belong to the workspace. They're the same cards you use when you connect ChatGPT or Codex to Voyager (see [Connect your AI](https://docs.voyager.so/connect/overview.md)): a card saved from the API shows up there, and the other way round.

> [!NOTE]
>
> Cast in the API is not the same as **Elements** in the Voyager desktop app. Elements are local files in each project on your computer and aren't reachable from the API. To use a character from the app, upload its reference images and save them as a Cast card.

## The Cast card

An example card:

```json theme={"system"}
{
  "id": "cst_01JC4S0B6Q8R2T4V6X8Z0A2C4E",
  "object": "cast",
  "slug": "mara",
  "name": "Mara",
  "kind": "character",
  "style": "photoreal",
  "description": "Woman in her 30s, short curly black hair, round silver glasses, green raincoat.",
  "references": [
    { "file_id": "file_01JC4R2M7K9T3V5B8N1X6D0QWE", "role": "hero", "note": "front, neutral light", "url": "https://…", "url_expires_at": "2026-11-05T21:44:03Z" },
    { "file_id": "file_01JC4R3A1C3E5G7J9L1N3Q5S7U", "role": "fullbody", "note": null, "url": "https://…", "url_expires_at": "2026-11-05T21:44:03Z" }
  ],
  "voice_id": null,
  "version": 3,
  "created_at": "2026-11-05T20:01:12Z",
  "updated_at": "2026-11-05T20:44:03Z"
}
```

| Field | Type | Description |
| - | - | - |
| `object` | `string` | Always "cast". Always `cast`. |
| `id` | `string` | cst\_… Pass in input.cast (up to 4) on a job. |
| `slug` | `string` | A short handle for this Cast card, unique in the workspace. |
| `name` | `string` | The card's display name. |
| `kind` | `string` | What this Cast card is: a character, a location or a prop. One of `character`, `location`, `prop`. |
| `style` | `string` | How references render: photoreal or stylized. One of `photoreal`, `stylized`. |
| `description` | `string` | What the card shows; prefixed to the prompt of jobs that feature it. |
| `version` | `integer` | Increases on every change; pass it as expected\_version to change it safely. |
| `voice_id` | `string` or `null` | A voice for this character, when set. |
| `references` | array of `CastReference` | The card's reference images, in order. |
| `created_at` | `string` (date-time) or `null` | When it was created (ISO 8601). |
| `updated_at` | `string` (date-time) or `null` | When it last changed (ISO 8601). |

Each entry in `references` (`url` is a signed preview link, valid about 1 hour):

| Field | Type | Description |
| - | - | - |
| `file_id` | `string` | The reference image (a file\_ id). |
| `role` | `string` | What the image shows of the card: hero, fullbody, angle, expression, outfit, plate or style. One of `hero`, `fullbody`, `angle`, `expression`, `outfit`, `plate`, `style`. |
| `note` | `string` or `null` | A short note about this reference. |
| `url` | `string` or `null` | Signed link to the image, valid about an hour. |
| `url_expires_at` | `string` (date-time) or `null` | When `url` stops working (ISO 8601); read the object again for a fresh link. |

`version` goes up on every change; send it back as `expected_version` when you change the card.

## Endpoints

| Method | Path | What |
| - | - | - |
| `GET` | `/v1/cast` | List the workspace's cards, most recently changed first. |
| `POST` | `/v1/cast` | Create a card. Each reference is copied to a permanent Cast file. |
| `GET` | `/v1/cast/{id}` | Read a card. `{id}` is the `cst_…` ID or the slug. |
| `PATCH` | `/v1/cast/{id}` | Change only the fields you send. `references`, when sent, replaces them all. Requires `expected_version`. |
| `DELETE` | `/v1/cast/{id}` | Delete a card and the reference files no other card uses. Optional `?expected_version=` refuses the delete if the card changed. Jobs already started keep their references. |
| `POST` | `/v1/cast/{id}/references` | Add a reference. Returns `201` with the card. |
| `DELETE` | `/v1/cast/{id}/references/{file_id}?expected_version=` | Remove a reference; its file is deleted when no other card uses it. |

`GET /v1/cast` takes:

| Parameter | Type | Description |
| - | - | - |
| `limit` | `integer` | 1–100. Default `20`. |
| `cursor` | `string` or `null` | Up to 200 characters. |

The `POST /v1/cast` body:

| Field | Type | Description |
| - | - | - |
| `name` | `string` · required | The card's display name. Up to 120 characters. |
| `kind` | `string` · required | What this Cast card is: a character, a location or a prop. One of `character`, `location`, `prop`. |
| `style` | `string` · required | How references render: photoreal or stylized. One of `photoreal`, `stylized`. |
| `description` | `string` | Fixed features that never change between shots. Up to 600 characters. |
| `references` | array of `ReferenceIn` | The card's reference images, in order. Up to 8 items. |
| `slug` | `string` or `null` | Short handle; derived from the name if omitted. Up to 48 characters. |
| `voice_id` | `string` or `null` | A voice (vox\_…) for this character. Up to 64 characters. |

Each entry in its `references`:

| Field | Type | Description |
| - | - | - |
| `file_id` | `string` · required | An image you own (file\_…), from an upload or job. Up to 64 characters. |
| `role` | `string` · required | What it shows: hero (the main look), fullbody, angle, expression, outfit… One of `hero`, `fullbody`, `angle`, `expression`, `outfit`, `plate`, `style`. |
| `note` | `string` or `null` | A short note about this reference. Up to 200 characters. |

The `PATCH /v1/cast/{id}` body:

| Field | Type | Description |
| - | - | - |
| `expected_version` | `integer` · required | The version you read; a stale one is 409 version\_conflict. |
| `name` | `string` or `null` | A new display name. Up to 120 characters. |
| `kind` | `string` or `null` | A new kind. One of `character`, `location`, `prop`. |
| `style` | `string` or `null` | A new style. One of `photoreal`, `stylized`. |
| `description` | `string` or `null` | A new description. Up to 600 characters. |
| `references` | array of `ReferenceIn` or `null` | Replaces every reference when given. Up to 8 items. |
| `slug` | `string` or `null` | A new slug. Up to 48 characters. |
| `voice_id` | `string` or `null` | Send null to clear. Up to 64 characters. |

The `POST /v1/cast/{id}/references` body:

| Field | Type | Description |
| - | - | - |
| `file_id` | `string` · required | An image you own (file\_…), from an upload or job. Up to 64 characters. |
| `role` | `string` · required | What it shows: hero (the main look), fullbody, angle, expression, outfit… One of `hero`, `fullbody`, `angle`, `expression`, `outfit`, `plate`, `style`. |
| `note` | `string` or `null` | A short note about this reference. Up to 200 characters. |
| `expected_version` | `integer` · required | The card's current version; a change made meanwhile answers 409. |

## Create a card and use it

**1. Upload the references**

Upload each photo or image with [`POST /v1/files`](https://docs.voyager.so/api/jobs#uploads) and complete it, or reuse a `file_…` from an earlier output.

**2. Save the card**

```bash theme={"system"}
curl https://api.voyager.so/v1/cast \
  -H "Authorization: Bearer $VOYAGER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Mara",
    "kind": "character",
    "style": "photoreal",
    "description": "Woman in her 30s, short curly black hair, round silver glasses, green raincoat.",
    "references": [
      { "file_id": "file_01JC4R2M7K9T3V5B8N1X6D0QWE", "role": "hero" },
      { "file_id": "file_01JC4R3A1C3E5G7J9L1N3Q5S7U", "role": "fullbody" }
    ]
  }'
```

**3. Pass it to a job**

```bash theme={"system"}
curl https://api.voyager.so/v1/jobs \
  -H "Authorization: Bearer $VOYAGER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "model": "nano-banana-2.1",
    "operation": "text-to-image",
    "input": { "prompt": "Mara waits at a rainy bus stop at night", "cast": ["cst_01JC4S0B6Q8R2T4V6X8Z0A2C4E"] }
  }'
```

## How Cast goes into a job

* Up to **4** cards per job in `input.cast`.
* Voyager takes each card's references in role order (`hero` first) and alternates between cards so each one gets its best reference in, up to the model's own reference limit.
* The cards' names, kinds and descriptions are added to the start of the prompt.
* The job records which version of each card it used.
* Cast works with image and video models only; anything else returns `422` [`cast_not_supported`](https://docs.voyager.so/api/errors#cast_not_supported). Look for a `cast` field in the operation's `input_schema` on [`GET /v1/models/{id}`](https://docs.voyager.so/api/models#read-a-model). More references than the model takes, counting Cast's, is `422` [`too_many_references`](https://docs.voyager.so/api/errors#too_many_references).

### Realistic faces

Some video models need a higher plan (Ultra or GigaMax today) for **photoreal characters**: a job that passes a `photoreal` `character` card to one of them on a lower plan returns `403` [`plan_required_for_faces`](https://docs.voyager.so/api/errors#plan_required_for_faces) before anything is charged. Use a `stylized` character, another model, or upgrade; [voyager.so/pricing](https://voyager.so/pricing) shows which plans include them. Locations, props and stylized characters aren't affected. Every model also applies its own content rules to all inputs.

## Changing cards safely

Every change takes the `expected_version` you last read (optional only for deleting a card). If someone changed the card since (in the API, ChatGPT or Codex), you get `409` [`version_conflict`](https://docs.voyager.so/api/errors#version_conflict): read it again and retry with the new version.

## Retention

Cast reference images are kept until you remove them from the card or delete the card, unlike plain uploads, which are deleted after 7 days. Saving an upload to a card is how you keep a reference for good.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.