# Save voice to library

- **Method:** `POST`
- **Path:** `/api/v1/voices`
- **Operation ID:** `save_voice_api_v1_voices_post`
- **Tags:** Voices

Save a new voice (audio + transcript) to the voice library. Clone audio can be up to 30 seconds long. A clone longer than 15 seconds is cut to 15 seconds or less, on sentence ends where it can, and the response carries the cut voice.

## Effective servers

- `http://127.0.0.1:8100`

  Voice Creator Pro on this computer

## Request body

**Required:** `true`

**Content type:** `application/json`

schema: `SaveVoiceRequest`

- **`audio_base64` (required)**: `string`

  Base64-encoded audio (WAV)
- **`name` (required)**: `string`

  Display name for the voice
- **`transcript` (required)**: `string`

  Transcript of the audio
- **`ref_text`**: `string | null`

  Reference text (for clone voices)
- **`source`**: `object | null`, schema: `VoiceSourceModel`

  Where the audio was cut from, when it came from a public sample
  - **`end` (required)**: `number`, exclusiveMinimum: `0`

    End of the saved audio within the sample, in seconds
  - **`start` (required)**: `number`, minimum: `0`

    Start of the saved audio within the sample, in seconds
  - **`task_id` (required)**: `string`

    Id of the public sample the audio was cut from
- **`transcript_manual`**: `boolean`, default: `false`

  True if the user wrote or corrected the transcript, so it must not be re-derived from word\_timestamps
- **`voice_type`**: `string`, default: `"clone"`

  Voice type: 'clone' or 'design'
- **`word_timestamps`**: `(array of object) | null`

  Word-level timestamps \[{text,start\_time,end\_time}] for local trim slicing

**Example:**

```json
{
  "name": "My Custom Voice",
  "audio_base64": "UklGRi4AAABXQVZFZm10IBAAAA...",
  "transcript": "Hello, this is a sample of my voice.",
  "voice_type": "clone",
  "ref_text": "Hello, this is a sample of my voice.",
  "word_timestamps": [
    {
      "additionalProperty": "anything"
    }
  ],
  "transcript_manual": false,
  "source": {
    "task_id": "",
    "start": 0,
    "end": 1
  }
}
```

## Responses

### 200 Successful Response

**Content type:** `application/json`

schema: `VoiceSaveResponse`

- **`success` (required)**: `boolean`

  Whether the voice was saved successfully
- **`message`**: `string | null`

  Error message if save failed
- **`voice`**: `object | null`, schema: `VoiceItem`

  Saved voice metadata
  - **`created_at` (required)**: `string`

    ISO 8601 creation timestamp
  - **`duration_seconds` (required)**: `number`

    Duration of the reference audio in seconds
  - **`id` (required)**: `string`

    Unique voice identifier
  - **`name` (required)**: `string`

    User-assigned voice name
  - **`transcript` (required)**: `string`

    Transcript of the reference audio
  - **`created_with_model`**: `string | null`

    Model family the voice was created with
  - **`has_voice_clone_prompt`**: `boolean`, default: `false`

    Whether a precomputed voice prompt cache exists
  - **`ref_text`**: `string | null`

    Reference text used during cloning
  - **`source`**: `object | null`, schema: `VoiceSourceModel`

    Public sample the audio was cut from, when imported

    *Schema `VoiceSourceModel` is shown above.*
  - **`starter_key`**: `string | null`

    Starter voice key when the voice came from the starter set
  - **`transcript_manual`**: `boolean | null`

    True if the transcript was written or corrected by the user
  - **`voice_type`**: `string`, default: `"clone"`

    Voice type: 'clone' or 'design'
  - **`word_timestamps`**: `(array of object) | null`

    Word-level timestamps if persisted

**Example:**

```json
{
  "success": true,
  "voice": {
    "id": "a1b2c3d4",
    "name": "My Custom Voice",
    "transcript": "Hello, this is a sample of my voice.",
    "ref_text": "",
    "voice_type": "clone",
    "created_at": "2026-01-15T10:30:00Z",
    "duration_seconds": 8.5,
    "has_voice_clone_prompt": false,
    "word_timestamps": [
      {
        "additionalProperty": "anything"
      }
    ],
    "transcript_manual": true,
    "created_with_model": "",
    "starter_key": "",
    "source": {
      "task_id": "",
      "start": 0,
      "end": 1
    }
  },
  "message": ""
}
```

### 400 Clone audio is longer than 30 seconds.

### 422 Validation Error

**Content type:** `application/json`

schema: `HTTPValidationError`

- **`detail`**: `array`

  **Items:**

  schema: `ValidationError`
  - **`loc` (required)**: `array of (string | integer)`
  - **`msg` (required)**: `string`
  - **`type` (required)**: `string`
  - **`ctx`**: `object`
  - **`input`**: `any`

**Example:**

```json
{
  "detail": [
    {
      "loc": [
        ""
      ],
      "msg": "",
      "type": "",
      "input": null,
      "ctx": {}
    }
  ]
}
```

## Schemas

- `HTTPValidationError` — shown above.
- `SaveVoiceRequest` — shown above.
- `ValidationError` — shown above.
- `VoiceItem` — shown above.
- `VoiceSaveResponse` — shown above.
- `VoiceSourceModel` — shown above.
