API BotLeadGen — запуск звонков и вебхуки для интеграций
[ Для разработчиков ]

API и вебхуки
BotLeadGen.

Два интеграционных контура: входящий вебхук — запускает звонок робота HTTP-запросом из любой вашей системы (CRM, сайт, 1С, самописный бэкенд); исходящий вебхук — отдаёт результат разговора на ваш URL прямо из сценария. Токен — в кабинете, первый запрос — за минуту.

Оглавление: быстрый старт · запуск звонка · ответы · дедупликация · переменные · исходящий вебхук · статусы и исходы · Bitrix24 / AmoCRM · свой транк · безопасность · примеры кода · Partner API

1. Быстрый старт

Токен выдаётся на сценарий: кабинет → настройки сценария → «Откуда приходят звонки» → «Вебхук / API — запуск из CRM или вашей системы». Подключать CRM не нужно: готовый URL с токеном показан в поле «Webhook URL (содержит токен сценария)». Первый звонок — одна строка:

curl "https://app.botleadgen.ru/api/scenarios/ВАШ_ТОКЕН/start-call?phone=79001234567"

Ответ 200 со status: "accepted" — звонок в очереди. Сохраните call_id: по нему вы свяжете результат разговора (исходящий вебхук) со своей сущностью. URL в кабинете оканчивается на /crm-webhook — это тот же эндпоинт, что /start-call (см. ниже), используйте любой.

2. Запуск звонка: полный справочник

GET | POST  https://app.botleadgen.ru/api/scenarios/{API_TOKEN}/start-call

Источник запуска — любой: ваш бэкенд, платформа, сайт, 1С, CRM. Полный алиас того же эндпоинта — …/crm-webhook (исторический, работает идентично). Данные принимаются в трёх форматах одновременно: query-параметры, JSON-тело, form-urlencoded — при совпадении ключей значение из тела перекрывает query.

Параметры

ПолеОбяз.Что делает
phoneда*Номер абонента в любом привычном формате («+7 900…», «8 900…») — нормализуем сами. Если в поле несколько номеров через запятую/точку с запятой — возьмём первый. *Можно не передавать, если передан deal_id и подключена интеграция Bitrix24/AmoCRM — тогда телефон достанем из карточки сделки.
name / contact_nameнетИмя клиента → переменная {{name}} (робот может обращаться по имени). Если не передано, но есть deal_id + CRM-интеграция — возьмём из карточки.
var_*нетЛюбые ваши данные: var_client_id → переменная {{client_id}}, var_order{{order}}. Доступны в репликах робота, Webhook-блоке и отчёте — так вы «прошиваете» свой ID через весь цикл. До 30 полей, значение до 500 символов; системные имена переменных перекрыть нельзя.
deal_id / dealIdнетID сделки → {{deal_id}} (и алиас {{lead_id}}); блоки «Действие в CRM» работают с этой сделкой; участвует в дедупликации.
stage_id / stageIdнетЭтап → {{crm_stage_id}}.
pipeline_id / pipelineIdнетВоронка → {{crm_pipeline_id}}.
contact_id / contactIdнетID контакта CRM — для сценариев, работающих с контактом, а не сделкой → {{contact_id}}.
event_tsнетВремя события у вас (ISO-8601 или Unix-время). Защита от «протухших» вебхуков: события старше момента включения приёма игнорируются с status: "ignored", reason: "stale_webhook" — полезно, если CRM ретраит старую очередь.
Незаполненные шаблоны вида {{lead.id}} (CRM не подставила значение) распознаются и игнорируются — «фигурные скобки» не попадут в звонок. Формат AmoCRM Salesbot (leads[status][0][id] и т.п.) разбирается автоматически: lead_id, этап и воронку достанем из него, телефон и имя передавайте query-параметрами.

Ответы: полный список

Все «мягкие» исходы приходят с кодом 200 и различаются полем status:

statusТело и что делать
accepted{"status":"accepted","scenario_id":"…","scenario_version_id":"…","call_id":"…","phone":"79001234567"} — звонок поставлен в очередь. Сохраните call_id.
duplicate_ignored{"status":"duplicate_ignored","call_id":"…","phone":"…","deal_id":"…"} — по этому номеру/сделке недавно уже был звонок этого сценария; call_id — ID того, прошлого звонка. Подробнее — дедупликация.
ignored + reason: "phone_unresolved"Телефон не передан и не достался из CRM. В теле — hint с подсказкой. Проверьте параметр phone или привязку контакта к сделке.
ignored + reason: "stale_webhook"Событие старше момента включения приёма (см. event_ts) — намеренно пропущено.
Код ошибкиПричина
404Неверный токен.
403Сценарий выключен в кабинете.
400У сценария не выбран источник «Вебхук / API» (настройки сценария → «Откуда приходят звонки»).
429Превышен лимит 600 запросов/мин с одного IP — повторите с паузой.
503Режим техработ. Звонок не потерян — просто повторите запрос позже; ретраи по 503 безопасны.

Дедупликация повторных запусков

CRM любят слать один и тот же вебхук несколько раз (ретраи, двойные триггеры автоматизаций). Платформа сама отсекает дубли: повторный запуск по тому же номеру и той же сделке внутри настраиваемого окна вернёт duplicate_ignored и НЕ создаст второй звонок. Окно настраивается в кабинете (Настройки → Телефония → «Окно дедупа»); если нужно легитимно перезвонить раньше — уменьшите окно.

Очередь и исполнение

Запрос ставит звонок в очередь всегда — даже при нулевом балансе лид не теряется, исполнение дождётся пополнения. Набор идёт с учётом окна обзвона линии и её лимита одновременных звонков; если запрос пришёл вне окна — звонок уйдёт при его открытии. Исполняется опубликованная версия сценария, зафиксированная в момент постановки: правки чернового сценария на звонки в очереди не влияют.

3. Переменные сценария: что доступно

Переменные подставляются в реплики робота, в URL/тело Webhook-блока и попадают в отчёт звонка. Синтаксис — {{имя}}.

ПеременнаяОткуда
{{call_id}}, {{phone}}Всегда: ID звонка на платформе и набранный номер.
{{name}}Из запуска (name/contact_name) или из карточки CRM.
{{deal_id}}, {{lead_id}}, {{crm_stage_id}}, {{crm_pipeline_id}}, {{contact_id}}Из CRM-параметров запуска (см. выше).
ваши var_*Из запуска: var_client_id{{client_id}} и т.д.
извлечённые из речиБлоки распознавания в сценарии складывают данные (дата, бюджет, адрес — что настроите) в переменные с именами, которые задаёт автор сценария.
{{business_outcome}}Бизнес-итог: «Тег результата», указанный в финальном блоке ветки («Согласие», «Отказ», «Перезвон»…).
{{system_disposition}}, {{system_details}}Технический исход набора/разговора (см. статусы).
{{last_webhook_status}}, {{last_webhook_response}}HTTP-статус и тело (до 2000 символов) последнего ответа вашего сервера на Webhook-блок — можно ветвиться по ним дальше в сценарии.

4. Получение результатов: исходящий вебхук

Блок «Webhook» ставится в любую точку сценария и делает HTTP-запрос на ваш URL. Вы полностью управляете методом, заголовками и телом; шаблоны {{…}} подставляются и в URL, и в тело, и в заголовки:

POST https://ваш-сервис.ru/lead-result
Content-Type: application/json

{
  "call_id":  "{{call_id}}",
  "phone":    "{{phone}}",
  "name":     "{{name}}",
  "deal_id":  "{{deal_id}}",
  "order":    "{{order}}",
  "result":   "{{business_outcome}}",
  "tech":     "{{system_disposition}}"
}
Параметр блокаКонтракт
МетодЛюбой HTTP-метод, по умолчанию POST.
ЗаголовкиСвои (например Authorization); по умолчанию Content-Type: application/json.
ТелоJSON-шаблон. После подстановки переменных должен оставаться валидным JSON — строковые значения берите в кавычки.
Таймаут1–60 секунд, по умолчанию 10.
Асинхронный режим (по умолчанию)Fire-and-forget: разговор не ждёт ваш сервер, у блока один выход. Результат запроса виден в отчёте звонка.
Синхронный режимРобот ждёт ответ и ветвится: «Успех» (HTTP < 400) / «Ошибка» (сеть или ≥ 400). Статус и тело ответа доступны дальше как {{last_webhook_status}} / {{last_webhook_response}}.
ИдемпотентностьЕсли движок повторно проходит тот же блок с тем же телом (восстановление после сбоя) — запрос НЕ уходит второй раз.
РетраиС нашей стороны ретраев нет: запрос уходит один раз. Нужна гарантия доставки — используйте синхронный режим и обработайте ветку «Ошибка» (например, блоком с резервным URL).
Практика: ставьте Webhook-блоки на ветки исходов («Согласие» — один запрос, «Отказ» — другой) и/или один общий перед финальным блоком — тогда вы получаете и бизнес-итог, и все извлечённые данные одним запросом, привязанным к вашему var_*-идентификатору.

5. Статусы звонка и технические исходы

Статус звонка (виден в кабинете и отчётах): queueddialingactive → финальный (completed, caller_hangup, no_answer, failed). Технический исход дозвона/разговора приходит в {{system_disposition}}; основные значения:

ЗначениеЧто случилось
answeredАбонент взял трубку, разговор состоялся.
no_answerНе дозвонились (не взял, отклонил, оператор не соединил).
busyЗанято.
unavailableНедоступен / вне сети.
caller_hangupАбонент положил трубку до конца сценария.
silenceТишина в линии (часто автоответчик оператора).
outside_call_windowЗапуск вне окна обзвона — звонок перенесён.
errorНепредвиденная ошибка исполнения (маршрутизируется в сценарии системным интентом «Ошибка»).

Автоответчики и IVR-меню распознаются платформой и маршрутизируются внутри сценария системными интентами («Робот», «IVR») — автор сценария решает, что с ними делать (положить трубку, перезвонить позже и т.д.).

6. Если ваш стек — Bitrix24 или AmoCRM

Отдельно от универсального API есть штатные двусторонние интеграции с этими CRM (смена стадии запускает звонок, итог разговора двигает сделку): робот для Битрикс24 и бот для AmoCRM. Для интеграции собственной платформы они не нужны — достаточно разделов 2 и 4.

7. Телефония: можно через ваш транк

Звонки могут идти как через нашу телефонию, так и через ваш SIP-транк: вы передаёте реквизиты транка, мы подключаем его линией к вашему аккаунту — набор выполняет наша платформа, но с ваших номеров, через вашего оператора и по вашим тарифам на связь. Ограничение одновременных звонков и темп набора настраиваются на линию.

8. Безопасность и лимиты

ЧтоЗначение
АутентификацияСекретный токен сценария в URL (bearer-семантика). Токен — как пароль: не публикуйте в клиентском коде, логах и трекерах. В наших логах он маскируется.
Ротация токенаКнопка «↻ Перегенерировать токен» в настройках сценария (рядом с Webhook URL). Старый URL перестаёт работать немедленно — обновите его во всех внешних системах.
ТранспортТолько HTTPS.
Rate limit600 запросов/мин с одного IP — массовый перенос сотен сделок проходит спокойно; лимит режет только петли автоматизаций и перебор токенов.
Персональные данныеЗаписи, расшифровки и номера не покидают платформу — доступ только через кабинет (152-ФЗ).
Идемпотентность запускаКаждый accepted = один звонок в очереди. Ретраи по 503/429 безопасны; случайные дубли по той же сделке отсекает дедупликация.

9. Примеры кода

curl

# GET — минимум
curl "https://app.botleadgen.ru/api/scenarios/ВАШ_ТОКЕН/start-call?phone=79001234567&name=Иван"

# POST JSON — имя + сквозные данные var_*
curl -X POST "https://app.botleadgen.ru/api/scenarios/ВАШ_ТОКЕН/start-call" \
  -H "Content-Type: application/json" \
  -d '{
    "phone":         "79001234567",
    "name":          "Иван Петров",
    "var_client_id": "acme-42",
    "var_order":     "A-1177"
  }'

Python

import requests

r = requests.post(
    "https://app.botleadgen.ru/api/scenarios/ВАШ_ТОКЕН/start-call",
    json={"phone": "79001234567", "name": "Иван Петров", "var_order": "A-1177"},
    timeout=10,
)
data = r.json()
if r.ok and data.get("status") == "accepted":
    save_call_id(data["call_id"])          # свяжете с результатом из вебхука
elif data.get("status") == "duplicate_ignored":
    pass                                   # звонок уже был — это не ошибка
else:
    log.warning("botleadgen: %s %s", r.status_code, data)

PHP

$ch = curl_init("https://app.botleadgen.ru/api/scenarios/ВАШ_ТОКЕН/start-call");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
    CURLOPT_POSTFIELDS => json_encode([
        "phone" => "79001234567",
        "name" => "Иван Петров",
        "var_order" => "A-1177",
    ]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
]);
$response = json_decode(curl_exec($ch), true);
// $response["status"] === "accepted" → сохранить $response["call_id"]

10. Partner API: интеграция под свой фронтенд

Разделы 1–9 — простой путь «запустил звонок токеном → получил результат Webhook-блоком». Если вы строите свою платформу поверх нашего ядра (свой кабинет и отчётность), есть server-to-server Partner API с ключами аккаунта, финальным колбэком и записями по API. Ниже — что уже работает.

Аутентификация: API-ключ аккаунта

Ключ создаётся в кабинете (раздел «🔌 Интеграции CRM» → «🔑 API-ключи»). Полный ключ и webhook-secret показываются один раз. Скоупы: calls:write, calls:read, scenarios:write, audio:write.

Authorization: Bearer blg_k1_XXXXXXXXXXXXXXXXXXXXXXXXXXXX

Запуск звонка

{scenario_ref} — идентификатор сценария: подойдёт токен сценария из кабинета (то же, что в разделах 1–2), внутренний ID сценария или ваш внешний ID (если сценарий загружен через ingest).

curl -X POST "https://app.botleadgen.ru/api/partner/v1/scenarios/{scenario_ref}/calls" \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" -H "Content-Type: application/json" \
  -d '{"phone":"79001234567","name":"Иван","var_client_id":"acme-42"}'
# → 202 {"call_id":"…","status":"accepted","phone":"…"}

Финальный колбэк call.completed

Задайте callback_url у ключа — после каждого звонка на него прилетит POST с полным отчётом: тег-итог, все переменные (включая ваши var_*), расшифровка диалога целиком, длительность, стоимость, флаг наличия записи. Подпись — X-BLG-Signature: sha256=… (HMAC телом на webhook-secret). Не доставили (не-2xx / таймаут) — ретраим с бэкоффом 1м→5м→30м→2ч→6ч, 6 попыток; и всегда можно забрать pull-запросом.

{
  "event": "call.completed",
  "call_id": "…", "partner_scenario_id": "acme-scn-1",
  "phone": "79001234567", "duration_sec": 148,
  "status": "completed", "system_disposition": "answered",
  "business_outcome": "Согласие",
  "variables": {"client_id": "acme-42", "budget": "150000"},
  "transcript": [{"role":"bot","text":"Здравствуйте!"},{"role":"client","text":"да"}],
  "cost": {"total_rub": 4.35, "duration_billed_sec": 148},
  "recording_available": true
}

Отчёт и запись по запросу

Метод и путьОтвет
GET /api/partner/v1/calls/{call_id}Тот же payload, что call.completed (+ status для незавершённых).
GET /api/partner/v1/calls/{call_id}/recording{"recording_url":"…","expires_in_sec":259200} — подписанная ссылка на wav, TTL 72ч; файл остаётся в нашем контуре (152-ФЗ).
Сборка сценария на вашей стороне (ваш редактор → JSON нам → обзвон) — контракт согласован, реализуется под подтверждённый с интегратором набор блоков. Запросите через форму на сайте — вышлем схему v1.

Получить токен — регистрация за минуту →