CRM: amoCRM и Битрикс24

Готовых действий «создать сделку», «найти контакт», «передвинуть по воронке» в платформе нет. На каждую CRM есть пара нод — выбор подключения и один универсальный вызов, — и этот вызов представляет собой тонкую обёртку над её REST API: вы сами пишете, какой метод дёрнуть и что положить в тело, а платформа берёт на себя адрес, заголовок авторизации, таймаут и разбор JSON. Значит, рядом с редактором всегда открыта документация самой CRM: имена методов, названия полей и форма ответа — её, не наши. Это и есть цена универсальности: любой метод, который умеет CRM, доступен в день своего появления и не ждёт, пока мы напишем под него отдельную ноду с полями «Название сделки» и «Сумма».

Что хранит подключение и чем авторизуется запрос

Учётные данные лежат в рабочем пространстве, а не в графе — общее устройство описано в обзоре интеграций. Здесь важно, что у двух CRM устроено это по-разному.

Вид подключенияПоляЧем авторизуется запрос
amoCRMПоддомен + Долгоживущий токензаголовок Bearer с токеном
Битрикс24URL входящего вебхука (+ Домен портала, необязательно)сам URL: код вебхука лежит в пути

amoCRM. В поле Поддомен кладётся либо голое имя аккаунта (mycompanymycompany.amocrm.ru), либо целый хост в одной из трёх разрешённых зон: amocrm.ru, amocrm.com, kommo.com. Список зон закрытый, и это не перестраховка: значение подставляется в адрес запроса, к которому прикладывается ваш токен, — произвольный хост в этом поле означал бы, что сохранённое подключение способно увезти токен куда угодно. Токен — долгоживущий, выпускается в настройках интеграции самого аккаунта amoCRM; OAuth с обновлением токена платформа не ведёт, так что срок жизни токена — ваша забота, и в день его истечения все вызовы начнут отвечать 401.

Битрикс24. У входящего вебхука ключом служит весь URL целикомhttps://<портал>.bitrix24.ru/rest/<id пользователя>/<код>/, отдельного токена нет. Поэтому поле хранится как секрет и обратно в браузер не отдаётся. Из этого следует практическое: права запроса определяет не платформа, а то, от чьего имени и с какими правами вебхук создан в портале. Ответ «недостаточно прав» лечится в Битрикс24, а не в воркфлоу. Поле Домен портала (необязательно) на сам вызов не влияет — оно сверяется с хостом вебхука при сохранении и ловит ровно одну ошибку: вставленный вебхук от другого или уже пересозданного портала.

Две ноды на сервис

Схема одинакова для обеих CRM. Нода-конфигурация (Конфигурация amoCRM, Конфигурация Bitrix24) не делает ничего, кроме выбора сохранённого подключения, и отдаёт его проводом данных в порт вызывающей ноды (amoCRM REST-вызов, Bitrix24 REST-вызов). Порядок исполнения задаёт обычная цепочка выполнения — конфигурация подключается сбоку и на него не влияет.

Вход
Bitrix24 REST-вызов
Конфигурация Bitrix24
Выход
  • Исполнение + данные
  • Данные
Подключение приезжает отдельным проводом данных; последовательность задаёт верхняя цепочка.

Ставить вторую ноду ради одного вызова необязательно: у вызывающей ноды есть собственное поле выбора подключения. Правило приоритета одно и то же во всём семействе интеграций — подключённый порт сильнее поля, и форма это прямо пишет, гася поле.

Пока не заполнено ни то, ни другое, редактор показывает предупреждение wire.required_port_not_wired, а деплой и запуск такой граф отклоняют (разбор кодов — на странице Коды валидации). Заполненное поле считается источником наравне с проводом, так что «жёлтая» подсказка исчезает в обоих случаях.

Выход config-ноды в журнале выполнения отредактирован: там остаётся только название подключения, без токена и без URL вебхука. Это стоит помнить, когда вы смотрите на прогон и не находите значения — оно не потерялось, его намеренно не пишут в базу.

Как задаётся запрос

НодаПоляЧто в них кладут
amoCRM REST Callmethod / path / bodyHTTP-глагол из списка; путь от слэша; JSON-тело
Bitrix24 REST Callmethod / paramsимя метода через точку; JSON-объект параметров

Разница не косметическая. У amoCRM адресация «как в HTTP»: GET /api/v4/leads, POST /api/v4/contacts, PATCH /api/v4/leads/12345. Глагол выбирается из фиксированного списка (GET, POST, PATCH, PUT, DELETE) — свободного ввода там нет, потому что вводить туда нечего. У Битрикс24 адресация «как в RPC»: имя метода пишется через точку — crm.lead.add, crm.deal.list, user.get, — и полностью задаёт, что произойдёт; путь и глагол платформа собирает сама.

Поля path, body, method (у Битрикс24) и paramsшаблонные: в них работают {{ inputs.<порт> }}, {{ nodes.<id>.output.<поле> }}, {{ variables.<имя> }} и {{ secret.<ИМЯ> }}, как везде (см. Шаблоны и переменные). Именно так и подставляются данные, собранные предыдущими нодами:

/api/v4/leads/{{ nodes.find_lead.output.result._embedded.leads[0].id }}

Три вещи, на которых спотыкаются в первый раз:

  • путь начинается со слэша. Он приклеивается к хосту как есть, без нормализации: api/v4/leads без ведущего слэша даст бессмысленный адрес и невнятную ошибку;
  • пустое тело и {} — разные вещи. Значение по умолчанию у body — именно {}, и это непустой JSON-объект: он уйдёт телом запроса. Для чистого GET поле стоит очистить совсем — тогда тело не отправляется вовсе. У Битрикс24 наоборот: пустые params превращаются в {}, потому что метод без аргументов — норма;
  • невалидный JSON — это отказ ноды, а не пустое тело. Ошибка приходит с кодом VALIDATION и указанием строки и колонки от разборщика. Собирать JSON конкатенацией строк в шаблоне — верный способ получить именно её; надёжнее собрать объект отдельной нодой и передать его целиком: {{ nodes.build_params.output }}.

Как читать ответ

Обе ноды кладут разобранный JSON в поле result своего выхода, то есть дальше по графу он читается так:

{{ nodes.crm_call.output.result }}

Что именно лежит внутри — определяет CRM. У Битрикс24 конверт {"result": …, "time": …} платформа распаковывает: в result попадает содержимое одноимённого поля ответа, а не весь конверт. У amoCRM распаковывать нечего — тело ответа отдаётся как есть, со всей его структурой (_embedded.leads, _links, _page и прочим), поэтому путь до нужного значения бывает длинным. Проверять форму удобнее всего прогоном в панели проверки: она показывает вход и выход каждой ноды целиком (см. Проверка воркфлоу).

Куда уходит ошибка

Клиенты обеих CRM устроены так, что сами никогда не бросают исключение: отказ транспорта, 401, 404 и ответ вида «ошибка в конверте» они сворачивают в один и тот же результат. Бросает нода — иначе вызов с мёртвым токеном заканчивался бы зелёным прогоном, а дальше по графу уезжало бы пустое значение.

Дальше поведение зависит от одной галочки в конфигурации ноды:

Выход ошибки
включён — на ноде появляется второй выход

По умолчанию выключен: без него сбой роняет весь запуск.

  • галочка выключена (так по умолчанию) — падение ноды роняет весь запуск: он получает статус failed, а ноды ниже по цепочке не выполняются;
  • галочка включена и выход подключён — управление уходит по ветке ошибки, а запуск остаётся успешным. В ветку приезжает объект с полями message (текст для автора), error_code, failed_node_id и failed_node_type. Ветвиться следует по error_code: это стабильная строка, пригодная для сравнения в ноде if.

Тонкость, которую видно только на практике: amoCRM различает виды отказов, а Битрикс24 — нет. amoCRM отвечает HTTP-статусом, поэтому 401 превращается в AUTH, 404 — в NOT_FOUND, 402 — в BILLING. Битрикс24 (как и VK ниже) отвечает 200 с ошибкой внутри тела, разбирать которую пришлось бы по тексту, поэтому его отказы приезжают одним кодом PROVIDER_ERROR, а конкретика — в message. Если ветка должна отличать «нет прав» от «нет объекта», для Битрикс24 придётся смотреть текст.

Что увидит человек: автор воркфлоу — нашу фразу плюс дословные слова CRM (в журнале, в ветке ошибки, в панели проверки), собеседник чата — только нейтральную формулировку по коду, без внутренностей провайдера. Подробный разбор — на странице Ошибки, статусы запусков — на странице Статусы.

Типичный сценарий: заявка из чата → поля → сделка

Самая частая связка выглядит так: человек пишет в чат свободным текстом, модель вытаскивает из этого текста поля, вызов CRM создаёт объект, а ответ CRM превращается в реплику для человека.

Вход
Поля заявки
LLM
crm.lead.add
Конфигурация Bitrix24
Выход
  • Исполнение + данные
  • LLM
  • Данные
Свободный текст → структура → вызов CRM → ответ в чат.
  1. Разобрать сообщение. Нода LLM со структурированным выводом возвращает не свободный текст, а JSON по заданной вами схеме — имя, телефон, что человек хочет. Именно схема, а не «попроси модель ответить JSON-ом», делает следующий шаг предсказуемым.
  2. Собрать параметры. В поле params кладётся объект метода в терминах CRM: {"fields": {"TITLE": "{{ nodes.fields.output.title }}", "NAME": "{{ nodes.fields.output.name }}"}}. Имена полей — из документации Битрикс24; у портала с настроенными пользовательскими полями там будут ещё и коды вида UF_CRM_….
  3. Вызвать метод. crm.lead.add для лида, crm.deal.add для сделки. Ответ — id созданного объекта; он же пригодится, если нужно сразу прикрепить комментарий или задачу вторым вызовом.
  4. Ответить человеку. В ноде выхода — текст со ссылкой на созданный объект, собранный из {{ nodes.crm_call.output.result }}.
  5. Решить, что делать при отказе. Для заявки клиента «молча упасть» — худший исход: включите выход ошибки и отправьте по этой ветке честное «не получилось, мы записали контакт» плюс уведомление себе.

Разбор того, как строятся такие цепочки (ветвление, шаблоны, сборка ответа), — в Уроке: логика и ветвление. Готового CRM-шаблона в примерах сейчас нет: ни один из встроенных шаблонов CRM не трогает, потому что шаблон обязан заработать сразу после установки, а вызов CRM без вашего портала и вашего токена работать не может. Ближайшая отправная точка — шаблон с извлечением полей, к которому дописывается вызов.

VK и VK Teams: только исходящие сообщения

Четыре ноды рядом с CRM — Конфигурация VK и Отправить сообщение в VK, Конфигурация VK Teams и Отправить сообщение в VK Teams — устроены так же: подключение сбоку, поля с шаблонами, выход ошибки по той же галочке. Но делают они ровно одно — отправляют текстовое сообщение.

НодаПодключение хранитПоляЧто возвращает
Send VK Messageтокен доступа + версия APIpeer_id, текстmessage_id
Send VK Teams Messageтокен бота (+ базовый URL API)chat_id, текстmessage_id

Что из этого следует практически: обе ноды имеют смысл как уведомление — «пришла заявка», «упал ночной обмен», «клиент ждёт ответа» — в беседу сотрудников, а не как канал общения с клиентом. Для VK peer_id кодирует тип получателя прямо в числе: пользователь — его id (12345), сообщество — с минусом (-98765), беседа — 2000000000 + номер беседы (беседа 5 → 2000000005). Ошибиться здесь означает отправить сообщение не туда, а не получить ошибку, — VK честно доставит его тому, чей id вы назвали. У VK Teams идентификатор чата — это email сотрудника (user@example.com) или id группового чата (681234567@chat.agent). Поле Базовый URL API (необязательно) нужно только тем, у кого Teams развёрнут на своём сервере; для облачного оставьте пустым.

Что дальше