> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hubtalk.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Вебхуки

> Руководство по вебхукам в HubTalk AI v4.

# Вебхуки

Вебхуки позволяют HubTalk AI v4 автоматически отправлять данные о звонках в ваши системы после завершения разговора. Используйте их для дашбордов, CRM-обновлений и автоматизации процессов.

## Что отправляют вебхуки

Вебхук передаёт JSON-payload с информацией о звонке, включая:

* статус и длительность звонка
* данные агента
* транскрипт и резюме
* пользовательские аналитические переменные

## Как включить вебхуки

Укажите URL вебхука в редакторе агента в разделе вебхука. Система будет отправлять данные после каждого завершённого разговора или попытки звонка.

<img src="https://mintcdn.com/hubtalk/yYJS_d_pzapQzHCp/images/v4_webhooks_form.png?fit=max&auto=format&n=yYJS_d_pzapQzHCp&q=85&s=6c42b09f4cf18d74608d812b5aeae9b5" alt="Форма «Новый webhook»: адрес, события, имя env-переменной с секретом подписи и таймаут ответа" width="720" height="522" data-path="images/v4_webhooks_form.png" />

### Один адрес принадлежит одному агенту

У каждого вебхука указан агент, и это должен быть живой агент вашей организации. Адреса на всю организацию не существует: подписка без имени агента отклоняется с кодом `webhooks.agent_required`, а неизвестный или архивный — с кодом `webhooks.agent_not_found`.

<Warning>
  **Подписки на всю организацию не бывает.** Если интеграции нужны события по нескольким агентам, зарегистрируйте адрес отдельно у каждого. Строка с пустым именем агента, если такая лежит в базе, инертна: её не удаляют, но она ничего не получает.
</Warning>

Чтобы получать события по нескольким агентам, добавьте адрес каждому из них. Один и тот же URL переиспользовать можно: в payload есть `agent_id`, поэтому один приёмник разберёт все.

## Настройки вебхука

Вебхуки агента живут в секции **«🪝 Уведомления после звонка»** панели настроек в конструкторе. Кнопка **«Добавить webhook»** открывает форму с такими полями:

* **Адрес (URL)** — HTTPS-адрес, который принимает уведомления. `http://` доступен только организации — владельцу платформы.
* **События** — что отправлять:
  * **«Звонок завершён (`call_ended`)»** — после завершения звонка;
  * **«Аналитика готова (`call_analyzed`)»** — когда готова пост-колл аналитика.
* **Секрет подписи — имя env-переменной** — хранится только ссылка на переменную: значение берётся из окружения и не попадает в базу и логи.
* **Таймаут ответа (сек)** — максимальное ожидание ответа вашего сервиса; `0` означает умолчание пайплайна.
* **Включён** — отправку можно приостановить, не удаляя адрес.
* **Слать события тест-сессий** — по умолчанию выключено, то есть тесты из кабинета вебхук не дёргают.

Отдельного поля с выбором агента в форме нет: вебхук принадлежит тому агенту, в настройках которого вы его завели. У сохранённого адреса в списке есть кнопка **«Тест»** — она отправляет пробное уведомление, не дожидаясь настоящего звонка.

## Примеры использования

* отправка результатов звонка в CRM
* обновление статуса заявки в службе поддержки
* запуск задачи последующего контакта, если клиент согласился на звонок
* сохранение резюме звонка для контроля качества

## Пример payload

Ниже пример webhook-сообщения `call_ended`, которое HubTalk AI v4 может отправить на ваш endpoint:

```json theme={null}
{
  "event": "call_ended",
  "event_id": "evt-4f0c22b17a9d4e3c8b6a5f019e2d7c31",
  "timestamp": 1753344187.51,
  "call_id": "call-out-3f9a1b2c4d",
  "agent_id": "support-agent",
  "flow_version": "9f2c41a87d3b",
  "flow_version_id": 42,
  "metadata": { "crm_lead_id": "L-98421" },
  "call": {
    "channel": "phone",
    "mode": "live",
    "direction": "outbound",
    "from_number": "15550100",
    "to_number": "15551234567",
    "trunk_id": "trunk-ab12cd34ef",
    "started_at": 1753344000.123,
    "ended_at": 1753344187.4,
    "duration": 187.3,
    "status": "ended",
    "outcome": "completed",
    "call_status": "completed",
    "status_reason": "agent_hangup",
    "error_code": null,
    "message_left": false,
    "transcript": [
      { "role": "assistant", "text": "Hi Alex, this is the clinic calling…" },
      { "role": "user", "text": "Yes, that works for me." }
    ],
    "dynamic_variables": { "customer_name": "Alex", "confirmed": "yes" },
    "latency": { "total": { "avg": 812.4, "max": 1420.0 } },
    "recording_url": "",
    "recording": {
      "id": "rec-7c1d…",
      "status": "pending",
      "recording_url": "",
      "channels": "",
      "format": "mp3",
      "duration": null,
      "size": null,
      "expires_at": null
    }
  }
}
```

## Второе событие: готовность аналитики

HubTalk AI v4 может отправить второй вебхук, когда пост-колл аналитика завершит обработку. Событие `call_analyzed` содержит полный объект звонка вместе с результатами анализа, поэтому подписчику достаточно одного этого события, чтобы получить полную картину — подписка на `call_ended` необязательна.

```json theme={null}
{
  "event": "call_analyzed",
  "event_id": "evt-9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6",
  "timestamp": 1752750007.42,
  "call_id": "c1e5a2b4-7f3d-4e8a-9b06-2d51c0ffee11",
  "agent_id": "demo_bilingual",
  "flow_version": "3a1f9c2b7d4e",
  "flow_version_id": 7,
  "call": {
    "channel": "phone",
    "mode": "live",
    "direction": "inbound",
    "started_at": 1752749875.4,
    "ended_at": 1752749998.9,
    "duration": 123.5,
    "status": "ended",
    "call_status": "completed",
    "status_reason": "agent_hangup",
    "transcript": [{ "role": "assistant", "text": "Здравствуйте! Чем могу помочь?" }],
    "dynamic_variables": { "client_name": "Айгерим", "slot": "10:00" }
  },
  "analysis_status": "done",
  "call_analysis": {
    "summary": "Клиент записался на приём на завтра на 10:00; агент подтвердил запись.",
    "sentiment": {
      "label": "positive",
      "score": 0.6,
      "caller_label": "neutral",
      "trajectory": ["neutral", "positive"]
    },
    "custom_fields": { "appointment_date": "2026-07-18", "service": "приём" },
    "call_successful": true
  },
  "analytics_tier": "mass",
  "analytics_model_used": "google/gemma-4-26B-A4B-it",
  "analytics_language": "ru"
}
```

Оба события несут поле **`error_code`** — числовой код отказа, присвоенный оператором связи (например `486` при `status_reason` = `busy`). Он равен `null`, если оператор кода не отдал. Трактовки кодов у операторов различаются — не строите на них жёсткую логику без сверки со своим оператором. Учтите также, что `busy` и `user_declined` — разные причины: занято и отбой абонента различаются.

Если анализ был пропущен или завершился ошибкой, `call_analysis` пуст, а в payload добавляется поле `reason`, объясняющее причину, например `voicemail` или `no_speech`. Если у звонка есть запись, `call_analyzed` также содержит поле верхнего уровня `recording_url` и объект `recording` — уже с готовой ссылкой на запись. `call_ended` несёт тот же блок записи, но на этот момент она обычно ещё обрабатывается.

## На недозвоне переменные тоже приходят

Звонок, который не состоялся — недозвон, занято, сбой, автоответчик, — всё равно даёт вебхук, и в этом вебхуке есть `dynamic_variables`: значения, которые вы передали для контакта при постановке звонка в очередь. В разговоре ничего не собрано, потому что разговора не было, но входные данные звонка на месте.

<Warning>
  **Не используйте пустой `dynamic_variables` как признак недозвона.** Переменные приходят и на состоявшемся звонке, и на недозвоне, поэтому пустой словарь об исходе ничего не говорит. Ветвитесь по `call_status` и `status_reason` — именно эти поля говорят об исходе.
</Warning>

Три поверхности показывают одно и то же: переменная звонка внутри пост-колл функций, словарь в вебхуке завершения и `GET /v1/calls/{call_id}` в [Web API](/ru/v4/web-api) — по одному звонку данные совпадают.

## Как проверить

После настройки выполните тестовый звонок или используйте инструмент инспекции вебхуков, чтобы убедиться, что payload приходит на ваш endpoint и формат данных соответствует ожиданиям.

## Не усложняйте сначала

Начните с одного URL вебхука и небольшого набора полей. Когда интеграция работает, добавьте больше аналитики и переменных.
