Перейти к содержанию

Ошибки

Публичный API возвращает стандартные HTTP-коды. Текущие два эндпоинта (POST /verifications/, GET /verifications/{id}/) сохраняют исходные форматы тел ответов (legacy-формат DRF) для обратной совместимости — новые эндпоинты будут использовать единый envelope (см. ниже).

Каталог HTTP-кодов

Код Значение Когда
400 Bad Request Валидация запроса Невалидный JSON, отсутствуют обязательные поля, плохой формат phone или webhook_url.
401 Unauthorized Аутентификация Нет заголовка, неверный / отозванный токен.
403 Forbidden Авторизация Аутентификация прошла, но не Bearer (например, сессия).
404 Not Found Ресурс не найден Несуществующий verification_id или принадлежит другой компании.
405 Method Not Allowed Неверный метод Например, PUT на /verifications/.
429 Too Many Requests Лимит Превышен 120 req/min на ключ. Заголовок Retry-After.
500 Internal Server Error Бага на нашей стороне Сообщите в саппорт с verification_id и временем.
503 Service Unavailable Нет DID Закончились свободные номера. Заголовок Retry-After: 60.

Форматы тел ответа

Валидация (400)

DRF-формат: ключ — имя поля, значение — массив строк-ошибок.

{
  "phone": ["Invalid phone number"]
}

Возможные ошибки полей:

Поле Сообщения
phone "Invalid phone number" (нормализованное; не раскрывает детали парсера, чтобы нельзя было энумерировать валидные форматы)
webhook_url "Enter a valid URL.", "URL host is not allowed (private/loopback/link-local).", "URL scheme must be http or https.", "URL too long."
client_ref "Ensure this field has no more than 120 characters."
ttl_seconds "Ensure this value is greater than or equal to 1.", "Ensure this value is less than or equal to 3600."

Если в JSON битый синтаксис — DRF вернёт:

{
  "detail": "JSON parse error - Expecting value: line 1 column 1 (char 0)"
}

Аутентификация (401)

{
  "detail": "Authentication credentials were not provided."
}

или

{
  "detail": "Invalid token."
}

В заголовках: WWW-Authenticate: Bearer realm="api".

Авторизация (403)

{
  "detail": "API key required."
}

Возникает, если запрос прошёл другую аутентификацию (например, сессию дашборда) — Bearer-эндпоинты требуют именно ApiKey-пользователя.

Не найдено (404)

{
  "detail": "Not found."
}

Лимит (429)

{
  "detail": "Request was throttled. Expected available in 23 seconds."
}

В заголовках: Retry-After: 23. Подробнее — Лимиты.

Нет свободных DID (503)

{
  "error": "no_dial_number_available",
  "retry_after": 60
}

В заголовках: Retry-After: 60. Это единственный legacy-эндпоинт с машинно-читаемым error-кодом. Рекомендуется ловить именно этот HTTP-код (503) и/или строку "no_dial_number_available".


Новый envelope (для будущих эндпоинтов)

При добавлении новых эндпоинтов мы будем использовать единый формат:

{
  "error": {
    "code": "<machine_code>",
    "message": "<human-readable>",
    "fields": {
      "<field>": ["<msg>", "..."]
    }
  }
}

Поле fields — опциональное (только для ошибок валидации).

Машинно-читаемые коды

code HTTP Описание
invalid_request 400 Ошибка валидации
authentication_failed 401 Аутентификация
permission_denied 403 Авторизация
not_found 404 Не найдено
method_not_allowed 405 Метод не разрешён
conflict 409 Конфликт состояния
rate_limited 429 Превышен лимит
no_dial_number_available 503 Нет свободных DID
idempotency_conflict 409 Idempotency-ключ переиспользован с другим телом
service_unavailable 503 Временно недоступно
internal_error 500 Внутренняя ошибка

Существующие два эндпоинта продолжают использовать legacy-формат. Документация конкретного эндпоинта точно указывает, какой формат возвращается.


Рекомендации по обработке

  • Ретраить автоматически только 429 (с уважением к Retry-After) и 503. Максимум 3 попытки с экспоненциальным backoff.
  • Не ретраить 4xx кроме 429 — это ошибка на вашей стороне.
  • Алертить 5xx (кроме 503 при попытках с backoff) — это может быть инцидент на стороне TrueNum.
  • Логировать все ответы вместе с verification_id (если получен) — упростит дебаг.