---
title: "POST /voices/fishaudio/clones — Create Fish Audio Voice Clone"
url: https://lumean.app/developers/docs/api/post-voices-fishaudio-clones
locale: ru
description: "Create Fish Audio Voice Clone"
generated: 2026-10-17
operationId: fishAudioVoice.storeClone
method: POST
path: /voices/fishaudio/clones
scopes: [voices.write]
spec_version: 0.0.1
---

# POST /voices/fishaudio/clones

**Create Fish Audio Voice Clone**

Клонирует голос по образцу записи. Образец — base64 (можно data URI) в поле
`reference_audio` JSON-тела, до 20 МБ. Согласие: `consent_biometric: true` (на обработку
биометрии — образца голоса) и `voice_owner` (`self` — ваш голос, `third_party` — чужой, есть
согласие владельца) пишутся в журнал согласий вместе с id клона; прежний
`consent_confirmed: true` принимается вместо них, пока согласия не стали обязательными.

Клонирование асинхронное. Ответ `201` приходит сразу с клоном в статусе `pending`
(или сразу `failed` с `error.reason: dispatch_failed`, если очередь недоступна —
тогда повторите через `POST /voices/fishaudio/clones/{voiceClone}/retry`). Дальше
`pending` → `cloning` → `ready` (или `failed`). Ход приходит WS-событием
`voice_clone.updated` на канале `private-fishaudio-voice-clones.{userId}`; без WS —
опрашивайте `GET /voices/fishaudio/clones`.

Проверки по порядку: доступ к сервису (`404 service_not_found`), подписка (`402
no_subscription`) — живая подписка с правом Fish Audio нужна, только если сервис
закрыт для оплаты с баланса; иначе клонировать можно и без подписки, — потолок
клонов (`422 voice_clone_quota_exceeded`, поле `max` — потолок): без подписки
доступно 2 клона (запасной потолок), с подпиской — лимит тарифа. Те же правила,
что у Cartesia. Исчерпанная квота токенов клону не мешает.

**Требуемое право ключа:** `voices.write`.

- Право ключа: `voices.write`

## Запрос

```bash
curl -X POST 'https://api.lumean.app/api/public/voices/fishaudio/clones' \
  -H 'Accept: application/json' \
  -H 'X-API-KEY: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "display_name": "My voice",
  "reference_audio": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=",
  "language": "ru",
  "description": "Audiobook narrator",
  "consent_biometric": true,
  "voice_owner": "self"
}'
```

## Параметры

Параметров нет.

## Тело запроса

Новый клон голоса Fish Audio: образец записи в base64 и согласие на использование
голоса. Принимается как `application/json`.

Content-Type: `application/json`

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `display_name` | `string` — ≤ 128 симв. | обяз. | Название клона — видно только вам, до 128 символов. |
| `reference_audio` | `string` | обяз. | Образец голоса в base64; data URI (`data:audio/wav;base64,…`) тоже подходит. До 20 МБ после декодирования; формат — обычная аудиозапись (WAV, MP3 и т. п.). Нужна чистая речь одного человека без музыки и шума. |
| `consent_confirmed` | `string` | обяз. | Прежняя галочка «это ваш голос или у вас есть право его использовать». Нужна, только если не передан `consent_biometric: true`; когда согласия станут обязательными, вместо неё — `consent_biometric` и `voice_owner`. |
| `language` | `string` — шаблон: ^[a-z]{2}$ — nullable | — | Справочная метка клона, двухбуквенный код ISO 639-1 (`ru`, `en`, …). У голоса Fish Audio своего языка нет, провайдеру метка не передаётся. |
| `description` | `string` — ≤ 500 симв. — nullable | — | Ваше описание клона, до 500 символов. |
| `consent_biometric` | `boolean` | — | Согласие на обработку биометрических данных — образца голоса (https://lumean.app/consent/biometric). Пишется в журнал согласий вместе с id клона. `true` — согласие дано. |
| `voice_owner` | `string` — `self` · `third_party` — nullable | — | Чей голос в образце: `self` — ваш, `third_party` — чужой, и у вас есть согласие его владельца. |

**Пример**

```json
{
  "display_name": "My voice",
  "reference_audio": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=",
  "language": "ru",
  "description": "Audiobook narrator",
  "consent_biometric": true,
  "voice_owner": "self"
}
```

## Сценарии тела

### Образец — чистый base64

reference_audio — содержимое файла в base64 (без переносов строк), до 20 МБ после декодирования; формат определяется по содержимому (WAV, MP3, M4A/MP4, AAC, OGG, WebM, FLAC). consent_biometric — строго true, voice_owner — self или third_party. Здесь в reference_audio пустой WAV для краткости: настоящий образец — 10–60 секунд чистой речи одного человека.

```json
{
  "display_name": "My voice",
  "reference_audio": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=",
  "language": "ru",
  "description": "Audiobook narrator",
  "consent_biometric": true,
  "voice_owner": "self"
}
```

### Образец — data URI, минимум полей

Префикс data:audio/...;base64, допускается и отбрасывается сервером. language и description можно не передавать.

```json
{
  "display_name": "Podcast voice",
  "reference_audio": "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=",
  "consent_biometric": true,
  "voice_owner": "self"
}
```

## Ответы

### 201 — Клон поставлен в очередь

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Признак успеха. Решение принимайте по HTTP-коду: у любого ответа 2xx здесь `true`, а ошибка приходит телом другой формы, где этого поля может не быть вовсе. |
| `message` | `string` | обяз. | Пояснение для человека, на языке аккаунта. Показать пользователю можно; разбирать программно — нет: формулировки меняются без предупреждения и кодом ошибки не являются. |
| `data` | `FishAudioVoiceClone` | обяз. | Созданный клон — в статусе `pending` (или сразу `failed` с `error.reason: dispatch_failed`, если очередь недоступна). |
| `data.id` | `string` | обяз. | UUID клона. Его подставляют в пути `/voices/fishaudio/clones/{voiceClone}/…`; в шаблон он НЕ идёт — туда идёт `voice_id`. |
| `data.provider` | `string` — `fishaudio` | обяз. | Провайдер клона — всегда `fishaudio`. |
| `data.display_name` | `string` | обяз. | Название клона, заданное при создании. |
| `data.language` | `string` | обяз. | Справочная метка языка (ISO 639-1) либо `null`, если не передавалась. На клонирование не влияет. |
| `data.description` | `string` | обяз. | Ваше описание клона либо `null`. |
| `data.status` | `string` | обяз. | Статус: `pending` → `cloning` → `ready` либо `failed`; `archived` — снят владельцем; `banned` — заблокирован модератором. Озвучивать можно только `ready`. |
| `data.voice_id` | `string` | обяз. | Идентификатор голоса Fish Audio (строка из 32 hex-символов, не UUID) — значение для `tts_settings.voice_id` шаблона с `service_key: fishaudio`. Есть только у `ready`, иначе `null`. |
| `data.attempts` | `integer` | обяз. | Номер попытки клонирования: 1 при создании, +1 за каждый повтор. |
| `data.error` | `object` — nullable | обяз. | Причина отказа последней попытки; `null`, пока отказа не было. |
| `data.error.reason` | `string` | обяз. | Машинный код отказа: `processing_error`, `max_retries`, `network`, `timeout`, `dispatch_failed`, `unbanned` (клон разбанен, но голоса у него не было). Повторить попытку — `POST /voices/fishaudio/clones/{voiceClone}/retry`; если `processing_error` повторяется, смените образец. |
| `data.error.message` | `string` | обяз. | Пояснение к отказу для человека либо `null`. Ветвитесь по `reason`, а не по тексту. |
| `data.created_at` | `string` | обяз. | Когда клон создан. |
| `data.completed_at` | `string` | обяз. | Когда клон стал `ready`; `null` до этого. |
| `data.failed_at` | `string` | обяз. | Когда последняя попытка завершилась отказом; `null`, если отказа нет. |
| `data.banned_at` | `string` | обяз. | Когда клон заблокирован модератором (`status = banned`); `null`, если блокировки нет. |
| `data.ban_reason` | `string` | обяз. | Причина блокировки от модератора либо `null`. Заблокированный клон нельзя ни использовать, ни архивировать. |

**Пример**

```json
{
  "success": true,
  "message": "Success",
  "data": {
    "id": "01a10e08-27fe-716f-b428-6bc739602ca7",
    "provider": "fishaudio",
    "display_name": "My voice",
    "language": "ru",
    "description": null,
    "status": "pending",
    "voice_id": null,
    "attempts": 1,
    "error": null,
    "created_at": "2026-10-14T09:15:00+00:00",
    "completed_at": null,
    "failed_at": null,
    "banned_at": null,
    "ban_reason": null
  }
}
```

### 401 — Невалидный или отсутствующий X-API-KEY

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Всегда `false` в ответах об ошибке. |
| `message` | `string` | обяз. | Текст ошибки на языке ключа (задаётся заголовком `X-Locale`). |
| `data` | `null` — nullable | обяз. | Всегда `null`, когда запрос отклонён до обработки. |

**Пример**

```json
{
  "success": false,
  "message": "API key is missing. Provide it in the X-API-KEY header.",
  "data": null
}
```

### 402 — Нет живой подписки с правом Fish Audio (`no_subscription`) — только если сервис закрыт для оплаты с баланса

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Всегда `false` у ошибок. |
| `message` | `string` | обяз. | Причина отказа словами, на языке аккаунта. Для показа пользователю; ветвиться по ней нельзя — формулировки меняются. |
| `reason` | `string` | обяз. | Машиночитаемая причина бизнес-отказа (например, `input_expired`, `insufficient_balance`). Ветвите обработку по ней, а не по тексту `message`. |
| `error_code` | `string` | обяз. | Тот же машинный код, что в `reason`, — второе имя поля. Значения всегда совпадают. |

**Пример**

```json
{
  "success": false,
  "message": "An active subscription is required.",
  "reason": "no_subscription",
  "error_code": "no_subscription"
}
```

### 403 — У ключа нет права voices.write

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Всегда `false` в ответах об ошибке. |
| `message` | `string` | обяз. | Текст ошибки на языке ключа (задаётся заголовком `X-Locale`). |

**Пример**

```json
{
  "success": false,
  "message": "This API key does not have permission to perform this action."
}
```

### 404 — Сервис Fish Audio закрыт для владельца ключа (`service_not_found`)

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Всегда `false` у ошибок. |
| `message` | `string` | обяз. | Причина отказа словами, на языке аккаунта. Для показа пользователю; ветвиться по ней нельзя — формулировки меняются. |
| `reason` | `string` | обяз. | Машиночитаемая причина бизнес-отказа (например, `input_expired`, `insufficient_balance`). Ветвите обработку по ней, а не по тексту `message`. |
| `error_code` | `string` | обяз. | Тот же машинный код, что в `reason`, — второе имя поля. Значения всегда совпадают. |

**Пример**

```json
{
  "success": false,
  "message": "Service not found.",
  "reason": "service_not_found",
  "error_code": "service_not_found"
}
```

### 422 — Под этим кодом два разных тела. Ошибка валидации: `{success: false, message, errors: {поле: [текст]}}` без `reason` (нет обязательного поля, нет согласия `consent_biometric`/`consent_confirmed`, `language` не двухбуквенный код ISO 639-1, образец не base64, больше 20 МБ или не WAV/MP3/M4A/AAC/OGG/WebM/FLAC). Потолок клонов тарифа: `{success: false, message, reason: "voice_clone_quota_exceeded", error_code, max}` — `max` это потолок; заархивируйте клон (`DELETE`) или перейдите на старший тариф. Различайте по наличию `reason`

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `message` | `string` | обяз. | Errors overview. |
| `errors` | `object` | обяз. | A detailed description of each field that failed validation. |
| `errors.*` | `array<string>` — произвольные ключи | — |  |

**Пример**

```json
{
  "success": false,
  "message": "Validation error",
  "errors": {
    "consent_confirmed": [
      "The consent confirmed field must be accepted."
    ],
    "reference_audio": [
      "The file is too large: 20 MB at most."
    ]
  }
}
```

### 429 — Превышен лимит частоты клонирования (`rate_limit_exceeded`): по умолчанию 6 попыток в минуту и 60 в сутки на пользователя, общий с веб-кабинетом и LumVoice; считается каждая попытка, в том числе отклонённая валидацией. Ждать `retry_after` секунд (заголовок `Retry-After`)

**Поля ответа**

| Поле | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `success` | `boolean` | обяз. | Всегда `false` в ответах об ошибке. |
| `message` | `string` | обяз. | Текст ошибки на языке ключа (задаётся заголовком `X-Locale`). |
| `reason` | `string` | обяз. | Машиночитаемая причина отказа — по ней ветвите обработку, а не по тексту сообщения. |
| `error_code` | `string` | обяз. | Тот же машинный код, что в `reason`, — второе имя поля. Значения всегда совпадают; ветвитесь по любому из них. |
| `retry_after` | `integer` — nullable | — | Через сколько секунд имеет смысл повторить запрос (то же значение — в заголовке `Retry-After`). |

**Пример**

```json
{
  "success": false,
  "message": "Too many attempts. Please wait a moment and try again.",
  "reason": "rate_limit_exceeded",
  "error_code": "rate_limit_exceeded",
  "retry_after": 30
}
```

---

- Эта же страница в браузере: https://lumean.app/developers/docs/api/post-voices-fishaudio-clones
- Машинный справочник целиком: https://api.lumean.app/docs/llm.md
