Обработчики событий (event handlers) в Битрикс24: практика
Как подписаться на события Битрикс24 через REST API, обработать их на своём сервере и избежать типовых ошибок с повторной доставкой.
Обработчики событий (event handlers) — механизм, который позволяет вашему сервису узнавать об изменениях в Битрикс24 без постоянного опроса методом list. Портал сам присылает POST-запрос на ваш URL при создании сделки, смене стадии, добавлении контакта — если вы заранее подписались на нужное событие. На практике именно здесь возникает больше всего продакшен-инцидентов: дублирующиеся уведомления, устаревшие данные в теле события, потерянные вызовы при недоступности вашего сервера. Разберём, как построить обработку событий, которая переживёт реальную нагрузку.
Подписка на событие: event.bind
Подписка регистрируется вызовом event.bind с тремя параметрами: event (код события, например ONCRMDEALADD), handler (URL вашего обработчика) и event_type (online — для мгновенной доставки, offline — для сущностей, которые обрабатываются асинхронно на стороне Битрикс24). Один обработчик может быть подписан на множество событий, для каждого делается отдельный вызов event.bind — привязки не группируются в один запрос.
POST /rest/1/xxxxxxxxxxxxxxxx/event.bind.json
{
"event": "ONCRMDEALUPDATE",
"handler": "https://yourservice.example.com/hooks/deal-update",
"event_type": "online"
}
// Просмотр текущих подписок:
// GET /rest/1/xxxxxxxxxxxxxxxx/event.get.jsonЧто реально приходит в теле события
Классическая ошибка новичка — ожидать в теле события полный набор изменённых полей. На самом деле в POST-запросе на handler приходит только data[FIELDS][ID] (идентификатор изменённой записи) и ts (метка времени события), но не сами значения полей и тем более не то, какие именно поля изменились. Чтобы получить актуальное состояние, обработчик обязан сделать отдельный REST-вызов (crm.deal.get с этим ID) после получения события — то есть событие работает как триггер «что-то произошло с записью N», а не как push актуальных данных.
POST /hooks/deal-update (тело входящего события)
event=ONCRMDEALUPDATE
&data[FIELDS][ID]=1042
&ts=1736500000
&auth[domain]=your-portal.bitrix24.ru
&auth[member_id]=abc123def456
&auth[access_token]=a1b2c3...Гонка между событием и актуальным состоянием
Между моментом отправки события и моментом, когда ваш обработчик успевает вызвать crm.deal.get, запись может измениться ещё раз — например, если пользователь быстро кликает по стадиям воронки. Это значит, что при высокой частоте изменений одной и той же записи обработчик событий не гарантирует, что вы увидите каждое промежуточное состояние: вы всегда получаете актуальное на момент запроса состояние, а не последовательность всех изменений. Если бизнес-логике критична каждая промежуточная стадия (например, для аналитики времени прохождения воронки), полагаться только на события недостаточно — нужен дополнительный лог изменений на стороне Битрикс24 (история изменений полей через отдельный функционал) или собственное версионирование на своей стороне при каждом полученном событии.
Дублирование событий и идемпотентность
Битрикс24 не гарантирует доставку события ровно один раз — при сетевых проблемах или таймауте вашего сервера событие может быть отправлено повторно. Обработчик обязан быть идемпотентным: повторная обработка одного и того же события (тот же ID записи, близкий ts) не должна приводить к дублированию побочных эффектов — повторной отправке письма клиенту, повторному списанию оплаты во внешней системе. Практический приём — хранить в своей БД пары (event, ID записи, ts с округлением до секунды) и пропускать обработку, если такая же комбинация уже была обработана в последние несколько минут.
- ONCRMDEALADD / ONCRMDEALUPDATE / ONCRMDEALDELETE — события по сделкам
- ONCRMCONTACTADD / ONCRMCONTACTUPDATE — по контактам
- ONCRMLEADADD / ONCRMLEADUPDATE — по лидам
- ONTASKADD / ONTASKUPDATE — по задачам
- ONIMBOTMESSAGEADD — входящее сообщение боту в чате
- ONAPPINSTALL / ONAPPUNINSTALL — установка и удаление приложения (не привязывается через event.bind, обрабатывается отдельно на Handler приложения)
Обработка недоступности вашего сервера
Если ваш сервер не отвечает на событие (таймаут, 500-я ошибка), Битрикс24 предпринимает ограниченное количество повторных попыток с интервалами, после чего просто перестаёт присылать конкретное событие — без предупреждения на портале, без уведомления администратора. Это значит, что длительный простой вашего сервиса (например, плановые работы дольше пары часов) приводит к тихой потере части событий, произошедших в этот период. Компенсируйте это периодической полной сверкой: раз в сутки или чаще запускайте фоновую задачу, которая через *.list с фильтром по дате изменения находит записи, изменённые за последние N часов, и сверяет их с тем, что реально обработано у вас.
- 1.Зарегистрируйте event.bind на все нужные события при установке приложения
- 2.В обработчике сразу проверяйте идемпотентность по (event, ID, округлённый ts)
- 3.Дозапрашивайте актуальное состояние записи, не доверяя составу данных в самом событии
- 4.Обрабатывайте событие асинхронно в очереди, отвечая порталу 200 OK немедленно, чтобы не словить таймаут на стороне Битрикс24
- 5.Раз в сутки запускайте сверку через *.list по дате изменения, чтобы поймать пропущенные события
Правило дозапроса состояния. Никогда не считайте данные, пришедшие в теле события, актуальными или полными — они таковыми не являются по дизайну API. Событие — это лишь триггер «посмотри на запись N», реальное состояние всегда нужно получать отдельным REST-вызовом непосредственно перед обработкой.
Отписка и управление подписками
Метод event.unbind снимает подписку по event и handler. Это критично вызывать в обработчике деинсталляции приложения — иначе Битрикс24 продолжит слать события на URL, который больше не обслуживается вашим сервисом, что для портала выглядит как постоянные неудачные попытки доставки в логах системы (хотя видимого для пользователя эффекта это не даёт). При смене адреса вашего обработчика (миграция инфраструктуры, смена домена) не забывайте перепривязать событие через unbind + новый bind, а не полагаться на автоматическое обновление.
Событие Битрикс24 — это не поток данных, а колокольчик: он говорит «что-то случилось», но что именно — нужно спросить отдельно.
Курс школы: Вебхуки в Битрикс24 без программирования — от 9 990 ₽
Асинхронные (offline) события и их особенности
Для part событий доступен режим event_type=offline: вместо мгновенной доставки Битрикс24 копит события и обрабатывает их по расписанию (обычно раз в несколько минут), что снижает нагрузку на инфраструктуру портала при массовых операциях (например, при импорте тысяч контактов). Такой режим подходит для интеграций, не требующих реального времени — например, для ночной синхронизации каталога. У offline-событий выше задержка, но ниже риск потери событий при кратковременной недоступности вашего сервера, потому что доставка растянута во времени, а не происходит одним залпом сразу.
Множественные обработчики на одно событие
Если у вас несколько логических подсистем, которым нужно реагировать на одно и то же событие (например, на ONCRMDEALUPDATE должны реагировать модуль уведомлений и модуль синхронизации с 1С), не пытайтесь регистрировать два разных event.bind на один event с разными handler в рамках одного приложения — это усложняет управление подписками и увеличивает число исходящих HTTP-запросов с портала при каждом изменении. Правильнее подписать один внутренний обработчик, который разбирает событие и рассылает его дальше внутренними средствами (очередь сообщений, шина событий) внутри вашей собственной инфраструктуры.
Фильтрация лишних срабатываний
Событие ONCRMDEALUPDATE срабатывает при изменении любого поля сделки, включая технические — например, при автоматическом пересчёте даты последней активности или при смене ответственного роботом БП. Если ваша интеграция должна реагировать только на конкретное изменение (скажем, только на переход в определённую стадию), фильтрация происходит не на уровне подписки — Битрикс24 не даёт подписаться на «изменение конкретного поля», только на событие целиком — а полностью на вашей стороне, после дозапроса актуального состояния и сравнения его со значением, сохранённым при предыдущей обработке этой же записи. Без такого сравнения обработчик будет выполнять полную бизнес-логику при любом чихе в карточке, что и дорого по нагрузке, и рискованно с точки зрения побочных эффектов.
Обработка событий в высоконагруженных порталах
На крупных порталах с сотнями активных пользователей события могут приходить пачками — например, при массовом импорте тысяч лидов маркетинговой кампанией все эти ONCRMLEADADD прилетают на ваш handler практически одновременно. Синхронная обработка каждого события в момент HTTP-запроса от портала быстро упирается в лимиты вашего собственного сервера и создаёт очередь необработанных HTTP-соединений. Правильная архитектура — handler максимально быстро (в первые сотни миллисекунд) складывает событие в очередь (Redis, RabbitMQ, SQS — что угодно персистентное) и отвечает порталу 200 OK, а фактическая бизнес-логика обрабатывается воркерами асинхронно, с собственным контролем скорости и повторов.
Тестирование обработчиков на песочнице
Проверить обработчик событий локально без реального портала сложно — Битрикс24 не даёт «отправить тестовое событие вручную» через интерфейс. Практический приём — создать тестовый портал, зарегистрировать event.bind на тестовое приложение с адресом временного туннеля (ngrok или аналог) к локальной машине, и вручную создавать/изменять записи CRM на этом портале, наблюдая за входящими запросами в логах туннеля. Это единственный надёжный способ увидеть реальный формат данных, а не полагаться на документацию, которая местами описывает структуру события неполно.
Порядок доставки и отсутствие гарантии очерёдности
Ещё одно предположение, которое обязательно подведёт: события приходят не строго в том порядке, в котором произошли изменения. Если пользователь быстро меняет стадию сделки дважды подряд, обработчик может получить оба события с небольшой задержкой в произвольном порядке относительно друг друга — особенно при масштабировании вашего сервиса на несколько инстансов, читающих из общей очереди. Единственный надёжный способ определить актуальное состояние — не полагаться на порядок событий, а всегда ориентироваться на данные, полученные дозапросом *.get в момент обработки, они отражают текущее состояние независимо от того, в каком порядке к вам пришли уведомления.
Что изучить дальше
Вебхуки в Битрикс24 без программирования
Заявка с сайта сама создаёт сделку, а данные из Битрикс24 уходят во внешний сервис — без программиста. 16 коротких уроков с готовыми шаблонами запросов, 4 практических задания и защита ключей.