# Change a voice

- **Method:** `POST`
- **Path:** `/v1/voice-changer`
- **Operation ID:** `createVoiceChange`
- **Tags:** Voice changer

Makes speech sound like one of your saved voices. The audio can be up to 60 minutes long. Returns a job whose result is an `AudioResult`.

## Effective servers

- `https://api.vcp.name`

## Authentication

- **bearer**: HTTP bearer (`API key`)

  An API key from Settings, starting vcp\_live\_.

## Header parameters

- **`Idempotency-Key`**: `string`, maxLength: `255`

  Optional. Up to 255 characters, scoped to your account and kept for 90 days. Sending the same key with the same body again returns the original job. The same key with a different body is rejected with 409.

## Request body

**Required:** `true`

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

schema: `VoiceChangeBody`, no additional properties

- **`voice` (required)**: `string`, minLength: `1`

  A saved voice id or name. Presets cannot be used.
- **`audio_file_id`**: `string`

  A file\_id from POST /v1/uploads. Send this or audio\_url.
- **`audio_url`**: `string`, format: `uri`

  An https link to the audio, up to 25 MB. Send this or audio\_file\_id.

**Example:**

```json
{
  "audio_file_id": "8383fc02-625a-4b71-a226-cbb2d19aaf17",
  "voice": "Narrator"
}
```

## Responses

### 202 Accepted. Returns the job.

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

schema: `Job`, no additional properties

- **`created_at` (required)**: `string`, format: `date-time`

  When the job was created.
- **`error` (required)**: `object | null`, schema: `ErrorDetail`, no additional properties

  Why the job failed, or null.
  - **`code` (required)**: `string`

    A code from the error tables.
  - **`message` (required)**: `string`

    What went wrong.
  - **`param`**: `string`

    The request field at fault, when there is one.
- **`finished_at` (required)**: `string | null`, format: `date-time`

  When the job finished, or null while it runs.
- **`id` (required)**: `string`

  Job id.
- **`progress` (required)**: `number | null`, minimum: `0`, maximum: `1`

  From 0 to 1 while an avatar video renders, a dub runs or a video is cut, otherwise null.
- **`resource_id` (required)**: `string | null`

  The voice id for voice clones, the project id for dubs and cuts, and the video id for avatar videos.
- **`result` (required)**

  The result of a succeeded job, or null. Speech, voice designs and the voice changer give AudioResult, kept for 24 hours after the job finishes, then this is null. Transcriptions give TranscriptionResult. Voice clones give VoiceCloneResult. Avatar videos give AvatarVideoResult, dubs give DubResult and cuts give CutResult, all kept for 24 hours after the job was created.

  **Any of:**
  - `object`, schema: `AudioResult`, no additional properties

    Links to the audio. The audio is kept for 24 hours after the job finishes.
    - **`audio_url` (required)**: `string`, format: `uri`

      WAV audio link for playback.
    - **`download_url` (required)**: `string`, format: `uri`

      The same audio, served as a download.
    - **`expires_at` (required)**: `string`, format: `date-time`

      When both links stop working, 24 hours after the job finished.
  - `object`, schema: `TranscriptionResult`, no additional properties

    The transcript of the audio.
    - **`language` (required)**: `string | null`

      The spoken language, or null if unknown.
    - **`text` (required)**: `string`

      The full transcript.
    - **`words` (required)**: `array | null`

      Each word with its timing, or null without timestamps.

      **Items:**

      schema: `Word`, no additional properties
      - **`end` (required)**: `number`, minimum: `0`

        Seconds from the start of the audio.
      - **`speaker` (required)**: `string`

        Who said the word, as SPEAKER\_00, SPEAKER\_01 and so on.
      - **`start` (required)**: `number`, minimum: `0`

        Seconds from the start of the audio.
      - **`text` (required)**: `string`
  - `object`, schema: `VoiceCloneResult`, no additional properties

    The saved voice.
    - **`transcript` (required)**: `string | null`

      What the clip says, or null if it has no transcript.
    - **`voice` (required)**: `object`, schema: `Voice`, no additional properties
      - **`created_at` (required)**: `string | null`, format: `date-time`

        When the voice was saved, or null for presets.
      - **`duration_seconds` (required)**: `number | null`, minimum: `0`

        Length of the reference clip, or null.
      - **`id` (required)**: `string`

        A uuid for saved voices, or the preset id.
      - **`model` (required)**: `string | null`

        The model a preset belongs to, or null for saved voices.
      - **`name` (required)**: `string`
      - **`type` (required)**: `string`, possible values: `"clone", "design", "preset"`
  - `object`, schema: `AvatarVideoResult`, no additional properties

    Links to the video. The video is kept for 24 hours after the job was created.
    - **`download_url` (required)**: `string`, format: `uri`

      The same video, served as a download.
    - **`duration_s` (required)**: `number`, minimum: `0`

      The video length in seconds.
    - **`expires_at` (required)**: `string`, format: `date-time`

      When the links stop working and the video is deleted, 24 hours after the job was created.
    - **`height` (required)**: `integer | null`, minimum: `1`

      The video height in pixels, or null if unknown.
    - **`thumbnail_url` (required)**: `string | null`, format: `uri`

      A still image of the video, or null if there is none.
    - **`video_url` (required)**: `string`, format: `uri`

      MP4 video link for playback.
    - **`width` (required)**: `integer | null`, minimum: `1`

      The video width in pixels, or null if unknown.
  - `object`, schema: `DubResult`, no additional properties

    Links to the dubbed video and its parts. The dub is kept for 24 hours after the job was created.
    - **`audio_url` (required)**: `string`, format: `uri`

      The new voices on their own, as a WAV file.
    - **`background_url` (required)**: `string | null`, format: `uri`

      The music and sound effects without the voices, as a WAV file, or null when keep\_background was false.
    - **`download_url` (required)**: `string`, format: `uri`

      The same video, served as a download.
    - **`duration_s` (required)**: `number`, minimum: `0`

      The video length in seconds.
    - **`expires_at` (required)**: `string`, format: `date-time`

      When the links stop working and the dub is deleted, 24 hours after the job was created.
    - **`lipsynced` (required)**: `boolean`

      True when the lips were matched to the new voices.
    - **`source_language` (required)**: `string | null`

      The spoken language of the original video, or null if unknown.
    - **`speakers` (required)**: `integer`, minimum: `0`

      How many speakers were found.
    - **`subtitles_url` (required)**: `string`, format: `uri`

      GET /v1/dubs/{id}/subtitles for this job. Send your API key with it.
    - **`target_language` (required)**: `string`

      The language the video was dubbed into.
    - **`video_url` (required)**: `string`, format: `uri`

      MP4 video link for playback. The lip-synced video when lip sync ran, otherwise the dubbed video.
  - `object`, schema: `CutResult`, no additional properties

    Links to the cut video and what was taken out. The cut is kept for 24 hours after the job was created.
    - **`download_url` (required)**: `string`, format: `uri`

      The same video, served as a download.
    - **`duration_s` (required)**: `number`, minimum: `0`

      The cut video length in seconds.
    - **`expires_at` (required)**: `string`, format: `date-time`

      When the links stop working and the cut is deleted, 24 hours after the job was created.
    - **`height` (required)**: `integer | null`, minimum: `1`

      The video height in pixels, or null if unknown.
    - **`incomplete` (required)**: `array`

      Which of fillers, retakes or silences could not check the whole video. Empty when every step checked it all.

      **Items:**

      `string`, possible values: `"fillers", "retakes", "silences"`
    - **`language` (required)**: `string | null`

      The spoken language, or null if unknown.
    - **`removed` (required)**: `array`

      Each part taken out of the uploaded video, in order, with why it was taken out. Empty when nothing needed cutting.

      **Items:**

      no additional properties
      - **`end` (required)**: `number`, minimum: `0`

        Seconds from the start of the uploaded video.
      - **`reasons` (required)**: `array`

        Why the part was taken out. Lists silence only when no filler or retake was found in the part.

        **Items:**

        `string`, possible values: `"filler", "retake", "silence"`
      - **`start` (required)**: `number`, minimum: `0`

        Seconds from the start of the uploaded video.
    - **`source_duration_s` (required)**: `number`, minimum: `0`

      The uploaded video length in seconds.
    - **`video_url` (required)**: `string`, format: `uri`

      MP4 video link for playback.
    - **`width` (required)**: `integer | null`, minimum: `1`

      The video width in pixels, or null if unknown.
  - `null`
- **`status` (required)**: `string`, possible values: `"queued", "running", "succeeded", "failed", "cancelled"`
- **`tokens_charged` (required)**: `integer | null`, minimum: `0`

  Tokens billed, or null until billing has run.
- **`type` (required)**: `string`, possible values: `"speech", "voice_design", "voice_clone", "voice_change", "transcription", "dub", "avatar_video", "cut"`

**Example:**

```json
{
  "id": "04bd0571-e2c8-4d5b-a3cc-e56f85773abf",
  "type": "voice_change",
  "status": "queued",
  "progress": null,
  "result": null,
  "error": null,
  "tokens_charged": null,
  "resource_id": null,
  "created_at": "2026-10-30T00:10:42Z",
  "finished_at": null
}
```

### 400, 401, 402, 403, 404, 409, 413, 429, 500, 503

- `400` The request is invalid. The message names the field.
- `401` The API key is missing, invalid or revoked.
- `402` The account is out of tokens for this period.
- `403` The account needs a paid plan, or the action is not allowed.
- `404` Not found.
- `409` Conflicts with the current state, or an Idempotency-Key was reused with a different body.
- `413` The request is too large.
- `429` Too many requests, or this account already has too many jobs in progress. Retry after the Retry-After header.
- `500` Something went wrong on our side.
- `503` Temporarily unavailable. Retry after the Retry-After header.

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

schema: `ErrorBody`, no additional properties

- **`error` (required)**: `object`, schema: `ErrorDetail`, no additional properties

  *Schema `ErrorDetail` is shown above.*

**Example:**

```json
{
  "error": {
    "code": "invalid_request",
    "message": "text is required.",
    "param": "text"
  }
}
```

## Schemas

### ErrorBody

**Type:** `object`, no additional properties

*Schema `ErrorBody` is shown above.*

**Example:**

```json
{
  "error": {
    "code": "invalid_request",
    "message": "text is required.",
    "param": "text"
  }
}
```

- `ErrorDetail` — shown above.

### JobType

**Type:** `string`, possible values: `"speech", "voice_design", "voice_clone", "voice_change", "transcription", "dub", "avatar_video", "cut"`

### JobStatus

**Type:** `string`, possible values: `"queued", "running", "succeeded", "failed", "cancelled"`

- `Job` — shown above.

### AudioResult

**Type:** `object`, no additional properties

Links to the audio. The audio is kept for 24 hours after the job finishes.

*Schema `AudioResult` is shown above.*

**Example:**

```json
{
  "audio_url": "https://files.example.com/speech.wav",
  "download_url": "https://files.example.com/speech.wav?download=speech.wav",
  "expires_at": "2026-10-31T00:10:42Z"
}
```

### TranscriptionResult

**Type:** `object`, no additional properties

The transcript of the audio.

*Schema `TranscriptionResult` is shown above.*

**Example:**

```json
{
  "text": "Welcome back to the show.",
  "language": "English",
  "words": [
    {
      "text": "Welcome",
      "start": 0.32,
      "end": 0.71,
      "speaker": "SPEAKER_00"
    },
    {
      "text": "back",
      "start": 0.71,
      "end": 0.94,
      "speaker": "SPEAKER_00"
    }
  ]
}
```

### VoiceCloneResult

**Type:** `object`, no additional properties

The saved voice.

*Schema `VoiceCloneResult` is shown above.*

**Example:**

```json
{
  "voice": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "name": "Narrator",
    "type": "clone",
    "model": null,
    "duration_seconds": 12.4,
    "created_at": "2026-10-30T00:10:42Z"
  },
  "transcript": "Welcome back to the show."
}
```

### AvatarVideoResult

**Type:** `object`, no additional properties

Links to the video. The video is kept for 24 hours after the job was created.

*Schema `AvatarVideoResult` is shown above.*

**Example:**

```json
{
  "video_url": "https://files.example.com/avatar.mp4",
  "download_url": "https://files.example.com/avatar.mp4?download=avatar.mp4",
  "thumbnail_url": "https://files.example.com/avatar.jpg",
  "duration_s": 8.2,
  "width": 1280,
  "height": 720,
  "expires_at": "2026-10-31T00:10:42Z"
}
```

### DubResult

**Type:** `object`, no additional properties

Links to the dubbed video and its parts. The dub is kept for 24 hours after the job was created.

*Schema `DubResult` is shown above.*

**Example:**

```json
{
  "video_url": "https://files.example.com/dub.mp4",
  "download_url": "https://files.example.com/dub.mp4?download=dub.mp4",
  "audio_url": "https://files.example.com/dub-voices.wav",
  "background_url": "https://files.example.com/dub-background.wav",
  "subtitles_url": "https://api.example.com/v1/dubs/04bd0571-e2c8-4d5b-a3cc-e56f85773abf/subtitles",
  "duration_s": 94.5,
  "source_language": "English",
  "target_language": "es",
  "speakers": 2,
  "lipsynced": false,
  "expires_at": "2026-10-31T00:10:42Z"
}
```

### CutResult

**Type:** `object`, no additional properties

Links to the cut video and what was taken out. The cut is kept for 24 hours after the job was created.

*Schema `CutResult` is shown above.*

**Example:**

```json
{
  "video_url": "https://files.example.com/cut.mp4",
  "download_url": "https://files.example.com/cut.mp4?download=cut.mp4",
  "duration_s": 281.344,
  "source_duration_s": 485.87,
  "width": 1080,
  "height": 1920,
  "removed": [
    {
      "start": 0,
      "end": 107.62,
      "reasons": [
        "retake"
      ]
    },
    {
      "start": 120.786,
      "end": 121.106,
      "reasons": [
        "filler"
      ]
    },
    {
      "start": 129.3,
      "end": 129.44,
      "reasons": [
        "silence"
      ]
    }
  ],
  "language": "English",
  "incomplete": [],
  "expires_at": "2026-10-31T00:10:42Z"
}
```

- `Word` — shown above.
- `Voice` — shown above.
- `VoiceChangeBody` — shown above.
