---
title: "Regenerate a single character's full-body figure on a table read artifact."
method: POST
path: "/artifacts/{artifactId}/figure"
tags: ["Artifacts"]
---

# Regenerate a single character's full-body figure on a table read artifact.

`POST /artifacts/{artifactId}/figure`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/artifacts/{artifactId}/figure`
- Auth: HTTP bearer

Re-renders ONE character's FULL-BODY FIGURE on the table read backing this `table_read` artifact, in place. The figure is the full-body cutout a render uses for that character; the avatar (POST /artifacts/{artifactId}/avatar) is the headshot the identity gate judges faces against. THEY MUST DEPICT THE SAME PERSON: when they drift apart, frames build from the figure and are judged against the avatar, so that character fails identity on every render while the rest of the cast passes.  Body: `{ character, refinement?, referenceImageUrl? }`. The figure is seeded from the character's own avatar unless `referenceImageUrl` overrides it. There is no `style` field — figure art direction follows the avatar. Async + queue-backed: enqueues a `generate_figure` job and returns `{ character, status, chatToolJobId }`.  Requires `Idempotency-Key`. Scope: `artifact:publish`.

## Headers

- `Idempotency-Key` string, required

## Request body

- FigureRecastRequest: Regenerate one character's FULL-BODY FIGURE — the cutout a render uses for that character, as opposed to the avatar headshot the identity gate judges faces against. The two must depict the same person: when they drift apart, frames build from the figure and are judged against the avatar, so that character fails identity on every render. The figure is seeded from the character's own avatar unless `referenceImageUrl` overrides it. There is deliberately no `style` field — figure art direction follows the avatar rather than diverging from it.
  - `character` string, required: Character cue whose figure to regenerate, e.g. "ALYOSHA".
  - `refinement` string: Optional freeform art-direction nudge for the BODY render only. Never rewrites the headshot prompt.
  - `referenceImageUrl` string, uri: Optional already-uploaded image URL (http or https) to seed the figure from. Omit to seed from the character's avatar, which is what keeps the pair consistent.
  - `confirmed` boolean: PRICED (one image; 1 credit). Omit to get the price only (`quotedOnly: true`, nothing drawn or charged); send `true` to draw and charge.

## Response `200`

Without `confirmed`: the price (1 credit), nothing drawn. With `confirmed: true`: figure regeneration dispatched and charged.

- union
  - CastArtQuote: The answer to a priced cast-art call WITHOUT `confirmed`: what it costs, what it would leave, and the fact that nothing was drawn or charged. The same price on every surface (the app's Cast panel, this API, MCP, the CLI and Slug).
    - `artifactId` string
    - `quotedOnly` true, required
    - `credits` integer, required
    - `balanceAfter` integer: Quote only. Studio Credits the writer would have left once this is spent: the balance available now (as Billing shows it) minus the price. Negative means they are that many short.
    - `sufficient` boolean: Quote only. True when the available balance covers the price. False means the writer must top up first (the note names the Billing link) — do not confirm; the reserve would refuse.
    - `costLabel` string, nullable
    - `kind` 'portrait' | 'figure', required
    - `characters` string[], required
    - `note` string, required: The same sentence to show the writer, in their terms.
  - FigureRecastResponse: Acknowledgement that a single-character figure regeneration has been dispatched and charged (`credits`). GET /artifacts/{artifactId}/cast exposes only avatar status and does not reflect figure render state; use `chatToolJobId` to track the queued `generate_figure` job. A draw that fails gives its credits back.
    - `artifactId` string, required
    - `quotedOnly` false, required
    - `credits` integer, required: Studio Credits held for the draw (settled when the picture lands).
    - `character` string, required
    - `status` 'queued' | 'rendering' | 'ready' | 'failed', required: Lifecycle of the figure render op.
    - `chatToolJobId` string, required: Id of the queued `generate_figure` job backing this render.

## 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 story artifact does not exist or is owned by another account.
- `409`: The artifact is not in a state where this operation is valid yet (e.g. requesting an MP4 render before the share link exists).
- `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)
