API и интеграции
Платформа поддерживает интеграцию с внешними системами: импорт контактов по API, автоматический экспорт лидов в CRM (amoCRM, Битрикс24) и получение уведомлений через webhook. На этой странице описаны технические детали каждого механизма.
Загрузка контактов по API#
Для автоматической загрузки контактов из внешней системы (CRM, формы, таблицы) создайте интеграцию типа «Загрузка контактов по API» на вкладке «Интеграции» в базе контактов. Платформа сгенерирует уникальный URL — на него нужно отправлять POST-запросы с контактами.
Запрос#
https://voicelines.ru/api/v1/upload-contacts/{token} Параметр {token} — уникальный ключ доступа, который отображается при создании интеграции. Аутентификация не требуется — токен в URL является единственным идентификатором.
Тело запроса#
JSON-массив объектов. Каждый объект — один контакт:
[
{
"phone": "+79001234567",
"name": "Иванов Иван",
"company": "ООО Ромашка",
"city": "Москва"
},
{
"phone": "+79007654321",
"name": "Петрова Мария"
},
{
"phone": "89005551234"
}
]| Поле | Тип | Описание |
|---|---|---|
phone | string | Обязательное. Номер телефона в любом формате — система автоматически нормализует в E.164 (например, +79001234567) и всегда сохраняет как основное поле контакта |
name | string | Имя контакта. Всегда сохраняется как основное поле контакта и доступно в роботе через плейсхолдер {name} |
| любое другое | string | Дополнительные параметры (до 128 символов ключ, до 1000 символов значение). Ключи phone и name зарезервированы и не попадают сюда. Остальные поля доступны через плейсхолдеры {ключ} |
Все дополнительные поля контакта сохраняются как есть и затем автоматически передаются в webhook в объекте contactFields. Зарезервированные поля phone и name не дублируются в contactFields, потому что они уже хранятся в основных полях контакта. Отдельной фильтрации по названиям или значениям сейчас нет, поэтому не передавайте в пользовательских полях чувствительные данные, если не готовы отправлять их во внешние системы.
Ограничения#
- Максимум 10 000 контактов за один запрос
- Дубликаты номеров (уже существующих в базе или повторяющихся в запросе) пропускаются
- Невалидные номера пропускаются (система поддерживает российские мобильные номера)
- Нечисловые значения полей конвертируются в строку
Ответ#
HTTP 200 OK
{
"totalReceived": 3,
"imported": 2,
"skipped": 1
}| Поле | Тип | Описание |
|---|---|---|
totalReceived | int | Всего контактов получено в запросе |
imported | int | Успешно импортировано |
skipped | int | Пропущено (дубликаты, невалидные номера, пустые значения) |
Коды ответов#
200 | Запрос обработан, результат в теле ответа |
400 | Ошибка валидации: пустой массив, более 10 000 контактов, некорректный JSON |
404 | Интеграция не найдена, неактивна или удалена |
При ошибке тело ответа — JSON с описанием в поле detail. Пример ответа на запрос, в котором больше 10 000 контактов:
HTTP 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Максимум 10000 контактов за один запрос"
}Пример (cURL)#
curl -X POST https://voicelines.ru/api/v1/upload-contacts/ВАШ_ТОКЕН \
-H "Content-Type: application/json" \
-d '[{"phone": "+79001234567", "name": "Иванов Иван", "company": "ООО Ромашка"}]'Пример (Python)#
import requests
url = "https://voicelines.ru/api/v1/upload-contacts/ВАШ_ТОКЕН"
contacts = [
{"phone": "+79001234567", "name": "Иванов Иван", "company": "ООО Ромашка"},
{"phone": "+79007654321", "name": "Петрова Мария"}
]
response = requests.post(url, json=contacts)
print(response.json())
# {"totalReceived": 2, "imported": 2, "skipped": 0}Интеграция с amoCRM#
Платформа умеет автоматически создавать сделки и контакты в amoCRM при достижении цели звонка, а также импортировать контакты из amoCRM для обзвона.
Подключение#
Создайте интеграцию — на вкладке «Интеграции» в базе контактов нажмите «Добавить» и выберите тип «amoCRM».
Укажите поддомен в поле «Поддомен amoCRM» — часть URL вашего аккаунта amoCRM. Например, если ваш аккаунт https://mycompany.amocrm.ru, введите mycompany.
Получите долгосрочный токен в amoCRM: откройте амоМаркет (иконка в левом боковом меню), справа вверху нажмите на кнопку «...», затем «+ Создать интеграцию», выберите «+ Создать Внешняя интеграция», сконфигурируйте интеграцию и сгенерируйте долгосрочный токен. Вставьте его в поле «Токен amoCRM».
Проверьте подключение — нажмите кнопку «Проверить подключение». Система проверит доступ к аккаунту и покажет результат.
Импорт контактов из amoCRM#
Если включён переключатель «Импорт контактов из amoCRM», платформа предоставит URL для вебхука. Настройте его в amoCRM:
Откройте амоМаркет (иконка в левом боковом меню amoCRM).
Справа вверху нажмите на кнопку «+ WebHooks».
Вставьте URL из настроек интеграции в поле адреса вебхука и отметьте событие «Создание контакта».
Также можно использовать Salesbot — настройте в нём отправку POST-запроса на этот же URL при нужном триггере.
Экспорт лидов в amoCRM#
Если включён переключатель «Экспорт лидов при достижении цели», при достижении цели звонка платформа автоматически создаст в amoCRM:
- Новую сделку с названием, включающим имя или номер контакта
- Новый контакт с телефонным номером
- Примечание к сделке с названием кампании, транскрипцией диалога и ссылкой на запись звонка
Экспорт работает через очередь с автоматическими повторными попытками (до 5 раз с увеличивающимся интервалом). Статус последней отправки и ошибки отображаются в настройках интеграции.
Интеграция с Битрикс24#
Платформа умеет автоматически создавать лиды в Битрикс24 при достижении цели звонка. Интеграция работает через входящий вебхук Битрикс24 — для настройки не нужны приложения или OAuth.
Подключение#
Создайте интеграцию — на вкладке «Интеграции» в базе контактов нажмите «Добавить» и выберите тип «Битрикс24».
Создайте входящий вебхук в Битрикс24: откройте Приложения → Разработчикам, вкладка «Готовые сценарии» → Другое → «Входящий вебхук». В разделе «Настройка прав» отметьте CRM и нажмите «Сохранить».
Скопируйте URL вебхука целиком (он будет вида: https://mycompany.bitrix24.ru/rest/1/abc123secret/) и вставьте его в поле «URL вебхука» в настройках интеграции.
Проверьте подключение — нажмите кнопку «Проверить подключение». Система проверит доступ к порталу и покажет результат.
Экспорт лидов в Битрикс24#
Если включён переключатель «Экспорт лидов при достижении цели», при достижении цели звонка платформа автоматически создаст в CRM:
- Новый лид с названием, номером телефона, именем контакта и транскрипцией разговора
- Комментарий в таймлайне с транскрипцией диалога и ссылкой на запись звонка
Экспорт работает через очередь с автоматическими повторными попытками (до 5 раз с увеличивающимся интервалом). Статус последней отправки и ошибки отображаются в настройках интеграции.
Лид перед переводом сотруднику#
В настройках перевода базы контактов галочка «Отправлять лид до перевода» включена по умолчанию. Сам перевод включается отдельно. После подготовки перевода платформа начинает отправку лида в подключённые Telegram, MAX, email, CRM и webhook, чтобы сотрудник получил итоги разговора с роботом. Получение сообщения до ответа сотрудника зависит от скорости доставки.
Ранний лид содержит резюме разговора и отдельную пометку «Запрошен перевод сотруднику». Если резюме отсутствует, используется общая формулировка о достигнутой цели. Длительность указана на момент подготовки перевода. Telegram, MAX, email и CRM получают итоги без диалога; полный текст сохраняется в карточке звонка. В Telegram учитывается ограничение всего сообщения в 4096 символов, в MAX — 4000. При сокращении резюме сохраняются пометка перевода и ссылка.
Ссылка на запись может быть недоступна до завершения всего разговора, включая сотрудника, и сохранения аудио. После окончания система может изменить статус в карточке звонка, но раннее сообщение автоматически не обновляется и второй лид не отправляется. Отдельного сообщения о готовности записи нет. При выключенной галочке действует обычная отправка после звонка.
Webhook-уведомления#
Webhook — это один из каналов уведомлений. При каждом подходящем звонке платформа отправляет HTTP POST-запрос на указанный URL с полными данными о звонке в формате JSON.
Базовые поля звонка передаются всегда. Если у контакта были дополнительные пользовательские поля из импорта, они приходят в объекте contactFields. Поле transcript передаётся только если в настройках webhook включена опция «Передавать полную транскрипцию разговора».
HTTP-запрос#
https://your-server.com/webhook HTTP/1.1| Заголовок | Описание |
|---|---|
X-Webhook-Event | Тип события: lead.goal_achieved (цель достигнута), call.completed (звонок завершён) или test (тестовый запрос) |
X-Webhook-Id | Уникальный идентификатор отправки (UUID) — используйте для идемпотентности |
X-Webhook-Signature | HMAC-SHA256 подпись тела запроса (если настроен секретный ключ). Формат: sha256=<hex> |
JSON-тело запроса#
{
"callId": "3fa85f97-6e93-4c3a-aab1-8cb9d1a1d8f5",
"organizationName": "Моя компания",
"callListId": "d1a2b3c4-5678-9012-abcd-ef3456789012",
"callListName": "Обзвон клиентов",
"callListItemId": "e5f6a7b8-9012-3456-cdef-123456789abc",
"phoneE164": "+79001234567",
"contactName": "Иванов Иван",
"status": "GoalAchieved",
"isGoalAchieved": true,
"goalSummary": "Клиент согласился на встречу",
"goalConversationResume": "Обсудили условия. Встреча назначена на завтра в 14:00",
"contactFields": {
"company": "ООО Ромашка",
"city": "Москва"
},
"transcript": "Робот: Добрый день, удобно говорить?\nКлиент: Да, пару минут есть.\nРобот: Тогда коротко расскажу...",
"durationSeconds": 125,
"recordingUrl": "https://voicelines.ru/public/recordings/3fa85f97.wav",
"calledAtUtc": "2026-04-04T10:30:45Z"
}| Поле | Тип | Описание |
|---|---|---|
callId | string (UUID) | Идентификатор звонка |
organizationName | string | Название организации |
callListId | string (UUID) | Идентификатор базы контактов |
callListName | string | null | Название базы контактов |
callListItemId | string (UUID) | Идентификатор контакта в базе |
phoneE164 | string | Номер телефона в формате E.164, например +79001234567 |
contactName | string | null | Имя контакта (если задано) |
status | string | Статус звонка (см. таблицу ниже) |
isGoalAchieved | boolean | true — цель достигнута |
goalSummary | string | null | Краткий результат (заполняется при достижении цели) |
goalConversationResume | string | null | Резюме разговора; в раннем лиде — результат робота и пометка о запросе перевода |
contactFields | object | null | Пользовательские поля контакта из импорта. Поле появляется только если у контакта есть дополнительные параметры. Все значения передаются без дополнительной фильтрации. |
transcript | string | null | Полная транскрипция разговора одним текстом. Поле появляется только если для webhook включена опция передачи транскрипции. |
durationSeconds | int | Длительность в секундах; в раннем лиде — на момент подготовки перевода |
recordingUrl | string | null | Ссылка на запись; в раннем лиде может отвечать 404 до окончания разговора и сохранения аудио |
calledAtUtc | string (ISO 8601) | Время звонка в UTC |
Статусы звонка#
GoalAchieved | Цель достигнута |
CallLater | Перезвонить |
NotInterested | Не интересно |
HungUp | Сбросил |
Negative | Негатив |
NoAnswer | Клиент не ответил |
Voicemail | Сработал автоответчик |
Silence | Клиент молчал или не дал распознаваемого ответа |
Error | Звонок завершился ошибкой обработки |
Initiated — технический промежуточный статус активного звонка; в webhook payload он не отправляется.
Проверка подписи (HMAC-SHA256)#
Если при создании webhook-уведомления указан секретный ключ, каждый запрос подписывается алгоритмом HMAC-SHA256. Подпись передаётся в заголовке X-Webhook-Signature в формате sha256=<hex>.
Алгоритм проверки:
- Возьмите тело запроса как строку (raw body)
- Вычислите
HMAC-SHA256(body, secret)— результат в lowercase hex - Сравните с подписью из заголовка (без префикса
sha256=)
Пример проверки (Node.js)#
const crypto = require('crypto');
function verifySignature(rawBody, secret, signatureHeader) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const received = signatureHeader.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(received)
);
}Пример проверки (Python)#
import hmac, hashlib
def verify_signature(raw_body: bytes, secret: str, signature_header: str) -> bool:
expected = hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
received = signature_header.replace("sha256=", "")
return hmac.compare_digest(expected, received)Webhook при переводе сотруднику#
При включённой ранней отправке приходит существующее событие lead.goal_achieved: status = GoalAchieved, isGoalAchieved = true. Поля goalSummary и goalConversationResume содержат результат робота и пометку о запросе перевода. Это не подтверждение успешного соединения с сотрудником. Полный transcript передаётся только при включённой опции передачи транскрипции; ограничение длины Telegram/MAX к нему не применяется.
После принятия раннего события автоматического финального webhook нет, включая call.completed при настройке «Все звонки». Последующее уточнение статуса не меняет уже отправленные данные. Явная ручная смена статуса сохраняет обычные правила уведомлений и может создать отдельное событие. Новых полей для признака ранней отправки или ссылки на запись нет.
Подтвердите получение webhook ответом 2xx, не ожидая готовности recordingUrl; загрузку записи можно выполнить позднее. При выключенной галочке, отсутствии перевода, получателей или успешной ранней постановки работают обычные правила отправки после звонка.
Таймаут и повторные попытки#
Платформа ожидает ответ от вашего сервера не более 10 секунд. При получении HTTP-ответа с кодом 2xx запрос считается доставленным. При любой другой ошибке (код 4xx/5xx, таймаут, ошибка подключения) система выполнит повторную попытку: всего до 5 попыток с растущей паузой. Если ни одна попытка не прошла, событие больше не отправляется.
Повторы одного события сохраняют тело запроса и X-Webhook-Id. Используйте этот идентификатор для защиты от повторной обработки. Один callId связывает события со звонком, но не отличает отдельное ручное уведомление от повтора доставки.