Верификации¶
Два эндпоинта: создание верификации и чтение статуса.
POST /api/v1/verifications/¶
Создаёт новую верификацию, забирает свободный DID на TTL и возвращает
его. Звонок на этот номер от телефона, переданного в phone, приведёт
к успешной верификации.
Запрос¶
POST /api/v1/verifications/ HTTP/1.1
Host: app.truenum.ru
Authorization: Bearer tn_live_<prefix>_<secret>
Content-Type: application/json
{
"phone": "+79991234567",
"webhook_url": "https://your-app.example.com/callbacks/phone-verify",
"client_ref": "user-1234",
"ttl_seconds": 300
}
Параметры тела¶
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
phone |
string (E.164) | ✓ | Номер, владельцем которого подтверждается пользователь. Формат +<country><number>, до 32 символов. |
webhook_url |
string (URL) | ✓ | HTTPS-эндпоинт для уведомлений о результате. До 500 символов. Должен указывать на публичный адрес (внутренние/loopback IP отклоняются — см. SSRF-защита). |
client_ref |
string | — | Произвольный идентификатор на вашей стороне (user_id, order_id). До 120 символов. Возвращается обратно в webhook. По умолчанию "". |
ttl_seconds |
int | — | Сколько секунд DID будет «зарезервирован» под эту верификацию. Минимум 1, максимум 3600, по умолчанию 300 (5 минут). |
Успешный ответ — 201 Created¶
{
"verification_id": "ver_01HXYZ4K9P2N3M8R7Q5S6T0V1W",
"phone": "+79991234567",
"dial_number": "+74951234567",
"client_ref": "user-1234",
"status": "pending",
"ttl_seconds": 300,
"created_at": "2026-05-26T12:30:00+00:00",
"expires_at": "2026-05-26T12:35:00+00:00",
"completed_at": null,
"caller_id_received": ""
}
В заголовках ответа:
Поля ответа¶
| Поле | Тип | Описание |
|---|---|---|
verification_id |
string | Уникальный ID, формат ver_<26 alphanumeric> (ULID). |
phone |
string | Эхо номера из запроса. |
dial_number |
string (E.164) | Номер, на который пользователь должен позвонить. |
client_ref |
string | Эхо из запроса. |
status |
string | Один из pending, completed, expired, failed. На момент создания — всегда pending. |
ttl_seconds |
int | Эхо из запроса (или дефолт 300). |
created_at |
string (ISO 8601) | Момент создания верификации, UTC. |
expires_at |
string (ISO 8601) | created_at + ttl_seconds. После этого момента DID освобождается и звонок не примется. |
completed_at |
string | null | Заполнено только при status=completed (момент входящего звонка). |
caller_id_received |
string | Caller-ID, который мы зафиксировали при звонке (заполнено только при status=completed). |
Ошибки¶
| Код | Что произошло |
|---|---|
400 |
Невалидный JSON или поля (phone, webhook_url). |
401 |
Отсутствует / неверный / отозванный токен. |
403 |
Заголовок Authorization есть, но не Bearer-токен (например, сессионная аутентификация). |
429 |
Превышен лимит 120 req/min на ключ. |
503 |
Нет свободных DID. Заголовок Retry-After: 60. |
Подробнее — Ошибки.
Что происходит дальше¶
- У вас на руках
dial_number. Покажите его пользователю с инструкцией «позвоните на этот номер с указанного телефона; вешать трубку не обязательно — звонок прервётся сам». - Пользователь звонит. Наша инфраструктура отвечает SIP-кодом
486 Busy Here— у пользователя короткий гудок и отбой. - На ваш
webhook_urlприходит POST сtype: "verification.completed"и зафиксированнымcaller_id. - На вашей стороне: проверьте подпись webhook'а, сравните
caller_idсphoneиз исходного запроса (поverification_id), при совпадении — пометьте номер как верифицированный.
Если за TTL звонок не поступил, придёт webhook с type:
"verification.expired". Подробнее: Webhooks.
GET /api/v1/verifications/{id}/¶
Возвращает текущий статус верификации. Полезен как фоллбек, если webhook не дошёл (но в норме полагайтесь на webhook — он быстрее и не требует поллинга).
Запрос¶
GET /api/v1/verifications/ver_01HXYZ4K9P2N3M8R7Q5S6T0V1W/ HTTP/1.1
Host: app.truenum.ru
Authorization: Bearer tn_live_<prefix>_<secret>
Успешный ответ — 200 OK¶
Тело идентично ответу на POST (та же схема), но с актуальным
status и заполненными completed_at / caller_id_received если
верификация завершилась.
Видимость¶
Эндпоинт возвращает только верификации вашей компании (привязка
по API-ключу). Запрос чужого verification_id → 404.
Ошибки¶
| Код | Что произошло |
|---|---|
401 |
Отсутствует / неверный / отозванный токен. |
403 |
Не Bearer-аутентификация. |
404 |
Верификация не существует или принадлежит другой компании. |
429 |
Превышен лимит. |
Статусы верификации¶
status |
Значение |
|---|---|
pending |
Создана, DID выдан, ждём звонка. |
completed |
Пользователь позвонил, caller-ID зафиксирован — успех. |
expired |
Истёк TTL, звонка не было. DID освобождён. |
failed |
Внутренняя ошибка (например, потеря связи с SIP-trunk до приёма звонка). Бывает редко; webhook с этим статусом не отправляется по умолчанию. |
Терминальные состояния: completed, expired, failed. После них
статус не меняется.
Жизненный цикл DID¶
Один DID в один момент времени привязан максимум к одной активной
верификации. После completed / expired / failed номер освобождается
и доступен для новых запросов.
Если в момент POST /verifications/ свободных DID нет, вы получите
503 no_dial_number_available с Retry-After: 60. Стратегия клиента:
ретрай с экспоненциальным backoff (60 → 120 → 240 секунд) и
максимум 3 попытки.