# Изменения API: 24 сентября 2026

[← Журнал изменений](/docs/changelog) · [Сентябрь 2026](/docs/changelog/2026-09)

### NEW-0924-2: Признак множественности у полей портала в описании полей сущности

В ответе `GET /v1/{entity}/fields` (например, `GET /v1/deals/fields`) у поля, которое пришло с портала, появился ключ `multiple: true`, если Битрикс24 сообщает, что поле принимает несколько значений, — например, у множественного пользовательского поля `ufCrm_*`. Значение такого поля при создании и изменении записи передавайте массивом. Отсутствие ключа `multiple` не означает, что поле одиночное: признак не выводится у полей, которые платформа описывает сама, и у полей, для которых портал множественность не сообщил.

### BC-0924-3: Сортировка документов CRM принимает только один уровень скобок

> Поддержка старого формата до: не предусмотрена

**Было**

[GET /v1/crm-documents](/docs/entities/documents/crm-list) принимал под именем поля сортировки второй уровень скобок. Написания `order[updateTime][]=desc` и `order[updateTime][0]=desc` отвечали HTTP 200 и сортировали выдачу так, будто передано `order[updateTime]=desc` — то есть за вызывающего досочинялась сортировка, которой он не писал. Написание `order[updateTime][x]=desc` отвечало HTTP 500.

**Стало**

Запись сортировки обязана нести направление, а не структуру. Второй уровень скобок под именем поля — `order[updateTime][x]=desc`, `order[updateTime][]=desc`, `order[updateTime][0]=desc` — возвращает HTTP 400 `INVALID_ORDER` до обращения к Битрикс24. Одноуровневое написание `order[updateTime]=desc` и регистр направления работают как прежде. Неизвестное направление по-прежнему отбрасывается без отказа, а написание, которое разбору не поддаётся вовсе — `order=desc`, `order[]=desc`, третий уровень скобок, — по-прежнему оставляет выдачу без сортировки.

**Что делать интеграторам**

Передавайте сортировку одним уровнем скобок: `order[updateTime]=desc`. Если строка запроса собирается из массива или индексированного списка, приведите её к этому виду: прежние написания `order[updateTime][]=desc` и `order[updateTime][0]=desc` теперь отказываются, а не сортируют.

### FIX-0924-5: суточная норма вызовов считается по закрытым часам

**Было**

Заголовки `X-RateLimit-Used` и `X-RateLimit-Remaining` были описаны как учитывающие и вызовы текущего часа — с точностью до минуты.

**Стало**

Оба заголовка считают израсходованное за сегодня по закрытым часам: вызовы текущего часа попадают в счёт после его окончания, поэтому заголовки отстают от факта до 70 минут и в начале часа могут не показывать уже сделанные вызовы. Размер суточной нормы, заголовок `X-RateLimit-Quota` и код отказа `QUOTA_EXCEEDED` не менялись, вызов в пределах нормы по-прежнему отвечает HTTP 200. Клиенту менять ничего не нужно; если остаток нужен точно, учитывайте собственные вызовы текущего часа на своей стороне.

### FIX-0924-6: справочник агрегации в GET /v1/guide описывает POST-агрегацию и поля числовых функций по типу

**Было**

Блок `operations.aggregate` в [GET /v1/guide](/docs/keys-auth/guide) описывал устаревший `GET …/aggregate` с параметрами `op` и `field` и называл `aggregatableFields` источником поля для `sum`/`avg`/`min`/`max`. Для элементов смарт-процессов (`/v1/items/:entityTypeId`) он указывал путь `GET /v1/items/:entityTypeId/aggregate`, которого нет. Сообщение `400 INVALID_PARAMS` о неизвестном поле в `POST …/aggregate` перечисляло тот же список `aggregatableFields` вместо числовых полей.

**Стало**

`operations.aggregate` описывает `POST …/aggregate` с массивом `aggregate[]`. Поле для `sum`/`avg`/`min`/`max` — любое поле с типом `number` из `…/fields` или числовое пользовательское поле там, где сущность их поддерживает (есть ключ `ufSupport`). `aggregatableFields` — поля для `groupBy`. Сообщение `400 INVALID_PARAMS` перечисляет числовые поля сущности, а у сущности без числовых полей говорит `This entity declares no number-typed field.`. У сущностей, где пользовательских полей нет, ключа `ufSupport` больше нет, и справочник с `openapi.json` их не обещает. Ответ `GET /v1/guide` по-прежнему HTTP 200, код и статус ошибки агрегации прежние.

**Влияние на интеграторов**

Если клиент читал из справочника `params.op` и `params.field`, переходите на `params.aggregate` и вызывайте `POST …/aggregate`. Вызовы устаревшего `GET …/aggregate` продолжают работать как раньше.

### NEW-0924-7: расписание, на котором рождаются новые машины

Администратор аккаунта Битрикс24 может отметить расписание работы, на котором рождаются новые машины: [PUT /v1/work-schedules/:id/default](/docs/infra/work-schedules/set-default) с телом `{"audience": "machines", "enabled": true}`. Отметок две: `machines` — для серверов и приложений в галактике, `agents` — для агентов и ботов. Вторая отдельная, потому что агент на расписании вне окна спит и не отвечает на сообщения до начала следующего окна. У каждой стороны отмечено не больше одного расписания: новая отметка переезжает с прежнего, `"enabled": false` её снимает.

Сервер, созданный через [POST /v1/infra/servers](/docs/infra/servers/create) без `runMode`, рождается на отмеченном расписании. Явный `runMode`, включая `IDLE`, по-прежнему сильнее отметки, а уже созданные машины свой режим не меняют.

В каждой строке библиотеки [GET /v1/work-schedules](/docs/infra/work-schedules/list) появились поля `defaultForNewMachines` и `defaultForNewAgents`. Отметку меняет только администратор, остальные получают `403 ADMIN_ONLY`.

### FIX-0924-8: режим работы, названный при создании, доезжает до приложения в галактике

**Было**

[POST /v1/infra/servers](/docs/infra/servers/create) принимал блок `runMode`, но когда машина размещалась в галактике, блок молча выбрасывался: приложение рождалось в режиме по умолчанию. Расписание, которого в аккаунте нет, в этом случае тоже не отвергалось.

**Стало**

Блок `runMode` применяется и к приложению в галактике. Ненайденное или пустое расписание отвергается до создания, как и у отдельного сервера: `400 WORK_SCHEDULE_NOT_FOUND` или `400 WORK_SCHEDULE_EMPTY`, приложение при этом не создаётся.

**Влияние на интеграторов**

Интеграция, которая передаёт `runMode`, получает названный режим без отдельного вызова `PATCH /v1/infra/servers/:id/run-mode`. Расписание, которого нет, теперь отвергается и при размещении в галактике, как документация и обещала.

### FIX-0924-9: агрегация отвечает об ошибке портала так же, как список

**Было**

`POST /v1/{entity}/aggregate` и устаревший `GET /v1/{entity}/aggregate` отдавали отказ
Битрикс24 без пояснений, привязанных к вызванному методу: тело ошибки приходило без поля
`hint` с известным ограничением метода и без поля `warning` о том, что та же ошибка уже
повторялась. Список и поиск по той же сущности на тот же отказ отвечали с этими полями.
Из-за этого один и тот же отказ портала выглядел у клиента по-разному в зависимости от того,
какой адрес его вызвал.

**Стало**

Обе двери агрегации отвечают об одной причине тем же кодом и с теми же пояснениями, что
`GET /v1/{entity}` и `POST /v1/{entity}/search`. В теле ошибки появляются `hint` с известным
ограничением вызванного метода Битрикс24 и `warning`, когда отказ повторяется. Успешные
ответы агрегации не изменились, коды успешных ответов прежние.

### NEW-0924-10: новый код отказа `agent_turn_loop_detected` для зациклившегося хода агента

[POST /v1/chat/completions](/docs/ai/chat/completions) получил код отказа `agent_turn_loop_detected` (409) для зациклившегося хода агента. **Сейчас отказ не действует**: такие запросы обслуживаются как прежде, код ничего не меняет в работе существующих интеграций. О включении отказа будет объявлено отдельной записью типа BC с датой.

Условие отказа после включения: в `messages` после последнего сообщения с ролью `user` накопилось 15 и более ответов модели с ролью `assistant` без `tool_calls`. Считаются все такие ответы после последнего сообщения `user`, а не только идущие подряд: вызовы инструментов между ними счёт не сбрасывают. Сами ответы с `tool_calls` в счёт не входят, поэтому ход, в котором модель на каждом шаге вызывает инструменты, условие не задевает. Обращение к модели по такому запросу не выполняется, и петля не расходует лимит. Чтобы продолжить, отправьте новое сообщение пользователя — счёт начинается заново.

### FIX-0924-11: пустой `fields` в теле бот-запроса больше не съедает плоские поля

**Было**

Тело `{"fields": [], "command": "help", "title": "Help"}` — так сериализуется пустой словарь,
например в PHP через `json_encode([])` — принималось за формат Битрикс24 и уходило в портал как
`fields: []`. Присланные `command` и `title` терялись молча, без предупреждения в ответе. То же
на `PATCH /v1/bots/{botId}` и `PATCH /v1/bots/{botId}/chats/{dialogId}`, причём там пустую обёртку
изображали ещё и `null`, `false`, `0` и пустая строка: запрос уезжал в портал как есть, портал
отвечал `200`, и ничего не менялось.

**Стало**

Пустая обёртка `fields` обёрткой не считается — тело читается как плоское и доезжает до портала
целиком. Затронуты `POST /v1/bots/{botId}/commands`, `PATCH /v1/bots/{botId}/commands/{commandId}`,
`PATCH /v1/bots/{botId}` и
`PATCH /v1/bots/{botId}/chats/{dialogId}`. Непустая обёртка по-прежнему передаётся без изменений.
Два следствия: ключ `fields` больше не попадает в `warning.droppedFields`, а неизвестный ключ
верхнего уровня при разворачивании отбрасывается — до портала он всё равно не доезжал.

### NEW-0924-12: отказ в создании приложения из Коворка говорит, откроет ли дверь пробный период Маркета

Отказ [`POST /v1/cowork/applications`](/docs/cowork/applications-create) «подписки нет» у аккаунта подписочной модели — `402 MARKETPLACE_REQUIRED` — теперь несёт необязательное поле `error.details.activation`. Это блок той же формы, что `activation` в [`GET /v1/cowork/state`](/docs/cowork/state), но посчитанный для этой двери: `marketTrial.available: true` значит, что одноразовый пробный период Маркета откроет создание приложений. Включается он прежней ручкой `POST /v1/cowork/activate-market-trial` с явным подтверждением человека.

Значения `not_required_for_data` здесь не бывает: для чтения данных подписка не нужна, а для создания приложений — нужна. Аккаунту на бесплатном тарифе Битрикс24 пробный период не предлагается: REST там недоступен, и период сгорел бы впустую. У аккаунта тарифной модели доступа поля нет: пробный период Маркета ему доступа не откроет, а путь покупки тарифа в теле отказа уже есть. Другие отказы этой двери поля не несут: пробный период снимает только отсутствие подписки, а подписку, которую не удалось прочитать, лечит переподключение приложения под главным администратором. Поля нет и тогда, когда строку аккаунта прочитать не удалось; остальное тело отказа не меняется.

### FIX-0924-14: Запрос событий бота с явным offset ниже сохранённого больше не сдвигает курсор

**Было**

[GET /v1/bots/{botId}/events](/docs/bots/events/polling) с явным `offset` ниже сохранённой позиции (например, `offset=0` для отладки) сдвигал сохранённый курсор, если в ответе были события. Следующий обычный запрос без `offset` уходил с новой позицией, Битрикс24 удалял отданные отладочному запросу события как подтверждённые, и основной цикл бота их не получал.

**Стало**

Явный `offset` ниже сохранённой позиции возвращает события, но курсор не сдвигает, и в ответе приходит `persisted: false`. Явный `offset`, равный сохранённой позиции или больше неё, сдвигает курсор как раньше. Подтверждённые события Битрикс24 удаляет, поэтому `offset=0` показывает только события, ещё не подтверждённые в очереди, а не всю историю.

**Влияние на интеграторов**

Менять ничего не нужно. Отладочный запрос с `offset=0` больше не отнимает события у основного цикла, листание по `nextOffset` работает как раньше.

### NEW-0924-15: resubscribe сообщает режим событий на стороне Битрикс24

Бот в режиме `fetch` получает события, только пока такой же режим стоит у него на стороне
Битрикс24. Это значение авторитетное, и оно может разойтись с тем, что хранит платформа
Вайбкод, — тогда опрос [GET /v1/bots/{botId}/events](/docs/bots/events/polling) успешен,
ошибок нет, а очередь остаётся пустой сколько угодно долго.

Ответ [POST /v1/bots/{botId}/resubscribe](/docs/bots/management/resubscribe) теперь несёт
три новых поля. `b24EventMode` — режим, который Битрикс24 держал ДО вызова (`null`, если
портал его не сообщил). `diverged` — расходился ли он с полем `eventMode`, которое хранит
платформа. `hint` — что вызов сделал на самом деле и что проверять дальше.

Различать это важно: Битрикс24 перепривязывает события только при РЕАЛЬНОЙ смене режима.
Если режимы уже совпадали, вызов ничего не перепривязал, и прежний ответ
`{ resubscribed: true }` читался как выполненное восстановление. Теперь такой случай назван
прямо, а причину пустой очереди подсказка предлагает искать выше очереди — в составе
участников чата и в том, упоминают ли бота, если он отвечает только на упоминания.

Подсказка в ответе `GET /v1/bots/{botId}/events` после серии пустых опросов переписана по
тому же разбору: она помечает `eventMode` как значение платформы и отправляет за
авторитетным в `resubscribe`.

### NEW-0924-16: вход в задеплоенное приложение по ключу десктопа Коворка

Новый эндпоинт `POST /v1/cowork/app-login` принимает адрес задеплоенного приложения и возвращает тот же адрес с добавленным параметром `__gw_token` и сроком его жизни `expiresIn`. Встроенный браузер Cowork/Code, открыв такой адрес, входит в приложение от имени владельца ключа, с его номером пользователя в Битрикс24, без формы авторизации. Токен открывает только это приложение. Эндпоинт принимает только ключ десктопа Cowork/Code со скоупом `vibe:cowork`. Неточный адрес приложения отклоняется кодом `400 INVALID_APP_URL`, любой исход проверки доступа — единым кодом `404 APP_NOT_AVAILABLE`, неизвестный номер пользователя в Битрикс24 — кодом `409 B24_USER_UNKNOWN`.

### BC-0924-17: методы списков проверяют ключ до чтения тела и без ключа отвечают 401

> Поддержка старого формата до: не предусмотрена

**Было**

На всех методах `/v1/lists/*` ключ проверялся после того, как платформа прочитала и разобрала тело запроса. Поэтому запрос без ключа или с неверным ключом получал ответ о теле, а не о ключе: `400 INVALID_JSON_BODY` на неразобранном JSON и `413 PAYLOAD_TOO_LARGE` на теле больше 1 МБ, например на [POST /v1/lists/:iblockId/elements](/docs/lists/elements/create). Сервер при этом читал тело целиком для любого отправителя.

**Стало**

Ключ проверяется первым, до чтения тела. Запрос без ключа или с неверным ключом на любом методе `/v1/lists/*` получает `401` независимо от размера и содержимого тела, а само тело не читается. Это закрывает возможность заставить сервер читать крупное тело без ключа — условие, при котором запись элемента смогла принять тело до 40 МиБ. Ответы на запросы с корректным ключом не изменились.

**Что делать интеграторам**

Ничего, если ключ передаётся. Если код различает ответы на запрос без ключа или с неверным ключом по кодам `400` или `413`, заменить эту проверку на `401`.

### FIX-0924-18: файл в свойстве элемента списка больше не упирается в 1 МБ

**Было**

Значение свойства типа «Файл» у элемента списка едет в теле запроса как base64, а тело записи элемента было ограничено 1 МБ. Практический потолок одного файла — около 750 КБ: [POST /v1/lists/:iblockId/elements](/docs/lists/elements/create) и [PATCH /v1/lists/:iblockId/elements/:elementId](/docs/lists/elements/update) с файлом крупнее отвечали `413 PAYLOAD_TOO_LARGE`, и запись не выполнялась. Тот же файл в поле сделки или контакта проходил.

**Стало**

Тело создания и обновления элемента списка ограничено 40 МиБ, как у записи сущностей CRM, — это чуть меньше 30 МиБ исходного файла после base64. Остальные методы списков и пакетные вызовы (`POST /v1/batch`) сохраняют прежний потолок 1 МБ, поэтому крупный файл отправляйте одиночным вызовом.

Запись элемента с телом крупнее 1 МБ делит общий лимит одновременно обрабатываемых крупных тел с записью сущностей CRM: когда он занят, приходит `429 LARGE_BODY_BACKEND_BUSY` с заголовком `Retry-After: 5`, запрос не выполнялся, и его нужно повторить.

**Влияние на интеграторов**

Действий не требуется: запрос, который раньше получал `413`, теперь выполняется. Вызов в Битрикс24 ограничен 15 секундами и не повторяется, поэтому файл у самой границы на медленном аккаунте может получить `BITRIX_TIMEOUT` — оставляйте запас.
