Appearance
Ошибки и лимиты
Формат ошибок
Все ошибки возвращают JSON с полем detail. Обычно это строка с описанием:
json
{
"detail": "Описание ошибки"
}Для ошибок с машиночитаемым кодом detail может быть объектом. Например, конфликт Idempotency-Key возвращается так:
json
{
"detail": {
"code": "idempotency_key_conflict",
"message": "Idempotency-Key was already used with a different ASR request"
}
}Ошибки валидации FastAPI также могут содержать массив элементов в detail. Клиенту не следует предполагать, что detail всегда имеет строковый тип: сначала проверьте строку, объект или массив, а для программной обработки объекта используйте поле detail.code.
HTTP-коды ответов
| Код | Значение | Когда возникает |
|---|---|---|
400 | Bad Request | Некорректный запрос: текст слишком длинный, не указан голос, неверный формат |
401 | Unauthorized | Отсутствует, невалидный, истёкший или отозванный API-ключ |
402 | Payment Required | Недостаточный баланс для синтеза |
403 | Forbidden | Модель недоступна на вашем тарифе |
408 | Request Timeout | Синтез занял более 5 минут |
413 | Content Too Large | Размер тела запроса превышает лимит edge |
429 | Too Many Requests | Превышен лимит запросов или параллельных подключений |
500 | Internal Server Error | Внутренняя ошибка сервера |
502 | Bad Gateway | TTS-воркер не смог обработать запрос |
Лимиты запросов
Лимиты применяются на Workspace (не на отдельный API-ключ). Участники и все API-ключи Workspace используют общие окна.
TTS: запросы в минуту и параллельная обработка
Для TTS контролируются два ограничения:
- запросы в минуту (RPM) в скользящем окне длительностью 1 минута;
- количество TTS-запросов, обрабатываемых одновременно.
| Тариф | RPM | Параллельных |
|---|---|---|
| Бесплатный | 5 | 1 |
| Старт | 8 | 1 |
| Базовый | 10 | 2 |
| Продвинутый | 30 | 5 |
| Проект | 45 | 8 |
| Команда | 60 | 10 |
| Масштаб | 120 | 15 |
ASR: категории запросов
Попытки создать новые синхронные и асинхронные ASR-задачи относятся к категории TARIFF_ASR. Они используют одно общее окно asr_rpm:
| Тариф | Попыток создания ASR-задач в минуту |
|---|---|
| Бесплатный | 20 |
| Старт | 20 |
| Базовый | 20 |
| Продвинутый | 20 |
| Проект | 40 |
| Команда | 40 |
| Масштаб | 60 |
Каждый авторизованный POST, включая повтор с известным Idempotency-Key, расходует попытку до чтения файла. Поэтому невалидный запрос, конфликт тела или отказ из-за баланса тоже учитывается в TARIFF_ASR. Результат повтора остаётся идемпотентным: новая задача и списание не создаются.
Только GET статуса относится к отдельной TARIFF_ASR_STATUS: 120/мин до «Продвинутого», 200/мин на «Проекте» и «Команде», 300/мин на «Масштабе».
Количество активных ASR-задач отдельно не ограничивается. Валидные задачи принимаются, пока хватает доступного баланса; стоимость уже принятых активных задач учитывается при проверке следующей задачи. Этот лимит регулирует только скорость приёма в асинхронную очередь и не является обещанием realtime-обработки.
Обработка ошибки 429
При превышении лимита ответ выглядит так:
json
{
"detail": "Rate limit exceeded (5/5 requests per minute)"
}Ответ 429 содержит заголовок Retry-After с числом секунд до следующей попытки. Используйте его как минимальную задержку; при повторных 429 увеличивайте паузу.
python
import time
import requests
def synthesize_with_retry(url, headers, payload, max_retries=3):
for attempt in range(max_retries):
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", "1"))
delay = max(retry_after, 2 ** attempt)
time.sleep(delay)
continue
return response
raise Exception("Превышено количество попыток")