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-воркер не смог обработать запрос |
Лимиты запросов
Лимиты применяются на пользователя (не на API-ключ). Все API-ключи одного аккаунта используют общие окна.
TTS: запросы в минуту и параллельная обработка
Для TTS контролируются два ограничения:
- запросы в минуту (RPM) в скользящем окне длительностью 1 минута;
- количество TTS-запросов, обрабатываемых одновременно.
| Тариф | RPM | Параллельных |
|---|---|---|
| Бесплатный | 5 | 1 |
| Старт | 8 | 1 |
| Базовый | 10 | 2 |
| Продвинутый | 30 | 5 |
ASR: категории запросов
Попытки создать новые синхронные и асинхронные ASR-задачи относятся к категории TARIFF_ASR. Они используют одно общее окно asr_rpm:
| Тариф | Попыток создания ASR-задач в минуту |
|---|---|
| Бесплатный | 20 |
| Старт | 20 |
| Базовый | 20 |
| Продвинутый | 20 |
| Бизнес / Постоплата | 40 |
Авторизованный POST без уже известного Idempotency-Key расходует попытку до чтения файла. Поэтому невалидный запрос или отказ из-за баланса тоже учитывается в этом окне.
Повтор POST по уже известному Idempotency-Key не создаёт новую задачу и не расходует TARIFF_ASR. Такой повтор и GET статуса относятся к общей категории WEB_DEFAULT — 60 запросов в минуту на пользователя. Они используют одно общее окно, поэтому частый polling уменьшает доступную частоту idempotent-повторов и наоборот.
Количество активных 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("Превышено количество попыток")