Обсудить задачу

Бронирование ресурсов в Битрикс24: как создать бронь через REST

В Битрикс24 два разных механизма бронирования с почти одинаковыми названиями. Из-за этого попытка создать бронь для сделки заканчивается ошибкой «Some resources were not found», а метод, который напрашивается по логике, в списке REST просто отсутствует. Разбираем, где проходит граница и как записать бронь в поле сделки.

Почему booking.v1.booking.add отвечает «Some resources were not found»?

Потому что вы передаёте в него идентификатор ресурса из другой подсистемы. В портале есть два независимых механизма бронирования, и реестры ресурсов у них разные. Метод ищет ваш ID в своём реестре, не находит и возвращает ошибку — хотя ресурс на портале есть и в интерфейсе виден.

Бронирование ресурсовБронирование и онлайн-запись
Модульcalendarbooking
Ресурсыcalendar.resource.*booking.v1.resource.*
Брониcalendar.resource.booking.list — только чтениеbooking.v1.booking.* — полный набор
Связь с CRMполе сделки или лида типа resourcebookingbooking.v1.booking.externalData.*

Реестры не пересекаются. Новый модуль бронирования не заполняет пользовательское поле сделки, а старый ничего не знает про ресурсы нового. Выбор механизма — это выбор один раз и навсегда.

Каким методом создать бронь, если calendar.resource.booking.add не существует?

Никаким: отдельного метода создания нет и не планировалось. В этой подсистеме бронь — побочный эффект сохранения пользовательского поля. Вы обновляете сделку методом crm.deal.update, а обработчик типа поля сам создаёт событие календаря и запись в реестре броней.

Поэтому единственный рабочий путь — записать значение в поле типа resourcebooking. Найти такое поле у сделок можно через crm.deal.userfield.list с фильтром по USER_TYPE_ID, список ресурсов и их идентификаторы — через calendar.resource.list.

В каком формате передавать значение в поле?

Поле множественное, каждый элемент — строка из пяти частей, разделённых вертикальной чертой.

BashФормат одного значения
тип|ID|дата_начала|длительность_в_секундах|название_услуги

resource|586|10.09.2026 15:00:00|3600|Консультация
  • тип — resource для ресурса из календаря или user для брони времени сотрудника
  • ID — идентификатор ресурса либо идентификатор пользователя портала
  • дата начала — в формате сайта, то есть 10.09.2026 15:00:00
  • длительность — в секундах: 3600 равно часу
  • название услуги — необязательно, попадёт в описание события строкой «Услуга: …»
BashСоздание брони через обновление сделки
curl -X POST -H "Content-Type: application/json" \
  -d '{
        "id": 1234,
        "fields": {
          "UF_CRM_1712345678": [
            "resource|586|10.09.2026 15:00:00|3600|Консультация"
          ]
        }
      }' \
  https://portal.bitrix24.ru/rest/1/WEBHOOK/crm.deal.update

Почему в поле лежит [5], а не то, что вы отправили?

Потому что при сохранении строка разбирается и заменяется. Обработчик поля создаёт событие календаря, добавляет строку в реестр броней и кладёт в поле идентификатор этой строки. То, что вы прочитаете через crm.deal.get, — не ваши данные, а ссылка на созданную бронь.

По этому же идентификатору бронь потом читается. В фильтре метода чтения два взаимоисключающих ключа: resourceIdList — это значения из поля сделки, resourceTypeIdList — идентификаторы самих ресурсов. Передать оба сразу нельзя.

BashДва режима calendar.resource.booking.list
# читаем бронь по значению из поля сделки
{"filter": {"resourceIdList": [5], "from": "2026-09-01", "to": "2026-09-30"}}

# читаем всю загрузку ресурса за период
{"filter": {"resourceTypeIdList": [586], "from": "2026-09-01", "to": "2026-09-30"}}

Как обновить или снять бронь, не потеряв остальные?

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

  • Чтобы снять все брони — передайте в поле пустой массив
  • Чтобы добавить бронь, сохранив прежние, — передайте прежние числовыми идентификаторами вместе с новой строкой
  • Чтобы сдвинуть время существующей брони — передайте её заново полной строкой с новыми датой и длительностью
BashДобавление брони без потери существующей
# 5 — уже существующая бронь, её оставляем как есть;
# вторым элементом добавляем новую
"UF_CRM_1712345678": ["5", "resource|590|11.09.2026 09:00:00|1800|Осмотр"]

На чём это ломается в реальной интеграции?

На трёх вещах, ни одна из которых не видна из справки REST.

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

Режим «весь день» меняет смысл длительности. Если у поля включена соответствующая настройка, время в дате игнорируется, а длительность считается сутками — та же строка даст совсем другую бронь.

Пересечения не проверяются. В коде обработчика есть метод с говорящим названием, который должен проверять доступность ресурса, — и он пустой. При сохранении он не вызывается ни разу. Портал спокойно поставит две брони на один ресурс и одно время, если вы этого не проверите сами.

Практический вывод: перед записью брони запрашивайте занятость ресурса за нужный период и решайте конфликт на своей стороне. Рассчитывать на то, что портал откажет, нельзя.

Что выбрать, если бронирование только внедряется?

Если бронь должна жить внутри сделки и быть её полем — берите механизм на календаре: он собран именно вокруг карточки CRM, но управляется только через сохранение поля и почти не документирован.

Если нужен полноценный API с созданием, изменением, удалением и листом ожидания — берите модуль бронирования. Тогда ресурсы заводятся в нём заново, а сделка привязывается отдельным методом. Поле resourcebooking в карточке при этом останется пустым: это два параллельных мира, и смешать их не получится.

Интеграция упирается в недокументированное поведение

Мы читаем исходники модулей портала, а не только справку REST: находим фактический формат данных и делаем интеграцию, которая не разваливается на первом же нестандартном поле.

Посмотреть услугу: Битрикс24 Обсудить задачу