Перейти к содержимому
Разработка и REST

Обработчики событий (event handlers) в Битрикс24: практика

14 июня 2026 г.8 минут

Как подписаться на события Битрикс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. 1.Зарегистрируйте event.bind на все нужные события при установке приложения
  2. 2.В обработчике сразу проверяйте идемпотентность по (event, ID, округлённый ts)
  3. 3.Дозапрашивайте актуальное состояние записи, не доверяя составу данных в самом событии
  4. 4.Обрабатывайте событие асинхронно в очереди, отвечая порталу 200 OK немедленно, чтобы не словить таймаут на стороне Битрикс24
  5. 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 практических задания и защита ключей.