API для программистов | Napulse

API для программистов

Napulse открывает сторонним сервисам один вход: MCP. Это тот же интерфейс, через который с CRM работают ИИ-помощники: POST /mcp, JSON-RPC, набор инструментов с описанием входа и выхода. Отдельного REST-сервера для интеграций нет: права на каждый вызов считаются так же, как у сотрудника в браузере. Подробный разбор вызовов: API-запросы и примеры, список инструментов: Каталог MCP-инструментов.

Ключ доступа

  1. Откройте Интеграции → MCP и выпустите ключ в блоке подключений.
  2. Выберите пресет «Интеграция». В нём только области для внешнего сервиса: запуск и настройка интеграций, клиенты, сделки. Инструментов переписки в нём нет, даже если область открыта.
  3. Укажите срок действия: 30, 90, 365 дней или бессрочно. За 7 дней до истечения придёт напоминание. При желании задайте список IP и подсетей, с которых ключ принимается. Пустой список значит «с любого адреса».
  4. Ключ lfm_… показывается один раз. Храните его в секретах приложения, не в коде и не в репозитории.
  5. «Перевыпустить» выдаёт новый ключ, старый работает ещё 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. Передачу переписки через интеграцию и включение своего канала в рабочий проект разрешают только владелец или сотрудник с правом «Управлять подключениями проекта».