---
title: "Restore a character's previous voice on a table read artifact."
method: POST
path: "/artifacts/{artifactId}/voice/restore"
tags: ["Artifacts"]
---

# Restore a character's previous voice on a table read artifact.

`POST /artifacts/{artifactId}/voice/restore`

## Request

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

Undoes the newest recast of `character` (or of any character when omitted): the previous voice comes back with the recording the read had before the recast — its voices-only track, and the finished mix and video while they still match — and the cast canon voice when the canon still holds the one the recast pinned. Free. Restoring again returns to the voice this restore replaced. GET /artifacts/{artifactId}/cast lists what is restorable (`restorable`). 409 `cast_voice_precondition_failed` when the character has not been recast on this read.  Requires `Idempotency-Key`. Scope: `artifact:publish`.

## Headers

- `Idempotency-Key` string, required

## Request body

- VoiceRestoreRequest
  - `character` string: The character to restore. Omitted: the newest recast of any character.

## Response `200`

The previous voice and what came back with it.

- VoiceRestoreResponse
  - `artifactId` string, required
  - `character` string, required
  - `voice` object, nullable, required: The voice the character speaks with now; null when it had none before the recast.
  - `voiceMap` object, required
  - `recordingRestored` boolean, required: The read's voices-only track came back.
  - `finishedMixRestored` boolean, required: The finished MP3 came back; no new finalize is needed.
  - `videoRestored` boolean, required: The rendered video came back (only while the share link still holds that render).
  - `canonRestored` boolean, required: The cast canon voice came back (only while the canon still held the voice the recast pinned).
  - `restore` RestorableVoice, required: A recast that POST /artifacts/{artifactId}/voice/restore can undo.
    - `character` string, required
    - `historyId` string, required
    - `at` string, date-time, required
    - `previousVoiceId` string, nullable, required: The voice a restore puts back; null when the character had none.
    - `previousVoiceName` string, nullable, required
    - `currentVoiceName` string, nullable, required
    - `recordingRecoverable` boolean, required: A restore also brings back the recording the read had before the recast.

## 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 read or project is not ready for this cast voice operation, and nothing was priced or charged (`cast_voice_precondition_failed`): no description and no Series Bible voice line, a character with no lines, nothing to restore, no finished recording to re-voice, a voice the character already speaks with, a finalize already running, or a recording that cannot be cut line by line. The message says which and what to do; `project_precondition_failed` when the project gate holds spending.
- `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/64c1102ccb2f?raw)
