Ошибки и лимиты
Формат ошибок
Большинство ожидаемых ошибок возвращаются в стандартной оболочке FastAPI:
{
"detail": {
"error": "error_code",
"message": "Человекочитаемое описание ошибки.",
"details": {}
}
}| Поле | Тип | Описание |
|---|---|---|
detail.error | string | Машинный код ошибки (для логики) |
detail.message | string | Описание (для логирования/отображения) |
detail.details | object | Дополнительные данные (опционально) |
Ошибки Pydantic-валидации (422) возвращают detail как массив объектов. Для
неожиданной серверной ошибки (500) безопасный fallback может иметь вид
{"error":"Internal server error"}. Поэтому клиенту следует сначала читать
body.detail, а при его отсутствии — корневой объект.
HTTP-коды
| Код | Ошибка | Описание |
|---|---|---|
400 | invalid_request, unsupported_parameter, image_too_small | Невалидные данные, неправильный формат, либо параметр несовместим с другим (например, design_key при style=cinematic); для видео — исходник меньше 300×300 пикселей |
401 | missing_authorization, invalid_api_key | Отсутствует или невалидный API-ключ |
402 | insufficient_tokens | Недостаточно искр |
403 | forbidden | Нет доступа (ресурс принадлежит другому пользователю) |
404 | not_found | Ресурс не найден |
413 | image_too_large | Изображение превышает лимит |
422 | invalid_request или массив detail | Ошибка валидации (webhooks, параметры) |
429 | rate_limit_exceeded | Превышен лимит запросов |
500 | *_failed | Внутренняя ошибка сервера |
503 | generation_unavailable | Сервис генерации временно недоступен |
Детали по каждому коду
401 Unauthorized
{
"detail": {
"error": "missing_authorization",
"message": "Authorization header required. Use: Authorization: Bearer ak_..."
}
}{
"detail": {
"error": "invalid_api_key",
"message": "Invalid or revoked API key"
}
}Что делать: Проверьте заголовок Authorization: Bearer ak_.... Убедитесь, что ключ не отозван.
402 Payment Required
{
"detail": {
"error": "insufficient_tokens",
"message": "Not enough sparks. Balance: 2, required: 4.",
"details": {"available": 2, "required": 4}
}
}Что делать: Пополните баланс на app.aidentika.com . Проверьте текущий баланс через GET /balance.
403 Forbidden
{
"detail": {
"error": "forbidden",
"message": "Access denied"
}
}Что делать: Убедитесь, что action_id принадлежит вашему аккаунту.
413 Payload Too Large
{
"detail": {
"error": "image_too_large",
"message": "Image exceeds size limit"
}
}Что делать: Уменьшите изображение. Максимальный размер декодированного файла — 15 МБ; сама base64-строка будет примерно на треть больше.
429 Too Many Requests
{
"detail": {
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Limit: 100 requests/minute.",
"details": {"limit": 100, "reset_at": 1772000000}
}
}Заголовки ответа:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1772000000
Retry-After: 60Что делать: Подождите до reset_at или используйте Retry-After. Если нужен более высокий лимит — свяжитесь с поддержкой: @aidentika_support_bot .
503 Service Unavailable
{
"detail": {
"error": "generation_unavailable",
"message": "Generation service temporarily unavailable"
}
}Что делать: Сервис генерации временно недоступен. Повторите позже.
Обработка ошибок
Python
import time
import requests
def api_request(method, path, **kwargs):
resp = requests.request(method, f"{BASE_URL}{path}", headers=headers, **kwargs)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
time.sleep(retry_after)
return api_request(method, path, **kwargs)
if resp.status_code == 402:
error = resp.json().get("detail", {})
print(f"Недостаточно искр: {error['details']['available']}/{error['details']['required']}")
return None
if resp.status_code >= 400:
body = resp.json()
error = body.get("detail", body)
if isinstance(error, list):
raise Exception(f"Validation error: {error}")
raise Exception(f"API error {resp.status_code}: {error.get('error')} — {error.get('message')}")
return resp.json()Рекомендации
- Всегда проверяйте HTTP-код ответа, не только тело
- Обрабатывайте 429 с exponential backoff или
Retry-After - Проверяйте баланс перед пакетной генерацией через
GET /balance - Логируйте
detail.error,detail.messageиX-Request-Idдля отладки - Не парсите
messageдля логики — используйте полеerror(машинный код)
Лимиты
| Параметр | Значение |
|---|---|
| Запросов в минуту (по ключу) | Обычно 100; фактическое значение — в X-RateLimit-Limit |
| Активных API-ключей | 10 на аккаунт |
| Активных webhooks | 5 на аккаунт |
| Активных загрузок (uploads) | 20 на аккаунт |
| Время жизни upload | 1 час |
| Изображений в запросе | 5 |
| Размер файла после декодирования | 15 МБ |
| Глубина редактирований | 99 |
Срок действия свежего result_url | до 30 дней; это не срок хранения исходного файла |
Нужен более высокий лимит? Напишите в поддержку: @aidentika_support_bot .