API для программистов
Napulse открывает сторонним сервисам один вход: MCP. Это тот же интерфейс, через который с CRM работают ИИ-помощники: POST /mcp, JSON-RPC, набор инструментов с описанием входа и выхода. Отдельного REST-сервера для интеграций нет: права на каждый вызов считаются так же, как у сотрудника в браузере. Подробный разбор вызовов: API-запросы и примеры, список инструментов: Каталог MCP-инструментов.
Ключ доступа
- Откройте Интеграции → MCP и выпустите ключ в блоке подключений.
- Выберите пресет «Интеграция». В нём только области для внешнего сервиса: запуск и настройка интеграций, клиенты, сделки. Инструментов переписки в нём нет, даже если область открыта.
- Укажите срок действия: 30, 90, 365 дней или бессрочно. За 7 дней до истечения придёт напоминание. При желании задайте список IP и подсетей, с которых ключ принимается. Пустой список значит «с любого адреса».
- Ключ
lfm_…показывается один раз. Храните его в секретах приложения, не в коде и не в репозитории. - «Перевыпустить» выдаёт новый ключ, старый работает ещё 24 часа.
Если сервис должен действовать не от имени сотрудника, заведите в Команде техническую учётку «Интеграция». У неё нет входа в браузер, права задаёт должность, а действия в журнале идут от её имени. Увольнение сотрудников её не трогает.
Вызов
POST https://<ваш адрес CRM>/mcp
Authorization: Bearer lfm_…
Content-Type: application/json
Accept: application/json, text/event-stream
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"list_deals","arguments":{"limit":20}}}
Сначала выполните initialize, как показано в API-запросах: заголовки сессии и версии протокола описаны там. Список инструментов отдаёт метод tools/list. У каждого инструмента есть схема аргументов и подпись, которая попадает в журнал действий проекта.
Пример на Python:
import requests
headers = {"Authorization": f"Bearer {KEY}", "Accept": "application/json, text/event-stream"}
r = requests.post(CRM + "/mcp", headers=headers,
json={"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "list_deals", "arguments": {"limit": 20}}}, timeout=30)
r.raise_for_status()
print(r.json()["result"])
Пример на PHP:
$body = json_encode(["jsonrpc"=>"2.0","id"=>1,"method"=>"tools/call",
"params"=>["name"=>"list_deals","arguments"=>["limit"=>20]]]);
$ch = curl_init($crm."/mcp");
curl_setopt_array($ch, [CURLOPT_POST=>1, CURLOPT_POSTFIELDS=>$body, CURLOPT_RETURNTRANSFER=>1,
CURLOPT_HTTPHEADER=>["Authorization: Bearer $key","Content-Type: application/json",
"Accept: application/json, text/event-stream"]]);
$res = json_decode(curl_exec($ch), true);
Лимиты и ошибки
| Что | Значение |
|---|---|
| Читающие инструменты | 120 вызовов в минуту на ключ, разовый всплеск 30 |
| Изменяющие инструменты | 30 вызовов в минуту на ключ, разовый всплеск 10 |
| Токен входа через браузер (OAuth) | 60 минут, обновляется до 30 дней. Для скрипта берите ключ, а не этот токен |
Счётчики лимитов хранятся вне процесса CRM и не сбрасываются при выкате.
| Ответ | Значение | Что делать |
|---|---|---|
HTTP 401, key_expired |
Ключ не принят, истёк или отозван | Проверить или перевыпустить ключ |
HTTP 403, ip_not_allowed |
Запрос с адреса не из списка ключа | Проверить список IP |
HTTP 403, forbidden |
Нет области или права | Расширить ключ или должность учётки |
HTTP 200, isError, текст с rate_limited: |
Лимит вызовов. В тексте есть retryAfterSeconds: N |
Подождать N секунд и повторить |
HTTP 200, confirmationRequired: true |
Опасное действие пульта. Код приходит сотруднику, в ответе API его нет | Попросить код у сотрудника и повторить вызов с confirmationCode |
Отказ инструмента приходит обычным ответом JSON-RPC с isError, поэтому проверяйте и код HTTP, и это поле. Другие ошибки подключения собраны в разделе Ошибки подключения.
Входящие события от вашего сервиса (постбэки)
Интеграция в конструкторе получает свой адрес POST /api/integrations/postbacks/<ключ>. Способы проверки подлинности:
- подпись HMAC-SHA256 тела или тела и времени, допуск по времени 5 минут, его можно настроить до часа;
- токен в заголовке или параметре;
- подпись по шаблону для сервисов со своей схемой, например
{OutSum}:{InvId}:{секрет}|md5|upper; - дополнительно: список IP.
Тело до 256 КБ, не больше 300 запросов в минуту на адрес. Каждый запрос, включая отклонённые, попадает в журнал интеграции.
Для оплат нужна подпись. Токен подойдёт, только если включена проверка оплаты запросом к сервису. Повтор того же события не создаёт вторую оплату.
Исходящие события из CRM (вебхуки)
Интеграции → Исходящие события: выберите события, адрес https://… (не во внутреннюю сеть) и получите секрет подписки. Секрет показывается один раз.
Событие (X-Napulse-Event) |
Когда |
|---|---|
new_lead |
Новый лид |
payment |
Оплата |
deal_stage |
Смена этапа сделки |
tag_added, tag_removed |
Тег добавлен, снят |
record_new, record_status |
Новая внешняя запись, смена её статуса |
postback, schedule |
Пришёл постбэк, сработало расписание |
client_variable |
Изменилась переменная клиента |
site.visit, site.form_submitted, site.payment |
Первый визит на сайт, заявка с формы, оплата по заявке. Телефона и почты в этих событиях нет ни при какой настройке |
Заголовки каждой доставки:
X-Napulse-Event: deal_stage
X-Napulse-Delivery: <id доставки, используйте как ключ идемпотентности>
X-Napulse-Timestamp: 1762400000
X-Napulse-Signature: sha256=<HMAC-SHA256(секрет, timestamp + "." + тело)>
Проверка на Python:
import hashlib, hmac, time
expected = "sha256=" + hmac.new(SECRET.encode(), f"{ts}.{raw_body}".encode(), hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, header_signature) and abs(time.time() - int(ts)) < 300
Проверка на PHP:
$expected = "sha256=".hash_hmac("sha256", $ts.".".$rawBody, $secret);
$ok = hash_equals($expected, $header) && abs(time() - (int)$ts) < 300;
Ответьте 2xx в течение 10 секунд. Иначе будут повторы: через 10 с, 1 мин, 10 мин, 1 ч, 6 ч, затем подписка встанет на паузу, а ответственный получит уведомление. Доставки одного клиента идут по порядку. Текста переписки в событиях нет, а набор полей клиента ограничен политикой данных проекта.
Что сервис не получит через API
Биллинг и тарифы, администрирование, чужие проекты. Секреты интеграций вводит только человек в CRM. Передачу переписки через интеграцию и включение своего канала в рабочий проект разрешают только владелец или сотрудник с правом «Управлять подключениями проекта».