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

# Regenerate a single character's avatar portrait on a table read artifact.

`POST /artifacts/{artifactId}/avatar`

## Request

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

Re-renders ONE character's avatar portrait on the table read backing this `table_read` artifact, in place. The artifact id, share token, and all player URLs remain STABLE — no new revision, no charge, like a voice recast.  Body: `{ character, refinement?, style?, referenceImageUrl? }`. `refinement` is a freeform art-direction nudge; `style` persists an episode portrait override without changing project Series Bible canon; `referenceImageUrl` seeds the image model from an already-uploaded image. Async + queue-backed: enqueues a `regenerate_avatar` job and returns `{ character, status, chatToolJobId }`. Poll GET /artifacts/{artifactId}/cast and watch that character's `avatarStatus` (`queued` → `rendering` → `ready`).  Requires `Idempotency-Key`. Scope: `artifact:publish`.

## Headers

- `Idempotency-Key` string, required

## Request body

- AvatarRecastRequest: Regenerate one character's avatar portrait. The render follows project Series Bible canon plus any episode override. Supplying `style` persists an explicit episode portrait override for this and subsequent episode renders; it does not change project canon.
  - `character` string, required: Character cue whose avatar to regenerate, e.g. "NARRATOR" or "MAYA".
  - `refinement` string: Optional freeform art-direction nudge for this render, e.g. "older, weathered, dim backlight".
  - `style` string: Optional explicit episode portrait override (at most 8000 characters: it is saved as the episode `avatar` override and takes that override's cap). It persists for subsequent renders in this episode without changing the project Series Bible. To apply it to the whole cast, use POST /artifacts/{id}/cast with `avatarStyle`.
  - `referenceImageUrl` string, uri: Optional already-uploaded image URL (http or https) to seed the portrait.
  - `confirmed` boolean: PRICED (three images: the headshot, and the body shot and sheet redrawn to match it; 3 credits). Omit to get the price only (`quotedOnly: true`, nothing drawn or charged); send `true` to draw and charge.

## Response `200`

Without `confirmed`: the price (3 credits), nothing drawn. With `confirmed: true`: avatar regeneration dispatched and charged. Poll GET /artifacts/{artifactId}/cast until the character's avatarStatus is ready.

- 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.
  - AvatarRecastResponse: Acknowledgement that a single-character avatar regeneration has been dispatched and charged (`credits`). Poll GET /artifacts/{artifactId}/cast until the character's `avatarStatus` reaches `ready`. 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 avatar render op.
    - `chatToolJobId` string, required: Id of the queued `regenerate_avatar` 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)
