---
title: "Каталог подій"
description: "Усі типи подій вебхуків, які надсилає ThunderPhone."
---

Кожне тіло вебхука має поле `type`, значенням якого є один із типів
подій на цій сторінці. Коли ви підписуєтеся на
[кінцеву точку](/uk/webhooks/endpoints), масив `events` має містити
потрібні вам типи подій (або бути порожнім, щоб підписатися на все —
крім подій для кожного ходу [`telephony.turn`](#telephony-turn) /
[`web.turn`](#web-turn), які надсилаються лише кінцевим точкам, де їх
явно вказано).

Ці події доставляються у двох стилях:

* **Доставки до endpoint** завжди є **неблокувальними** сповіщеннями з [повторними спробами](/uk/webhooks/overview): відповідайте будь-яким кодом 2xx; оболонка містить `event_id` для дедуплікації.
* **Блокувальні** обміни виконуються лише через [застарілий webhook з однією URL-адресою](/uk/webhooks/overview): запит конфігурації [`telephony.incoming` / `web.incoming`](/uk/webhooks/call-incoming) (номери в режимі webhook: 13 с, включно з однією повторною спробою; ключі віджета в режимі webhook: 10 с) і [диспетчеризація інструментів](/uk/tools/overview) у режимі webhook. Ваша відповідь формує перебіг активного дзвінка.

Наведені нижче приклади корисного навантаження показують конверт
кінцевої точки в порядку передавання (ключі відсортовано за абеткою:
`data`, `event_id`, `type`); застарілі доставки містять ті самі `data`
без `event_id`.

## Події викликів

### `telephony.incoming`

Надсилається, коли вхідний виклик надходить на один із ваших
[номерів телефонів](/api-reference/phone-numbers). Доставки до кінцевої точки є
сповіщеннями без очікування відповіді та надсилаються для **кожного** вхідного виклику,
незалежно від того, чи номер налаштовано для агента або вебхука. Номери без
призначеного агента також отримують **блокувальний** запит конфігурації
на застарілий вебхук — див.
[`telephony.incoming` / `web.incoming`](/uk/webhooks/call-incoming), щоб
переглянути повну схему запиту / відповіді.

```json
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `telephony.complete`

Надсилається після завершення вхідного або вихідного телефонного виклику. Неблокувальна.
Містить транскрипт, URL запису за наявності та підсумок виставлення рахунків. Див.
[`telephony.complete` / `web.complete`](/uk/webhooks/call-complete), щоб
переглянути схему корисного навантаження.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `telephony.tool`

Надсилається після того, як телефонний виклик викликає
[інструмент функції](/uk/tools/overview). Неблокувальне сповіщення для аудиту —
інструмент уже виконано на момент доставки цієї події; воно охоплює
ваші власні інструменти функцій і вбудований інструмент `send_sms` (але не інші вбудовані
інструменти, інструменти бази знань, підключень застосунків або MCP). Для `send_sms`
і `arguments.to`, і `arguments.body` мають значення `[REDACTED]`. У транскриптах
завершення їх також приховано; отримуйте вміст і отримувача з
SMS-ресурсу на рівні організації за допомогою `message_id` із відповіді.

```json
{
  "data": {
    "arguments": { "date": "2026-04-21" },
    "call_id": 987654321,
    "from_number": "+14155550199",
    "response": {
      "response": { "available_slots": ["9:00 AM", "2:00 PM"] },
      "status": 200
    },
    "to_number": "+15551234567",
    "tool_name": "search_appointments"
  },
  "event_id": "1f0a7c3e-52d4-4a0e-8f4b-b1a6a1c0d9e2",
  "type": "telephony.tool"
}
```

`response` — це результат виконання: `{"status": <http status>,
"response": <your endpoint's JSON>}` у разі успіху або
`{"status": <status>, "error": "<message>"}` у разі помилки.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `telephony.turn`

Надсилається, поки телефонний виклик **триває**, один раз для кожної
репліки з мовленням у момент її появи — озвучені відповіді агента та
транскрибовані репліки абонента. Дає змогу відстежувати розмову наживо
через звичайні вебхуки замість опитування
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).
Неблокувальна.

<Note>
  **Потрібна явна підписка.** На відміну від усіх інших типів подій,
  події реплік ніколи не доставляються через порожній масив `events`
  (підписка на все). Кінцева точка отримує їх, лише якщо її список `events`
  явно містить `telephony.turn` / `web.turn`.
</Note>

```json
{
  "data": {
    "call_id": 987654321,
    "entry_type": "completion",
    "from_number": "+14155550199",
    "position": 7,
    "role": "assistant",
    "start_ms": 15200,
    "text": "How many employees does your company have?",
    "to_number": "+15551234567"
  },
  "event_id": "8d3f5a2c-7b1e-4c9a-b6d0-2e4f6a8c0d1e",
  "type": "telephony.turn"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |
| `position` | integer | Індекс репліки в історії виклику — стабільний ідентифікатор для впорядкування |
| `role` | string | `assistant` (мовлення агента) або `user` (мовлення абонента) |
| `text` | string | Текст транскрипту репліки, відомий на момент надсилання |
| `entry_type` | string | Тип базового запису історії: `completion` (агент) або `user_turn` / `span` (абонент) |
| `start_ms`, `end_ms` | integer | Зміщення аудіо в мс від початку виклику; присутні лише якщо час відтворення вже був відомий на момент надсилання |

<Note>
  Доставка виконується щонайменше один раз, а репліки можуть надходити **не за порядком**:
  усувайте дублікати за `event_id` конверта та впорядковуйте за `position`. Транскрипти
  абонента можуть уточнюватися після надсилання; транскрипт
  [`telephony.complete`](/uk/webhooks/call-complete) після виклику є
  авторитетним. Надсилаються лише озвучені репліки — виклики інструментів, шепіт та
  інші внутрішні записи ніколи не з’являються в цьому потоці.
</Note>

### `web.incoming`

Еквівалент `telephony.incoming` для вебканалу, який надсилається, коли
починається сеанс [вебвіджета](/uk/widget/overview) або тестовий виклик мікрофона в конструкторі.
Доставки до кінцевої точки є сповіщеннями без очікування відповіді для кожного вебсеансу.
Публічні ключі в `mode="webhook"` також отримують
**блокувальний** запит конфігурації на застарілий вебхук — цей
блокувальний запит має іншу структуру (`origin_domain`,
`publishable_key_prefix`; без номерів телефонів). Див.
[`telephony.incoming` / `web.incoming`](/uk/webhooks/call-incoming).

```json
{
  "data": {
    "call_id": 987654322,
    "from_number": "web",
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2",
    "to_number": "+15551234567"
  },
  "event_id": "9a2b4c6d-8e0f-4a1b-9c2d-3e4f5a6b7c8d",
  "type": "web.incoming"
}
```

`from_number` завжди має буквальне значення `"web"`. Для сеансів віджета в режимі вебхука
`to_number` порожній (номер агента для сеансу призначається
після конфігурації); для тестових викликів мікрофона в конструкторі `origin_domain` і
`publishable_key_prefix` порожні.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `web.complete`

Еквівалент `telephony.complete` для вебканалу, який охоплює виклики
вебвіджета (`direction: "web"`) і тестові виклики мікрофона в конструкторі
(`direction: "test"`). Неблокувальна. Така сама структура корисного навантаження, як у
[`telephony.complete`](/uk/webhooks/call-complete), а також `origin_domain`,
де `from_number` має значення `"web"`.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

<Note>
  У застарілому вебхуку з однією URL-адресою тестові виклики мікрофона в конструкторі
  історично позначаються як `telephony.complete` — лише виклики з `direction:
  "web"` використовують там тип `web.complete`. Система кінцевих точок
  зіставляє як вебвиклики, так і тестові виклики з `web.*`. Історичні корисні навантаження можуть
  містити застарілі значення `direction`: `widget` або `mic`.
</Note>

### `web.tool`

Еквівалент `telephony.tool` для вебканалу. `data` містить
`origin_domain` замість `from_number` / `to_number`.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `web.turn`

Еквівалент [`telephony.turn`](#telephony-turn) для вебканалу, який
охоплює виклики вебвіджета та тестові виклики мікрофона в конструкторі. Така сама структура
корисного навантаження, але з `origin_domain` замість `from_number` / `to_number`.
Як і `telephony.turn`, потребує **явної підписки** —
ніколи не доставляється через порожній масив `events`.

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |

### `call.transfer_completed`

Надсилається один раз для кожного дзвінка з остаточним результатом
[переадресації дзвінка](/uk/guides/call-transfers): холодної переадресації або
з’єднання між людьми, яке залишається після теплої переадресації, коли агент виходить із дзвінка.
Не блокує виконання та надсилається лише на ендпоїнти (ніколи до застарілого
вебхука з однією URL-адресою). Надходить після `telephony.complete` дзвінка:
коли оператор приймає дзвінок або переадресація не вдається, або, коли
ThunderPhone з’єднав дзвінок, після завершення з’єднання.

```json
{
  "data": {
    "agent_id": 12,
    "agent_name": "Front desk",
    "bridge_kind": "cold_fallback",
    "bridge_seconds": 255,
    "bridge_total_cents": 5,
    "call_id": 987654321,
    "destination": "+15555550102",
    "sip_status": 403,
    "transfer_outcome": "bridged"
  },
  "event_id": "5b0f6c1e-9d2a-5e7b-8c4d-1a2b3c4d5e6f",
  "type": "call.transfer_completed"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `call_id` | integer | Дзвінок, який було переадресовано |
| `agent_id` | integer \| null | Агент, який обробляв дзвінок, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробляв дзвінок, якщо його було призначено |
| `transfer_outcome` | string | `refer_accepted`: оператор прийняв дзвінок. `bridged`: ThunderPhone сам підтримував з’єднання між абонентом і пунктом призначення, оскільки оператор відхилив холодну переадресацію або агент вийшов із теплої переадресації. `bridge_unanswered`: оператор відхилив холодну переадресацію, а пункт призначення не відповів на власний дзвінок ThunderPhone. `failed`: переадресація не відбулася, а дзвінок завершився |
| `destination` | string \| null | Номер, на який було переадресовано дзвінок |
| `sip_status` | integer \| null | SIP-статус оператора, коли він відхилив холодну переадресацію: `403` (наприклад, для транка Twilio без переадресації дзвінків), `405` або `501`. `null`, якщо оператор не відхилив її |
| `bridge_kind` | string \| null | Лише для `bridged`: `cold_fallback` (відхилена холодна переадресація, яку ThunderPhone з’єднав) або `warm` (двоє людей у теплій переадресації після виходу агента) |
| `bridge_seconds` | integer \| null | Лише для `bridged`: час з’єднання в секундах, за який ThunderPhone виставив рахунок |
| `bridge_total_cents` | integer \| null | Лише для `bridged`: вартість з’єднання в центах USD після застосування будь-якого безкоштовного кредиту на дзвінки; нараховується окремо від `billing_total_cents` дзвінка |

Ті самі значення доступні в [об’єкті дзвінка](/api-reference/calls#call-object)
як `transfer_outcome`, `transfer_destination`, `transfer_sip_status`,
`transfer_bridge_kind`, `transfer_bridge_seconds` і
`transfer_bridge_total_cents`. `event_id` є однаковим для кожної доставки
одного дзвінка, тому повторне повідомлення не створює другу подію.

---

## Події SMS

Події SMS описують повідомлення, надіслані через підключений обліковий запис
Twilio або Telnyx організації. Текст повідомлення не вказується, а значення `to`
редагується. Отримуйте повідомлення в межах організації за допомогою
[`GET /v1/sms/{message_id}`](/api-reference/sms#retrieve-a-message), коли
потрібен його вміст або одержувач.

### `sms.sent`

Надсилається, коли оператор клієнта приймає запит на надсилання вихідного SMS. Це не
підтвердження доставки на пристрій.

```json
{
  "data": {
    "accepted_at": "2026-09-19T15:42:10.113Z",
    "agent_id": 12,
    "call_id": 987654321,
    "created_at": "2026-09-19T15:42:09.901Z",
    "direction": "outbound",
    "error_code": null,
    "error_message": null,
    "from_number": "+15551234567",
    "id": "313a3117-827b-46e9-a01a-ac1493838724",
    "provider": "twilio",
    "provider_id": "SM0123456789abcdef0123456789abcdef",
    "segment_count": 1,
    "source": "agent_tool",
    "status": "accepted",
    "to": "[REDACTED]"
  },
  "event_id": "0ae347b4-1716-45bb-9a0e-b52373586e37",
  "type": "sms.sent"
}
```

### `sms.failed`

Надсилається після остаточної відмови оператора, після вичерпання повторних
спроб для тимчасових помилок або коли результат остаточно невідомий. `error_code` — це стабільний
код ThunderPhone, а `error_message` містить дію для клієнта, якщо її можна
вказати. `status: "unknown"` означає, що оператор міг прийняти SMS;
звірте це з журналом оператора, оскільки ThunderPhone не надсилатиме його повторно
автоматично.

### `sms.received`

Зарезервовано для підтримки вхідних SMS. У поточному випуску події
`sms.received` не надсилаються. Налаштування webhook для вхідних повідомлень від оператора та
перевірка підпису будуть випущені окремо.

---

## Голосові події

Створення користувацького голосу відбувається асинхронно. Ці неблокувальні події дають змогу
реагувати на кінцевий результат замість опитування
[кінцевої точки відомостей про клон](/api-reference/custom-voices#list-and-retrieve-clones).

`voice.ready` і `voice.failed` доставляються лише до кінцевої точки для всієї
організації з `events: []`. Їх не можна вибрати як явні фільтри подій.

### `voice.ready`

Надсилається, коли користувацький голос завершує обробку та його можна призначити
агенту.

```json
{
  "data": {
    "voice": {
      "created_at": "2026-07-30T14:12:08.317Z",
      "display_name": "Support voice",
      "failure_reason": "",
      "gender": "female",
      "id": "cv_2f6f90b0e9a34ee8b39be7d1",
      "language": "en",
      "name": "custom:cv_2f6f90b0e9a34ee8b39be7d1",
      "status": "ready",
      "updated_at": "2026-07-30T14:13:31.605Z"
    }
  },
  "event_id": "2d5f0a61-e9b5-4a3c-b684-29d7d9e4b214",
  "type": "voice.ready"
}
```

### `voice.failed`

Надсилається, коли обробка користувацького голосу завершується остаточною помилкою.

```json
{
  "data": {
    "reason": "audio sample could not be processed",
    "voice": {
      "created_at": "2026-07-30T14:12:08.317Z",
      "display_name": "Support voice",
      "failure_reason": "audio sample could not be processed",
      "gender": "female",
      "id": "cv_2f6f90b0e9a34ee8b39be7d1",
      "language": "en",
      "name": "custom:cv_2f6f90b0e9a34ee8b39be7d1",
      "status": "failed",
      "updated_at": "2026-07-30T14:13:31.605Z"
    }
  },
  "event_id": "3493e985-1a75-4f77-a10a-e74af440cd31",
  "type": "voice.failed"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `voice.id` | рядок | Публічний ідентифікатор користувацького голосу |
| `voice.name` | рядок | Значення голосу агента у форматі `custom:<public_id>` |
| `voice.display_name` | рядок | Назва голосу для організації |
| `voice.language` | рядок | Код єдиної мови клону |
| `voice.gender` | рядок | `male`, `female` або порожній рядок |
| `voice.status` | рядок | `ready` для `voice.ready`; `failed` для `voice.failed` |
| `voice.failure_reason` | рядок | Порожнє значення в разі успіху; відомості про помилку обробки в разі невдачі |
| `voice.created_at`, `voice.updated_at` | мітка часу | Мітки часу ISO 8601 |
| `reason` | рядок | Відомості про помилку; наявне лише для `voice.failed` |

---

## Події якості

### `call.graded`

Надсилається щоразу, коли для виклику завершується [запуск оцінювання ШІ](/api-reference/calls#ai-call-grading).
Неблокувальна подія.

```json
{
  "data": {
    "call_id": 987654321,
    "grade": {
      "call_outcome": "success",
      "created_at": "2026-04-20T18:25:11.002Z",
      "detected_issues": [],
      "graded_at": "2026-04-20T18:25:11.002Z",
      "grader_model": "heuristic-v1",
      "id": 5512,
      "score": 92,
      "status": "completed",
      "summary": "Caller asked about their policy and got a full answer…"
    },
    "report": null
  },
  "event_id": "7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
  "type": "call.graded"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив дзвінок, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив дзвінок, якщо його було призначено |
| `grade.id` | integer | Ідентифікатор оцінки |
| `grade.score` | integer \| null | 0–100 |
| `grade.call_outcome` | string | `success`, `failure`, `unknown` або `no_conversation` |
| `grade.summary` | string | Підсумок в одному абзаці |
| `grade.detected_issues` | array | Рядки з проблемами, виявленими оцінювачем |
| `grade.status` | string | Завжди `completed` — надсилаються лише завершені запуски |
| `grade.grader_model` | string | Який оцінювач створив результат (наприклад, `heuristic-v1`) |
| `grade.graded_at`, `grade.created_at` | timestamp | |
| `report` | object \| null | Орієнтований на клієнта [звіт про дзвінок](/api-reference/calls#call-report): мітка результату, прапорець потреби в увазі та причина, абонент, однорядковий підсумок, досвід абонента. Для ранньої евристичної оцінки це `null` або звіт `pending`, поля якого містять заповнювачі; подія повної оцінки містить завершений звіт |

<Note>
  Виклик можна оцінювати кілька разів — за швидким евристичним оцінюванням
  часто слідує повне оцінювання моделлю, щойно стає доступним запис, також
  можливе ручне повторне оцінювання. Кожен завершений запуск надсилає власну
  подію `call.graded`; вважайте найновіше значення `graded_at` авторитетним.
</Note>

### `call.data_extracted`

Надсилається щоразу, коли успішно завершується вилучення структурованих даних,
зокрема під час пізньої повторної спроби після `telephony.complete` / `web.complete`
або ручного повторного запуску через
[`POST /v1/calls/{call_id}/extract`](/api-reference/calls#run-data-extraction).
Неблокувальна подія.

У режимі блокувального вилучення даних подія завершення зазвичай очікує не
довше ніж 75-секундний ліміт вилучення. Якщо процес працівника вилучення даних
втрачено, продакшн-обробка фіналізації (кожні п’ять хвилин) надсилає подію
завершення, у якої минув `blocking_deadline_at`, перш ніж запускати іншу спробу
вилучення. Пізніший успіх надсилається окремо як ця подія.

<Warning>
  Вилучені значення є інтерпретацією розмови моделлю. Кожне значення, відмінне
  від null, містить цитату, роль мовця та індекс репліки, на яких воно
  ґрунтується, а також прапорець перевірки на рівні запуску. Перевіряйте
  результат перед ухваленням рішень щодо грошей, ідентичності або доступу.
</Warning>

```json
{
  "data": {
    "call_id": 987654321,
    "agent_id": 12,
    "agent_name": "Acme intake",
    "extracted_data": {
      "status": "completed",
      "fields": {
        "customer_name": "Alex Morgan",
        "appointment_date": "2026-04-23"
      },
      "evidence": {
        "customer_name": {
          "quote": "My name is Alex Morgan",
          "speaker_role": "caller",
          "turn_index": 4
        },
        "appointment_date": {
          "quote": "April 23 works for me",
          "speaker_role": "caller",
          "turn_index": 7
        }
      },
      "verification": "verified",
      "field_reasons": {},
      "schema_version": "92850758e231a3c95a..."
    },
    "extracted_at": "2026-04-20T18:25:11.002Z",
    "model": "<model id>",
    "summary": "Alex Morgan called to book a follow-up visit and confirmed Thursday, April 23."
  },
  "event_id": "4d79ef1d-c2b1-4ed6-85b8-8326bd2895ef",
  "type": "call.data_extracted"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |
| `summary` | string \| null | Завершений [підсумок виклику](/uk/webhooks/call-complete), коли в агента ввімкнено **Створювати підсумок виклику**, тому подія пізнього вилучення також надсилає підсумок, що не потрапив у вікно завершення; інакше `null`. Агенти з підсумком, але без полів вилучення, ніколи не надсилають цю подію: отримуйте пізній підсумок через `GET /v1/calls/{call_id}` |
| `extracted_data.status` | string | Для цієї події завжди `completed` |
| `extracted_data.fields` | object | Значення, ключами яких є налаштовані ключі полів вилучення; недоступні значення мають `null` |
| `extracted_data.evidence` | object | Докази з ключами за полем вилучення. Значення, відмінне від null, містить точну структурно перевірену цитату (не більше 1 000 символів), `speaker_role` (`caller` або `agent`) та `turn_index`; довші цитати, повернуті моделлю, відхиляються замість скорочення, а докази мають `null`, коли відповідне поле має `null` |
| `extracted_data.verification` | string | `verified` лише тоді, коли незалежна перевірка доказів повернула рівно один дійсний висновок для кожного поля-кандидата. `unavailable` означає, що перевірка не виконалася, перевищила час очікування, не мала достатнього ліміту або повернула некоректні чи часткові дані. Повністю недоступна перевірка зберігає структурно обґрунтовані значення для перегляду клієнтом. Для часткових даних застосовуються дійсні висновки, а кожен кандидат без рівно одного дійсного висновку отримує null |
| `extracted_data.field_reasons` | object | Причини з ключами за полями, яким структурне обґрунтування або незалежний перевіряльник встановив null |
| `extracted_data.schema_version` | string | Хеш точної схеми полів, використаної для цього вилучення |
| `extracted_at` | timestamp | Час завершення у форматі ISO 8601 |
| `model` | string | Модель, використана для вилучення |

### `campaign.completed`

Надсилається один раз, коли кампанія переходить зі стану `running` до `completed`,
незалежно від того, чи завершився її розклад, чи всі контакти досягли кінцевих
станів. Повторні спроби виконавця не надсилають іншу подію. Ця подія життєвого
циклу на рівні організації надсилається лише до кінцевих точок з областю
організації, а не до кінцевих точок з областю агента. Неблокувальна подія.

```json
{
  "data": {
    "campaign_id": "3f6b2c9e-2a0d-4c63-b6d6-a708dc98f403",
    "name": "May win-back",
    "agent_id": 12,
    "status": "completed",
    "started_at": "2026-04-20T17:00:00Z",
    "completed_at": "2026-04-20T18:25:11Z",
    "counts": {
      "contacts_total": 150,
      "completed": 121,
      "failed": 11,
      "no_answer": 18,
      "remaining": 0
    }
  },
  "event_id": "8d8f52ce-6b46-423f-9dde-cea0b91ec135",
  "type": "campaign.completed"
}
```

Чотири лічильники результатів є взаємовиключними та в сумі дорівнюють
`contacts_total`: `completed` містить успішні контакти; `no_answer` містить
контакти з остаточним станом невдачі або вичерпаними спробами, для яких
останнім результатом була відсутність відповіді; `failed` містить усі інші
контакти з остаточним станом невдачі або вичерпаними спробами; а `remaining`
містить контакти, що очікують, заплановані або для яких зараз здійснюється
виклик. Контакт, що очікує повторної спроби, має стан `remaining`, навіть якщо
в його останній спробі не було відповіді. Виклики в процесі виконання
узгоджуються перед одноразовим знімком завершення. `started_at` — це
налаштований початок кампанії або час створення кампанії, якщо початок не було
налаштовано.

### `issue.reported`

Надсилається, коли створюється [звіт про проблему](/api-reference/issue-reports) —
або поданий користувачем із панелі керування (`source: "user"`), або автоматично
створений оцінюванням виклику (`source: "system"`). Неблокувальна подія.

```json
{
  "data": {
    "call_id": 987654321,
    "issue_report": {
      "created_at": "2026-04-20T18:25:11.002Z",
      "description": "Five-second silence before responding to the main question.",
      "id": 4321,
      "severity": "warning",
      "source": "system",
      "status": "open",
      "title": "Agent paused too long"
    }
  },
  "event_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
  "type": "issue.reported"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |
| `issue_report.severity` | string | `critical`, `warning` або `info` |
| `issue_report.status` | string | `open` або `resolved` |
| `issue_report.source` | string | `user` (подано з панелі керування) або `system` (створено оцінюванням) |

<Note>
  Повторне оцінювання виклику перебудовує створені системою звіти про проблеми,
  що повторно надсилає `issue.reported` для відтворених звітів. Виконуйте
  дедуплікацію за `call_id` + `title`, якщо вам потрібне лише одне сповіщення
  для кожної базової проблеми.
</Note>

### `issue.escalated`

Надсилається, коли шаблон проблеми надсилається до ThunderPhone для перевірки
персоналом: після **Повідомити ThunderPhone** або коли функція «Виправити за
допомогою ШІ» не може підтвердити виправлення на стороні клієнта й автоматично
маршрутизує проблему. Цю подію отримують лише кінцеві точки рівня організації.

```json
{
  "data": {
    "automatic": false,
    "cluster_id": "7ac2844c-2df0-4fa8-a560-7378da649e19",
    "escalation_id": "ec99f52b-c8c0-41dd-a4f2-dd8a07b10894",
    "status": "open"
  },
  "event_id": "d8f8f420-7a42-45ba-bcf1-b747f9bbecda",
  "type": "issue.escalated"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `automatic` | boolean | `true` для автоматичної ескалації; `false` для ручної ескалації |
| `cluster_id` | UUID | Ескальований шаблон проблеми |
| `escalation_id` | UUID | Запис ескалації |
| `status` | string | `open` під час надсилання події |

Це сповіщення, а не пакет доказів. Використовуйте `cluster_id`, щоб пов’язати
його з шаблоном проблеми. Дивіться [Повідомити ThunderPhone](/uk/guides/issues).

---

## Події тестових викликів

### `test-call.completed`

Надсилається, коли
[запуск тестового виклику](/api-reference/test-calls#test-call-run-object)
досягає кінцевого статусу — `completed` або `failed`, включно із запусками,
які завершилися невдачею під час запуску й не створили виклик. Не блокує виконання. Корисно
для підключення пакетних запусків CI до ваших систем чату та сповіщень.

```json
{
  "data": {
    "test_call_run": {
      "call_id": 987654321,
      "completed_at": "2026-04-20T18:25:04.822Z",
      "error_message": "",
      "id": 7110,
      "status": "completed",
      "target_id": 12,
      "target_type": "agent"
    }
  },
  "event_id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
  "type": "test-call.completed"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `agent_id` | integer \| null | Агент, який обробив виклик, якщо його було призначено |
| `agent_name` | string \| null | Агент, який обробив виклик, якщо його було призначено |
| `test_call_run.target_type` | string | `agent` або `phone_number` |
| `test_call_run.target_id` | integer | Ідентифікатор агента або номера телефону, на який було націлено запуск, відповідно до `target_type` |
| `test_call_run.status` | string | `completed` або `failed` |
| `test_call_run.call_id` | integer \| null | `null`, якщо запуск завершився невдачею до здійснення виклику |
| `test_call_run.error_message` | string | Порожнє значення в разі успіху |

---

## Події сповіщень

### `alert.triggered`

Надсилається, коли [правило сповіщення](/uk/guides/alerts) з увімкненим каналом
**Надсилати до вебхуків розробника** перетинає свій поріг.
Не блокує виконання. Правило спрацьовує один раз, а потім дотримується свого періоду
очікування, тому тривале порушення створює одну подію на кожне вікно періоду очікування.

```json
{
  "data": {
    "comparator": "lt",
    "event_id": "b8e6a1d4-2c3f-4a5b-9c8d-7e6f5a4b3c2d",
    "fired_at": "2026-04-20T18:00:00+00:00",
    "metric": "success_rate",
    "metric_value": 71.4,
    "rule_id": "d2c3b4a5-6f7e-4d8c-9b0a-1c2d3e4f5a6b",
    "rule_name": "Success rate below 80%",
    "threshold": 80.0,
    "window_hours": 24
  },
  "event_id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
  "type": "alert.triggered"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `event_id` (у `data`) | UUID | Ідентифікатор **спрацювання** сповіщення — відрізняється від `event_id` доставки в оболонці |
| `rule_id`, `rule_name` | UUID, string | Правило, яке спрацювало |
| `metric` | string | `success_rate`, `failure_rate`, `avg_score`, `call_volume` або `suite_regression` |
| `comparator` | string | `lt`, `lte`, `gt` або `gte` |
| `metric_value` | number | Значення метрики за вікно, коли правило спрацювало |
| `threshold` | number | Налаштований поріг |
| `window_hours` | integer | Ковзне вікно оцінювання |
| `fired_at` | timestamp | |

Дивіться [посібник зі сповіщень](/uk/guides/alerts), щоб створювати правила, налаштовувати метрики,
періоди очікування та канали електронної пошти / Slack.

---

## Події міграції

### `migration.call.complete`

Надсилається, коли завершується дзвінок, здійснений через
[`POST /v1/migrations/{id}/calls`](/api-reference/migration-calls),
незалежно від платформи, через яку його було здійснено. Не блокує виконання. Надходить протягом приблизно 5 хвилин
після завершення дзвінка. `data` містить усі поля з
[`telephony.complete`](/uk/webhooks/call-complete) і блок `migration`. Дзвінок, здійснений ThunderPhone, також надсилає `telephony.complete` як зазвичай, з тим самим
`call_id`. Дзвінок на іншій платформі, який не завершився протягом 2
годин або для якого міграція раніше завершилася чи втратила ключ, надсилається зі
`status: "unknown"` і без транскрипту.

```json
{
  "data": {
    "agent_id": 42,
    "agent_name": "Front desk",
    "billable_minutes": null,
    "billing_total_cents": null,
    "call_id": null,
    "direction": "outbound",
    "duration_seconds": 94,
    "end_reason": "user_hangup",
    "end_time": "2026-10-06T17:01:34+00:00",
    "extracted_data": null,
    "from_number": "+15551234567",
    "migration": {
      "arm": "vendor",
      "id": "5f0c2a9e-7b1d-4c3e-8a6f-2d9e1b4c7a30",
      "metadata": {
        "lead_id": "8812"
      },
      "routing_id": "9b2f8c1e-4d3a-4f6b-8e2d-1a7c5b9e0f34",
      "vendor": "retell",
      "vendor_call_id": "call_6a1f0e",
      "vendor_cost_usd": "0.1240"
    },
    "product": "",
    "recording_mode": "vendor",
    "recording_url": "https://…",
    "start_time": "2026-10-06T17:00:00+00:00",
    "status": "completed",
    "summary": "The callee booked a table for two on Thursday.",
    "thunderphone_retained_call_content": true,
    "to_number": "+14155552671",
    "transcripts": [
      {
        "content": "Hi Ada, this is Rosa's calling about your booking.",
        "role": "agent"
      },
      {
        "content": "Yes, Thursday works.",
        "role": "user"
      }
    ],
    "transfer_number": null,
    "unresolved_variables": [],
    "variables": {
      "first_name": "Ada"
    },
    "voice": ""
  },
  "event_id": "7c1e2f3a-4b5c-4d6e-8f7a-9b0c1d2e3f4a",
  "type": "migration.call.complete"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `migration.id` | UUID | Міграція |
| `migration.routing_id` | UUID | Маршрутизований дзвінок, повернений під час його здійснення |
| `migration.arm` | string | `ours` (дзвінок здійснив ThunderPhone) або `vendor` (дзвінок здійснила інша платформа) |
| `migration.vendor` | string | `retell`, `vapi`, `elevenlabs` або `bland` |
| `migration.vendor_call_id` | string \| null | Ідентифікатор дзвінка на іншій платформі; `null` для `ours` |
| `migration.metadata` | object | `metadata`, які ви надіслали під час здійснення дзвінка |
| `migration.vendor_cost_usd` | string \| null | Вартість дзвінка, про яку повідомила інша платформа, якщо вона її надала |
| `call_id` | integer \| null | Ідентифікатор дзвінка ThunderPhone; `null` для `vendor` |
| `status` | string | Для `vendor`: `completed`, коли абонент відповів, `failed`, коли він не відповів, `unknown`, як описано вище. Для `ours`: як у `telephony.complete` |

Для дзвінка `vendor` ThunderPhone не має даних про виставлення рахунків або вилучення даних:
`billable_minutes`, `billing_total_cents` і `extracted_data` мають значення `null`,
`product` і `voice` порожні, `recording_mode` має значення `vendor`, а
`recording_url` містить посилання іншої платформи, якщо вона його надала.

### `migration.rollback`

Надсилається, коли поступове перемикання міграції самостійно повертає всі дзвінки на іншу
платформу: 3 дзвінки не змогли підключитися до ThunderPhone протягом 15
хвилин, 2 дзвінки, надіслані до ThunderPhone, завершилися до відповіді агента, або
показник результативності завдань ThunderPhone впав нижче показника іншої
платформи більше ніж на налаштовану різницю. Не блокує виконання, один раз на кожне скасування. Після цього частка
ThunderPhone становить 0%, а міграцію призупинено, доки хтось не відновить її на вкладці «Міграція»
агента. Корисне навантаження не містить номерів телефонів, транскриптів або
ідентифікаторів дзвінків.

```json
{
  "data": {
    "agent_id": 42,
    "agent_name": "Front desk",
    "dropped": 0,
    "migration_id": "5f0c2a9e-7b1d-4c3e-8a6f-2d9e1b4c7a30",
    "ours": {
      "graded": 20,
      "success_rate": 0.8
    },
    "ours_failed": 3,
    "ours_percent": 0,
    "previous_percent": 25,
    "reason": "ours_failed_burst",
    "rolled_back_at": "2026-10-10T12:05:00+00:00",
    "step": 1,
    "theirs": {
      "graded": 20,
      "success_rate": 0.8
    },
    "vendor": "retell"
  },
  "event_id": "3d1f6b2a-8c4e-5a7b-9d0e-2f1a3b4c5d6e",
  "type": "migration.rollback"
}
```

| Поле | Тип | Опис |
|-------|------|-------------|
| `migration_id` | UUID | Міграція |
| `vendor` | рядок | `retell`, `vapi`, `elevenlabs` або `bland` |
| `reason` | рядок | `ours_failed_burst` (3 невдалі підключення за 15 хвилин), `dropped_calls` (2 дзвінки завершилися до відповіді агента протягом 30 хвилин) або `rate_gap` (різниця в показниках результативності завдань щонайменше для `rollback_min_calls` оцінених дзвінків з кожного боку) |
| `previous_percent` | ціле число | Частка дзвінків ThunderPhone до скасування |
| `ours_percent` | ціле число | Завжди `0` |
| `step` | ціле число \| null | Крок розкладу, на якому вона перебувала (відлік від 0) |
| `ours` / `theirs` | об’єкт \| null | Оцінені дзвінки на поточному кроці та їхній показник успішності; `theirs` може охоплювати останні 30 днів, якщо на кроці надто мало дзвінків. `null`, якщо їх не було |
| `ours_failed` | ціле число | Невдалі підключення, підраховані за останні 15 хвилин |
| `dropped` | ціле число | Дзвінки, зараховані як перервані за останні 30 хвилин |
| `rolled_back_at` | часова позначка | |

---

## Пов’язані матеріали

<CardGroup cols={2}>
  <Card title="telephony.incoming / web.incoming" icon="phone" href="/uk/webhooks/call-incoming">
    Блокувальне корисне навантаження вхідного виклику, на яке потрібно відповісти.
  </Card>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/uk/webhooks/call-complete">
    Транскрипт і метрики після виклику.
  </Card>
  <Card title="Кінцеві точки вебхуків" icon="bolt" href="/uk/webhooks/endpoints">
    Підпишіть URL на підмножину цих подій.
  </Card>
  <Card title="Інструменти функцій" icon="screwdriver-wrench" href="/uk/tools/overview">
    Як генеруються події `telephony.tool` / `web.tool`.
  </Card>
</CardGroup>
