Покрокова інструкція
Markdown статтіПовідомити про помилку

Як налаштувати UniTalk

Підключіть UniTalk до ConnectiveOne через вбудований preset UniTalk: завершені дзвінки з'являтимуться в архіві дзвінків із записом, призначеним оператором і полями в картці клієнта.

Ця інструкція — повний гайд для імплементації: preset, webhook, два способи призначення оператора (з готовими JSON), поля клієнта, smoke-тест і типові проблеми.

Передумови

  • Доступ адміністратора до кабінету UniTalk
  • Доступ до налаштувань бота в ConnectiveOne (Налаштування → Боти → Телефонія)
  • Email операторів у ConnectiveOne збігаються з email у UniTalk (для автопризначення)
  • Для шляху A (рекомендовано): таблиця SIP-лінія (line у UniTalk) ↔ email оператора
  • Для шляху B (опційно): API-ключ UniTalk (Інтеграція → API)

Коли знадобиться

  • UniTalk — провайдер телефонії
  • Потрібно швидко підключити інтеграцію без ручного маппінгу полів webhook
  • Завершені дзвінки мають з'являтися в Операторській панелі з записом і оператором

Два способи призначити оператора

Шлях A — operator_mapping Шлях B — action_telephony_staff_enrich
Суть Статична таблиця SIP → email у Advanced Config Запит до UniTalk API /users/list, матч по полю line
Зовнішні API Ні Так (кеш обовʼязковий через ліміти UniTalk)
Коли обирати Відомий стабільний список ліній (типовий кейс First / більшості клієнтів) Лінії часто змінюються, таблицю не хочете вести вручну
Що вказати в каналі Блок operator_mapping у JSON API Key + Action збагачення webhook = action_telephony_staff_enrich

Якщо спрацював operator_mapping, ConnectiveOne не викликає enrich — зайвих запитів до API немає.

action_telephony_staff_enrichуніверсальний internal action (будь-який HTTP-список співробітників через json_config). Нижче — готова конфігурація саме під UniTalk.


Крок 1: Відкрити налаштування каналу

  1. НалаштуванняБоти
  2. Оберіть бот
  3. Вкладка Телефонія
  4. Створіть новий канал або відкрийте існуючий

Заповніть мінімум:

Поле каналу Значення
Назва Наприклад UniTalk
Активний Увімкнено
Код країни за замовчуванням Наприклад UA / 380 (як у вашому інстансі)

Після першого збереження зʼявляться Webhook URL і токен.

Крок 2: Застосувати preset UniTalk

  1. У блоці Розширена конфігурація (JSON) оберіть у списку провайдера UniTalk
  2. Натисніть Застосувати пресет
  3. Натисніть Зберегти і скопіюйте Webhook URL?token=...)

Preset додає:

  • event_detection — лише подія CALL_END
  • field_mapping / status_mapping / direction_mapping
  • client_field_mapping — UTM, джерело, коментар → картка клієнта
  • записи з call.link

Повний JSON preset (без operator_mapping) також є в репозиторії: apps/engine/modules/extra/telephony/presets/unitalk.json.

Крок 3: Webhook у кабінеті UniTalk

  1. Кабінет UniTalk → Обробка подій
  2. Додайте обробник «Надіслати вебхук»
  3. Привʼяжіть лише до події CALL_END (не надсилайте CALL_NEW тощо)
Поле в UniTalk Значення
Метод POST
URL Повний Webhook URL з ConnectiveOne, наприклад: https://<ваш-домен>/kw/telephony/webhook/<id_каналу>?token=<webhook_token>
Тіло Стандартний JSON

Токен тільки в URL (?token=...). Шлях /kw/telephony/webhook/... не змінюйте.

Приклад тіла CALL_END (вхідний)

{
  "event": "CALL_END",
  "call": {
    "id": "sample-call-id",
    "from": "380501234567",
    "to": "9578",
    "direction": "in",
    "state": "ANSWER",
    "secondsFullTime": 120,
    "secondsTalk": 90,
    "date": "2026-09-02T12:00:00.000Z",
    "link": "https://example.test/recording.mp3",
    "utmSource": "google",
    "utmCampaign": "brand",
    "source": "ads",
    "comment": "Коментар до дзвінка"
  }
}
Поле UniTalk Після preset у ConnectiveOne
event Має бути CALL_END, інакше відповідь 200 ignored
call.id ID дзвінка (ідемпотентність — повтор не створить дубль)
call.from / call.to Номер клієнта або SIP оператора (залежить від direction)
call.direction in / out
call.state ANSWER → прийнятий; NOANSWER, BUSY, … → пропущений
call.link Запис розмови
call.utmSource, utmCampaign, source, comment Картка клієнта (client_field_mapping)

Напрямок і SIP оператора:

Напрямок Номер клієнта SIP-лінія оператора (ключ у operator_mapping / lookup enrich)
in (вхідний) call.from call.to
out (вихідний) call.to call.from

У формі каналу ConnectiveOne: формат webhook = JSON.


Крок 4A: Призначення оператора через operator_mapping (рекомендовано)

Після Застосувати пресет додайте в той самий JSON блок operator_mapping (на одному рівні з event_detection, field_mapping, …) і натисніть Валідувати JSON / Зберегти.

Приклад фрагмента

"operator_mapping": {
  "source": {
    "in": "callee_number",
    "out": "caller_number"
  },
  "map": {
    "9578": "[email protected]",
    "201": "[email protected]"
  }
}

Повний приклад Advanced Config (preset + mapping)

Скопіюйте, підставте свої SIP → email, збережіть:

{
  "event_detection": {
    "mode": "event_field",
    "event_field": "event",
    "call_ended_values": ["CALL_END"]
  },
  "field_mapping": {
    "call_id": "call.id",
    "caller_number": "call.from",
    "callee_number": "call.to",
    "status": "call.state",
    "duration": "call.secondsFullTime",
    "talk_duration": "call.secondsTalk",
    "recording_url": "call.link",
    "direction": "call.direction",
    "date": "call.date",
    "utm_source": "call.utmSource",
    "utm_campaign": "call.utmCampaign",
    "call_source": "call.source"
  },
  "status_mapping": {
    "ANSWER": "answered",
    "NOANSWER": "missed",
    "BUSY": "missed",
    "CANCEL": "missed",
    "AUTOCANCEL": "missed",
    "UNREACHABLE": "missed",
    "VOICE_MAIL": "missed",
    "FAIL": "failed",
    "BLOCKED": "failed",
    "AUDIO_ERR": "failed"
  },
  "direction_mapping": {
    "in": "in",
    "out": "out",
    "inbound": "in",
    "outbound": "out"
  },
  "recordings": {
    "enabled": true,
    "download": false
  },
  "transcription": {
    "enabled": false,
    "source": "provider"
  },
  "client_field_mapping": {
    "utm_source": "call.utmSource",
    "utm_campaign": "call.utmCampaign",
    "call_source": "call.source",
    "last_call_comment": "call.comment"
  },
  "operator_mapping": {
    "source": {
      "in": "callee_number",
      "out": "caller_number"
    },
    "map": {
      "9578": "[email protected]",
      "201": "[email protected]"
    }
  }
}

Правила:

  1. Ключі в mapсирі SIP-рядки як у UniTalk ("9578"), до нормалізації E.164 (не +3809578).
  2. Email у ConnectiveOne = email оператора (активний користувач Операторської панелі).
  3. У UniTalk у кожного оператора заповнена внутрішня лінія (line).
  4. Поле Action збагачення webhook можна залишити порожнім.

Крок 4B: Динамічне призначення через action_telephony_staff_enrich (опційно)

Використовуйте, якщо не ведете operator_mapping (або як запасний шлях, коли лінії в таблиці немає).

4B.1 Поля каналу

Поле Значення
API Key API-ключ UniTalk (Інтеграція → API)
API Base URL (якщо є в формі) https://api.unitalk.cloud/api
Action збагачення webhook action_telephony_staff_enrich

Ключ — секрет. Не публікуйте в чатах / тікетах.

4B.2 Параметри action (json_config)

Action уже є в продукті (internal). Якщо на інстансі використовуєте Action Jail-обгортку — ті самі параметри в JSON config action.

Готовий приклад під UniTalk:

{
  "api_url": "https://api.unitalk.cloud/api/users/list",
  "http_method": "POST",
  "auth_header_name": "Authorization",
  "auth_scheme": "raw",
  "request_body": {},
  "response_items_path": "",
  "match_field": "line",
  "lookup_source": {
    "in": "callee_number",
    "out": "caller_number"
  },
  "email_field": "email",
  "name_fields": ["firstName", "lastName"],
  "cache_ttl_seconds": 300,
  "timeout_ms": 8000
}
Параметр Навіщо
match_field: line Внутрішня SIP-лінія АТС у відповіді /users/list (не плутати з phone — мобільний, часто null)
lookup_source Звідки брати SIP з нормалізованого дзвінка: in → callee_number, out → caller_number
cache_ttl_seconds Кеш списку співробітників (ліміти UniTalk: ~15 req/s)
api_key Можна в json_config або лише в полі каналу API Key (канал має пріоритет як джерело секрету, якщо в params немає ключа)

Якщо відповідь API — масив у корені, response_items_path залиште порожнім "". Якщо обгортка на кшталт { "data": [ … ] } — вкажіть "data".

4B.3 Що має повернути UniTalk /users/list (фрагмент)

[
  {
    "id": 1,
    "email": "[email protected]",
    "firstName": "Іван",
    "lastName": "Петренко",
    "line": "9578",
    "phone": null,
    "role": "OPERATOR"
  }
]

ConnectiveOne шукає запис з line = SIP з дзвінка і пише manager_email / manager_name у збагачення → призначення за email.

Деталі загального механізму enrich: Налаштувати збагачення webhook.
Технічний шаблон для впровадників: docs/developer/engine/modules/telephony/action_telephony_staff_enrich.template.md.


Крок 5: Поля картки клієнта

Preset уже містить client_field_mapping:

Ключ у extra_data Шлях у webhook
utm_source call.utmSource
utm_campaign call.utmCampaign
call_source call.source
last_call_comment call.comment

Щоб поля відображались у картці клієнта, додайте відповідні кастомні поля в Налаштування інстансу (схема extra_data). Сам merge у клієнта робить Telephony без Action Jail.


Крок 6: Збереження та перевірка (smoke)

  1. Зберегти канал (активний).
  2. У формі каналу — Тест webhook або curl нижче.
  3. Зробіть тестовий вхідний і вихідний дзвінок у UniTalk.
  4. Операторська панель → Закриті звернення: діалог telephony, запис (якщо є call.link), оператор.

Приклад curl (локальний / stage smoke)

Підставте URL каналу і токен. Тіло — як у кроці 3; для шляху A змініть "to" / email у operator_mapping під реальну лінію.

curl -X POST 'https://<ваш-домен>/kw/telephony/webhook/<channel_id>?token=<webhook_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "event": "CALL_END",
    "call": {
      "id": "smoke-unitalk-001",
      "from": "380501234567",
      "to": "9578",
      "direction": "in",
      "state": "ANSWER",
      "secondsFullTime": 60,
      "secondsTalk": 45,
      "date": "2026-09-02T12:00:00.000Z",
      "link": "https://example.test/recording.mp3",
      "utmSource": "google",
      "utmCampaign": "brand",
      "source": "ads",
      "comment": "Smoke test"
    }
  }'

Очікувано: HTTP 200, у тілі є dialogue_id.
Повтор з тим самим call.id → 200, «already processed», без дубля діалогу.

Подія не CALL_END (наприклад "event": "CALL_NEW") → 200 ignored, діалог не створюється.

Чекліст приймання

# Перевірка Очікування
1 CALL_END Діалог створено, канал telephony, завершений
2 Не-CALL_END 200 ignored, без діалогу
3 Є call.link Запис доступний у діалозі
4 Вхідний / вихідний Клієнт за правильним номером
5 SIP in і out Оператор призначений (mapping або enrich)
6 UTM / comment Значення в картці клієнта (якщо поля в Instance Settings)
7 Той самий call.id двічі Без дубля
8 Шлях B Кеш / без rate-limit блокування; або шлях A без enrich

Типові проблеми

Симптом Що перевірити
200 ignored на кожному webhook У тілі є "event": "CALL_END"; застосовано preset UniTalk (event_detection)
Діалог є, оператора немає Email у map / UniTalk збігається з користувачем C1; SIP як "9578", не E.164; для out — лінія в call.from
Enrich не викликається Заповнений operator_mapping з матчем — це очікувано (skip enrich)
Enrich error / немає email match_field = line; у /users/list у оператора заповнений line; API Key на каналі
Дубль діалогів Різні call.id від UniTalk; ідемпотентність лише за одним id
UTM не видно в UI Merge в extra_data є — додайте відображення кастомних полів у Instance Settings
403 / unauthorized webhook Токен у URL = токен каналу

Що включає preset UniTalk

  • Детекція лише CALL_END
  • Маппінг полів, статусів, напрямку
  • Записи з call.link
  • client_field_mapping (UTM, джерело, коментар)

operator_mapping і webhook enrich не входять у кнопку preset — додаються вручну (кроки 4A / 4B).

Обмеження

  • Лише завершені дзвінки (CALL_END), без realtime під час розмови
  • Click-to-call з ConnectiveOne — поза цим обсягом
  • Транскрипт / аналітика UniTalk — окремий scope

Повʼязана документація

Працюєте з власним ШІ-агентом?Встановіть відкритий skill, щоб ваш ШІ-агент працював з актуальною офіційною документацією ConnectiveOne.Отримати skillПотрібна підтримка?Не знайшли відповідь або потрібна допомога команди ConnectiveOne? Створіть запит у Client Portal.Створити запит