Безопасное подключение к Битрикс24 через входящий вебхук или локальное приложение: чтение лидов, сделок, воронок, стадий, источников, UTM, звонков и истории стадий, сверка с Яндекс Директом и Метрикой, атрибуция обращений, запись только по плану и разрешению владельца. Использовать вместо amoCRM/Roistat, когда CRM клиента — Битрикс24.
Installs into .claude/skills of the current project.
Are you the author of Bitrix24 Crm Api?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/hashgraph-online-bitrix24-crm-api)
---
name: bitrix24-crm-api
description: "Безопасное подключение к Битрикс24 через входящий вебхук или локальное приложение: чтение лидов, сделок, воронок, стадий, источников, UTM, звонков и истории стадий, сверка с Яндекс Директом и Метрикой, атрибуция обращений, запись только по плану и разрешению владельца. Использовать вместо amoCRM/Roistat, когда CRM клиента — Битрикс24."
---
# Битрикс24: CRM через REST
## Граница задачи
Навык читает CRM клиента и сверяет её с рекламой. Запись (создание, изменение, удаление лидов, сделок, полей, стадий, вебхуков) — только по отдельному плану, с точным списком полей, «да» владельца и чтением после записи. Реклама, цели, ставки и кампании меняются только навыком `yandex-direct-unified`.
## Доступ
1. Берёт адрес из переменной `BITRIX24_WEBHOOK_URL` (вид `https://<портал>/rest/<id_пользователя>/<код>/`) или из закрытого JSON с правами `0600`. Адрес и код никогда не печатай, не передавай аргументом командной строки и не клади в журнал, отчёт и репозиторий.
2. Вебхук действует от имени сотрудника, который его создал, и в рамках выбранных скоупов. Создаёт администратор или сотрудник с разрешением администратора. Для чтения достаточно скоупа `crm`; имена сотрудников требуют `user`; статистика звонков (`voximplant.statistic.get`) требует `telephony` и право «Статистика звонков — Просмотр». Если на ответе `insufficient_scope`, не повторяй запрос: попроси отдельный вебхук с нужным скоупом (переменная `BITRIX24_TELEPHONY_WEBHOOK_URL`) или используй локальное приложение.
3. Часть методов (например, привязка виджетов, часть телефонии) недоступна из вебхука и требует контекста приложения. Для нескольких порталов, событий и методов с контекстом создай локальное приложение (OAuth 2.0: `access_token` живёт 1 час, `refresh_token` 180 дней; код авторизации 30 секунд) и храни токены в файле `0600`.
4. Новый вебхук или приложение создаёт только владелец или по его явному «да». Перед этим проверь, нет ли уже подходящего. Срок действия вебхука может быть ограничен: при ошибке авторизации сначала проверь его.
5. Файлы доступа и выгрузки (в них телефоны и имена) держи в закрытой папке, добавь её в `.gitignore`, в отчётах и чатах телефоны маскируй.
## Режим чтения
1. Скрипт `scripts/bitrix24_read.py` (команды `probe`, `schema`, `export`) вызывает только методы из белого списка: `crm.item.list`, `crm.item.fields`, `crm.lead.list`, `crm.deal.list`, `crm.lead.fields`, `crm.lead.userfield.list`, `crm.status.list`, `crm.status.entity.types`, `crm.category.list`, `crm.dealcategory.list`, `crm.stagehistory.list`, `crm.activity.list`, `crm.contact.list`, `voximplant.statistic.get`, `user.get`, `scope`, `batch` (только с чтением внутри). Любой другой метод — отказ.
2. Основной путь — `crm.item.list` (`entityTypeId`: лид 1, сделка 2, контакт 3, компания 4). `crm.lead.list` и `crm.deal.list` помечены в документации как устаревшие; используй их только когда поле недоступно в `crm.item.list`.
3. Страница списка всегда 50 записей. Малые выборки — через `start`/`next`. Большие выгрузки — обход по ID: сортировка `ID` по возрастанию, в фильтре `>ID` последнего полученного, `start=-1`, повтор пока вернулось 50. Для этого режима `total` не приходит: объём считай отдельным запросом.
4. Множественные поля (`PHONE`, `EMAIL`) перечисляй в `select` явно; маска `*` их и пользовательские поля не включает, добавляй `UF_*`. Поля UTM (`UTM_SOURCE`, `UTM_MEDIUM`, `UTM_CAMPAIGN`, `UTM_CONTENT`, `UTM_TERM`) называй в `select` явно; в `crm.item.list` сверь их имена через `crm.item.fields`.
5. В фильтре `ENTITY_ID` и `STATUS_ID` справочников передавай строкой. Префиксы: `>=`, `>`, `<=`, `<`, `@` (IN, массив), `!@`, `%`, `=`, `!=`.
6. Лимиты (облако): для тарифа «Энтерпрайз» 5 запросов в секунду при пороге 250, для остальных 2 в секунду при пороге 50; превышение — HTTP 503 `QUERY_LIMIT_EXCEEDED`; ресурсоёмкость — HTTP 429 `OPERATION_TIME_LIMIT` (ориентир `operating_reset_at` в блоке `time`). Держи не больше одного потока, паузу между запросами не меньше 0,5 с, при 503/429 повторяй с растущей паузой, не запускай параллельные серии с того же IP. `batch` — до 50 команд, вложенный `batch` запрещён, ошибки команд лежат в `result_error` при ответе 200.
7. Каждая выгрузка сохраняет манифест: метод, фильтр, период, число строк, число уникальных ID, число страниц, признак `complete`, время начала и конца. Повтор или отсутствие ID в выгрузке — ошибка; `ID` скрипт добавляет в поля сам. В файл попадают только объявленные поля (`--fields` или набор по умолчанию), даже если метод вернул больше. Телефоны, почта и имена сохраняются только с `--include-personal-data` и только если названы в `--fields`. Неполную выгрузку (`complete=false`) не превращай в отчёт.
8. Время: даты REST приходят в часовом поясе портала. Переводи всё в UTC и записывай границу периода с поясом; Метрика считает в поясе счётчика, копия данных BI отстаёт.
## Что прочитать перед вопросами клиенту
1. Все воронки сделок (`crm.category.list` с `entityTypeId=2`; основная воронка имеет `id=0`) и стадии каждой через `crm.status.list`; семантика стадии: `S` успех, `F` провал, пусто или `P` в работе.
2. Статусы лидов, справочник источников, пользовательские поля лидов и сделок, историю стадий (`crm.stagehistory.list`, `TYPE_ID`: 1 создание, 2 промежуточная, 3 финальная, 5 смена воронки).
3. Какие формы и интеграции уже заводят лиды: штатные веб-формы CRM и установленные приложения интеграции форм. Пока не прочитано, не пиши «форма не подключена» и не включай второй отправитель.
4. Только после этого спрашивай клиента о том, чего в CRM нет.
## Атрибуция обращений
Порядок источников для лида, строго в таком порядке:
1. Точная метка: `UTM_SOURCE` (`yandex`; вариант `ya` принимай только при `UTM_MEDIUM=cpc` и числовой кампании, существующей в выгрузке Директа), `UTM_MEDIUM=cpc`, `UTM_CAMPAIGN` равен идентификатору кампании Директа; `UTM_CONTENT` равен идентификатору объявления, `yclid` — подтверждение клика. Совпадение только точное, без подбора по похожести.
2. Номер коллтрекинга: ближайший к созданию лида входящий звонок (`CALL_TYPE` 2 или 3), связанный с лидом прямо (`CRM_ENTITY_TYPE=LEAD`) или через дело звонка с владельцем-лидом, разница не больше 300 секунд, совпадение номеров с картой источников, единственный кандидат. Окно не расширяй: большие окна переносят исходящие лиды во входящие.
3. Иначе источник из подписи CRM с префиксом «CRM:».
Дополнительные правила:
- Общий (основной) номер организации не является рекламной связью.
- Если оператор набрал номер без открытой карточки, телефония сама заводит лид (`CALL_TYPE=1` в пределах нескольких секунд от создания): выдели такие лиды в отдельный источник «Исходящий звонок оператора», не называй их «не реклама» (первичный источник пациента не записан) и не считай в стоимости обращения.
- Заявка без метки — `unknown`, не органика. Источник доказывает только ClientID Метрики из карточки (визит в Метрике до заявки). Сопоставление «по времени цели» годится для разовой оценки и помечается как оценка.
- ClientID со значением `0` не связь с Метрикой. Отсутствие согласия на аналитику даёт пустое значение.
- Тестовые и служебные записи отфильтровывай одним и тем же условием во всех выборках (пользовательские поля «тест», «служебная форма», имя «Тест»). Новые тестовые лиды без разрешения владельца не создавай.
- Единица счёта — карточка лида. Повторные карточки одного телефона показывай отдельной строкой («уникальных телефонов»), первичный источник клиента — отдельным столбцом.
- Удалённые лиды в выгрузке не видны; звонки на рекламные номера бери из статистики звонков отдельным показателем и не складывай с лидами.
## Сверка с Директом и Метрикой
1. Расход, показы, клики и кампании читай навыком `yandex-direct-unified` (или `yd_*` MCP), цели и визиты — `ym_*`. Не вызывай их API из этого навыка.
2. Сопоставляй по числовым идентификаторам кампаний и объявлений. Таблица должна показывать три числа по каждой кампании: конверсии цели в Метрике/Директе, лиды CRM с точной меткой, лиды CRM по номеру коллтрекинга.
3. Расхождение между конверсиями рекламы и лидами CRM ожидаемо (заявка без метки, звонок без согласия, окно атрибуции). Назови причину по доказательствам: ClientID, метка, звонок, время. Нулевой результат в отчёте не доказывает отсутствие обращений.
4. Воронка: стадия «записан» не равна явке; успешная сделка не равна оплате; выручка привязана к дате создания лида или к дате закрытия, укажи, к какой. Проверь двойные сделки на одну сумму.
5. НДС: перед любой арифметикой с расходом проверь признак НДС источника (расход, полученный штатным коннектором рекламной аналитики Битрикс24, приходит с НДС). Неподтверждённый коэффициент не добавляй.
## Запись
Любая запись требует: плана с точным списком сущностей и полей, «да» владельца на этот план, снимка полей «до» в закрытой папке, записи только перечисленных полей, чтения после записи с сопоставлением, журнала с откатом. Запрещено без отдельного «да»: создание и удаление лидов и сделок, смена стадий, изменение пользовательских полей, создание вебхуков и приложений, массовые изменения. Ответ HTTP 500 или таймаут на записи означает «исход неизвестен»: перечитай запись, а не повторяй вызов вслепую. Создание пользовательских полей — только отдельным скриптом с режимом без `--apply` (печатает план); в наборе записывающих скриптов нет.
## Ловушки
- Лид может сразу конвертироваться в сделку: ищите обращение и по сделке (`crm.deal.list` с фильтром `@LEAD_ID`), а не только по лиду.
- Повторное сообщение существующего контакта новый лид не создаёт: повторные обращения ищите по контакту; дубли по телефону — `crm.duplicate.findbycomm` с `type: PHONE`.
- Общая форма сайта может присылать лиды вебхуком без меток: смотрите поля формы, а не только `UTM_*`.
- Чаты открытых линий: `imopenlines.crm.chat.getLastId` (`CRM_ENTITY_TYPE`: `LEAD`, `DEAL`, `CONTACT`) отдаёт только последний чат сущности — для периода перебирайте все сущности; сообщения — `im.dialog.messages.get` с `DIALOG_ID` вида `chat<id>`. Метка запуска бота (`/start <метка>`) видна в сообщениях чата; ссылка мессенджера без метки к рекламе не привязывается.
- Поля, которые дописывает фоновая интеграция аналитики, появляются через несколько минут после создания лида.
- «Группа номеров» в описании источника — группа номеров АТС, а не коллтрекинг.
- Роботы и бизнес-процессы лидов не трогайте.
- Цепочку коллтрекинга (пул подменных номеров → скрипт сайта → приёмник звонков → карта номеров в BI) включайте с конца: пул номеров — последним, после всех потребителей.
- Без вебхука в браузере, где пользователь уже вошёл в портал, те же методы доступны из вкладки через `BX.rest.callMethod` (права — этого пользователя). Значения форм, вебхуков и токенов из вкладки целиком не выгружайте.
## Сбои
- `insufficient_scope`: нужен другой скоуп, не повторяй запрос.
- `INVALID_CREDENTIALS`, `NO_AUTH_FOUND`: проверь ID пользователя и код вебхука в адресе; у вебхука мог истечь срок.
- `ACCESS_DENIED` «REST is available only on commercial plans»: REST недоступен на текущем тарифе.
- `expired_token`: продли токены приложения и повтори вызов.
- `ERROR_METHOD_NOT_FOUND`: опечатка в методе или нет скоупа.
## Граница публикации
Не публикуй адреса порталов, коды вебхуков, ID пользователей, телефоны, имена, названия кампаний клиента и выгрузки. Публичные примеры и тесты — только синтетические.