Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-07-28.md индекс документации — /llms.txt
Изменения API: 28 июля 2026
← Журнал изменений · Июль 2026
NEW-0728-1: приложение стёртого автора больше не выдаёт новые пользовательские токены
Когда автор приложения удалил свои персональные данные, приложение перестаёт выдавать токены новым пользователям. Раньше такой запрос доходил до Битрикс24 и создавал рабочий токен вместе с именем и почтой нового пользователя, хотя автора в системе уже нет.
Возврат из GET /v1/oauth/callback в этом случае приходит на ваш redirect_uri с ?error=app_unavailable — той же формой, что уже используют token_exchange_failed, invalid_domain и profile_fetch_failed. POST /v1/oauth/placement-session отвечает 403 с кодом APP_UNAVAILABLE — тем же кодом отвечает и обработчик размещения, куда Битрикс24 открывает виджет приложения (раньше там приходил 401 с общим USER_AUTH_REQUIRED, который читался как проблема авторизации пользователя).
Уже выданные токены и сессии этого приложения не продлеваются. Ранее работавшие вызовы не затронуты: пока автор активен, поведение обоих эндпоинтов прежнее.
NEW-0728-2: снятие зависшего лока стало кросс-репличным; ответ DELETE /lock несёт broadcast и localLock
DELETE /v1/infra/servers/:id/lock теперь рассылает снятие лока на все реплики платформы, поэтому снимает зависший лок и тогда, когда он держится на другой реплице (частый случай под горизонтальным масштабированием). Ответ дополнен полями broadcast (снятие разослано по флоту, best-effort) и localLock (держался ли лок на этой реплице). Поле released теперь описывает только текущую реплику и не является подтверждением снятия по всему флоту — при зависшем локе на другой реплице released может быть false, хотя лок реально снят; не опрашивайте эндпоинт в цикле до released: true, повторите операцию. Прежние вызовы работают без изменений (поля добавлены аддитивно). Дополнительно зависший exec-лок теперь гарантированно снимается серверным авто-сбросом вскоре после истечения TTL.
Ответ POST /v1/infra/servers/:id/exec при 502 EXEC_BUSY для galaxy-приложения теперь несёт error.hint с честным путём восстановления (общий exec-канал хоста; эскалация к платформенной команде — DELETE /lock тут не помогает, так как блокирует мьютекс агента). Ответ POST /v1/infra/servers/:id/deploy при 409 GALAXY_APP_BUSY дополнен error.hint, retryable: true, retryAfter и заголовком Retry-After.
NEW-0728-3: указатели на открытые линии, чек-листы задач и ТЗ приложений в ответах самоописания
Ответ GET /v1/guide дополнен указателем data.appBlueprints — ссылка на документацию готовых ТЗ приложений и условие ответа 403 BLUEPRINTS_DISABLED.
Для ключа со скоупом imopenlines в ответ добавлен блок data.openLines: описание раздела, ссылки на все семь страниц документации и разграничение двух групп эндпоинтов. Настройка линий и действия оператора доступны на любом портале. Статистика дашборда до прихода обновления Битрикс24 отвечает 422 METHOD_NOT_YET_AVAILABLE, а без права на просмотр статистики — 403 B24_TARIFF_RESTRICTION.
В ответе GET /v1/me блок api._rules получил три новых указателя — на чек-листы задач, открытые линии и ТЗ приложений.
Поля аддитивные, существующие клиенты не затронуты. Сами эндпоинты не менялись.
FIX-0728-4: деплой в галактику восстанавливает оборванный туннель хоста
Было
Деплой галакси-приложения на хост, туннель которого молча оборвался под нагрузкой сборки (в том числе «фантомно-CONNECTED» хост — флаг завис, а туннель уже мёртв), зацикливался на GALAXY_HOST_UNREACHABLE / GALAXY_DEPLOY_INTERRUPTED: платформа не чинила туннель сама, и повторные попытки клиента били в тот же мёртвый туннель.
Стало
Такой обрыв на пути деплоя теперь запускает фоновый ремонт туннеля хоста, поэтому честный повтор попадает уже на восстановленный туннель и деплой доезжает. Коды ошибок и их «повторяемая» семантика не изменились — меняется только поведение (самовосстановление).
BC-0728-5: единый конверт 404 для несуществующих маршрутов /v1
Поддержка старого формата до: 28.07.2026
Прежняя форма тела не возвращается — переходного периода с двойным форматом нет, изменение действует с даты публикации.
Было
Запрос на несуществующий путь или неподдерживаемый HTTP-глагол под /v1/ отвечал телом веб-сервера вне единого конверта API:
{
"message": "Route GET:/v1/dealz not found",
"error": "Not Found",
"statusCode": 404
}
Стало
Тот же запрос отвечает в едином конверте V1 с новым кодом ROUTE_NOT_FOUND. HTTP-статус прежний — 404:
{
"success": false,
"error": {
"code": "ROUTE_NOT_FOUND",
"message": "Route GET:/v1/dealz not found. Check GET /v1/guide for available endpoints and verbs."
}
}
ROUTE_NOT_FOUND означает «такого маршрута или глагола не существует» — сверьте путь со списком в GET /v1/guide. Не путайте с ENTITY_NOT_FOUND и доменными кодами вида *_NOT_FOUND: там маршрут существует, не найден запрошенный объект. Вне /v1/ форма тела 404 не изменилась.
Что делать интеграторам
Ветвитесь по error.code, а не по форме тела. Клиент, который разбирал поля message, error и statusCode прежнего тела на путях /v1/, должен перейти на единый конверт success и error.code.
BC-0728-6: календарь: неизвестное имя в select отвечает ошибкой, а не пустым объектом
Поддержка старого формата до: 28.07.2026
Было
GET /v1/calendar-events (а также GET /v1/calendar-events/{id}, POST /v1/calendar-events/search и calendar-events-подвызовы POST /v1/batch) при незнакомом имени поля в select (например dateFrom — такого поля нет, реальное имя from) молча возвращали объекты, состоящие из одного id. Клиент считал, что сузил трафик, а на деле терял данные.
Стало
Незнакомое имя поля в select отвечает 400 UNKNOWN_SELECT_FIELD с перечнем допустимых имён (Available: …). Имена в формате Битрикс24 (DATE_FROM) и алиасы дат (updatedAt) по-прежнему принимаются и проецируют канонический ключ — ошибку вызывают только имена, которые не разрешаются ни в одно поле схемы. На остальных сущностях поведение прежнее: незнакомое имя даёт предупреждение в meta.warnings, без ошибки.
Что делать интеграторам
Брать имена полей из GET /v1/calendar-events/fields и убрать из select несуществующие имена (dateFrom/dateTo → from/to). Клиенты, не передающие select или передающие корректные имена, не затронуты.
NEW-0728-7: календарь: поля occurrenceIndex и version
У событий календаря появились два поля только для чтения. occurrenceIndex — порядковый номер вхождения в развёрнутой серии повторяющегося события, с нуля: строки серии делят один id, и пара id + occurrenceIndex однозначно идентифицирует строку набора. version — монотонный счётчик изменений события, растёт при каждом изменении и не зависит от региональных настроек аккаунта. Рецепт диффа: запросите GET /v1/calendar-events с select=id,version, сравните пары со своим снимком и дочитайте изменённые события по id.
NEW-0728-8: чаты: эхо ограничения limit в meta
Три эндпоинта чатов — GET /v1/chats/recent, GET /v1/chats/:dialogId/messages и GET /v1/chats/:dialogId/users — при срезании переданного limit до допустимого диапазона дополняют ответ полем meta с парой requestedLimit и appliedLimit: сколько запросили и сколько применено. Когда limit в диапазоне, meta не добавляется — конверт прежний. Для чтения сообщений задокументирован реальный потолок облачного Битрикс24 — не больше 50 записей за вызов независимо от limit, продолжение читается курсором lastId.
NEW-0728-9: взаимные алиасы полей дат updatedAt и createdAt
Поля дат в каталоге сущностей носят два семейства имён: одни сущности объявляют updatedAt и createdAt, другие — updatedTime и createdTime. Теперь члены пары принимаются на вход взаимозаменяемо: в filter и select — на всех сущностях, где объявлен парный ключ, в sort — на сущностях с camelCase-схемой полей. Например, updatedTime на сущности с полем updatedAt работает как updatedAt, и наоборот. Канонические имена полей в ответах не меняются — алиас действует только на входе.
NEW-0728-10: POST-алиас поиска по Базе знаний
Поиск документов Базы знаний 2.0 принимает и POST /v1/note/documents/search с JSON-телом { "query": "...", "limit": 20 } — для агентов, которые ожидают поиск POST-запросом по аналогии с остальными сущностями. Канонической остаётся форма GET /v1/note/documents/search с query-параметрами. Обе формы принимают только query и limit, при передаче параметра и в теле, и в query приоритет у тела.
NEW-0728-11: лента: limit до 200 записей за запрос
GET /v1/posts принимает limit от 1 до 200. Страница ленты Битрикс24 фиксирована в 50 записей — при limit больше 50 платформа склеивает до четырёх страниц в один ответ. Значение больше 200 отвечает прежним 400 INVALID_LIMIT. В meta добавлено поле returned — фактическое число записей в ответе, а meta.nextOffset при многостраничном чтении выводится из окна ответа, чтобы цепочка страниц продолжалась как раньше.
FIX-0728-12: календарь: честные offset и hasMore, детерминированный порядок
Было
GET /v1/calendar-events при любом offset возвращал начало одного и того же набора: запрошенный диапазон приходит от Битрикс24 одним массивом без пагинации, поэтому каждая «страница» повторяла первую, meta.hasMore оставался true, а хвост набора за пределами первой страницы был недоставаем.
Стало
Полный набор сортируется детерминированно — по началу события from, при равенстве по id, затем по occurrenceIndex — и из него отдаётся честное окно от offset до offset + limit. meta.total — число вхождений в наборе: повторяющиеся события развёрнуты по-вхожденно, строки серии делят один id. meta.hasMore отвечает true только пока за окном остаются записи. Порядок элементов в ответе стал детерминированным и может отличаться от прежнего.
Влияние на интеграторов
Обход набора через offset теперь отдаёт весь диапазон. Клиентам, которые обходили дубли страниц самостоятельно, ничего менять не нужно — дублей больше нет.
FIX-0728-13: select принимает объявленные имена Битрикс24 и предупреждает о незнакомых полях
Было
Параметр select понимал только канонические имена полей из GET /v1/{entity}/fields. Имя в другом написании — исходное имя Битрикс24 (DATE_FROM, UF_DEPARTMENT) или другой регистр — молча выпадало из проекции: поля не было в ответе без какого-либо признака ошибки, а запрос из одних таких имён вырождался в объекты с единственным полем id. Пакетные вызовы select не применяли вовсе: и глобальный POST /v1/batch, и пакетный вызов одной сущности POST /v1/{entity}/batch возвращали полные объекты.
Стало
select принимает канонические имена без учёта регистра, объявленные исходные имена Битрикс24 (DATE_FROM проецирует from, UF_DEPARTMENT — departmentId) и взаимные алиасы полей дат — поле приходит в ответе под каноническим ключом. Незнакомое имя больше не теряется молча: список, поиск и получение записи по id дополняют ответ массивом meta.warnings с записями { "code": "UNKNOWN_SELECT_FIELD", "field": "<имя>" } — до 10 предупреждений на ответ. Оба пакетных вызова применяют select к операциям списка и поиска так же, как одиночные эндпоинты; получение записи по id внутри глобального пакета select не применяет. Глобальный вызов дополнительно отдаёт предупреждения о незнакомых именах в meta по каждому своему вызову. Пакетный вызов одной сущности предупреждений не несёт и жёсткого отклонения незнакомых имён не выполняет — незнакомое имя там по-прежнему просто отсутствует в ответе.
Влияние на интеграторов
Ответы одиночных эндпоинтов только дополняются. В пакетных вызовах клиент, который передавал select и при этом читал поля за его пределами, теперь получит только запрошенные поля — уберите select из вызова или перечислите в нём все нужные поля.
FIX-0728-14: быстрый отказ оконного поиска при таймауте портала
Было
Поиск POST /v1/{entity}/search с широким диапазоном дат разбивается на временные окна. Таймаут Битрикс24 на первом окне пропускался, и остальные окна выполнялись каждое со своим таймаутом: до ответа проходило 60–75 секунд, после чего приходил 503 BITRIX_TIMEOUT. Если поздние окна успевали, возможен был частичный 200 с неполными данными после той же минуты ожидания.
Стало
Таймаут первого окна (BITRIX_TIMEOUT) завершает запрос сразу: ответ 503 с кодом BITRIX_TIMEOUT и заголовком Retry-After приходит примерно за 15 секунд, остальные окна не выполняются. Частичный 200 при таймауте первого окна больше невозможен — это осознанный размен: окна одинаковы по форме, таймаут первого предсказывает таймауты остальных, а частичный ответ после минуты ожидания провоцировал волны повторов. Таймаут любого последующего окна обрабатывается как раньше — окно пропускается, ответ может быть частичным.
Влияние на интеграторов
Повторяйте запрос по заголовку Retry-After. Клиенты, которые полагались на частичный ответ при перегрузке портала, теперь получают быстрый 503 — сузьте диапазон дат или повторите позже.
FIX-0728-15: Galaxy-деплой из .zip: честная причина ошибки извлечения вместо EMPTY_BUILD_CONTEXT
Деплой Galaxy-приложения из .zip теперь возвращает реальную (санитизированную) причину ошибки извлечения архива в buildLog 502-ответа, а не вводящее в заблуждение «EMPTY_BUILD_CONTEXT»/общее сообщение.
FIX-0728-16: отбой лимитера времени операций Битрикс24 возвращается как `OPERATION_TIME_LIMIT` с `Retry-After`
Было
Когда портал отбивал вызов метода, израсходовавшего бюджет рабочего времени, платформа
отдавала 429 RATE_LIMITED с Retry-After: 2, а сам вызов повторяла до трёх раз. Против
адресного отказа на несколько минут эти повторы не помогали, а Retry-After: 2 вводил в
заблуждение: клиент возвращался через две секунды и получал тот же отказ.
Стало
Такой отбой возвращается кодом OPERATION_TIME_LIMIT — тем же, что отдаёт портал, — с
Retry-After, посчитанным от известного срока снятия ограничения, и понятным текстом в
userMessage. Повторы отключены: ограничение адресное — на тройку «портал + ключ +
метод», ровно так же, как его накладывает сам Битрикс24, — и до истечения срока платформа
отбивает вызовы этого метода сама, не обращаясь к порталу. Остальные методы портала, как и
тот же метод под другим ключом, не затронуты. Прочие отказы 429 (в том числе
RATE_LIMITED и QUEUE_OVERFLOW) не изменились.
Соблюдайте Retry-After: раньше срока тот же вызов пройти не может. Тяжёлые чтения стоит
разредить по времени или сузить — меньше полей, меньше страница, POST /v1/batch.
FIX-0728-17: Значение * в select возвращает все поля
Было
Привычная для Битрикс24 запись select: ["*"] (и ["*", "UF_*"]) на одиночных эндпоинтах приводила к обратному результату: * не совпадает ни с одним объявленным полем, поэтому в ответе оставался только id. Признака ошибки не было — запись просто приходила пустой.
Стало
* и UF_* (в любом регистре) распознаются как запрос «вернуть все поля»: отбор полей не применяется, приходит полная запись. Незнакомое имя, переданное рядом со звёздочкой, не отклоняется — ответ дополняется предупреждением UNKNOWN_SELECT_FIELD. Это работает одинаково в списке, поиске, получении записи по id и в обоих пакетных вызовах — POST /v1/batch и POST /v1/{entity}/batch. У событий календаря, где незнакомое имя поля отвечает ошибкой 400, значение * ошибкой не считается.
Влияние на интеграторов
Ничего менять не нужно. Клиент, переносивший запросы из портального кода Битрикс24 вместе с select: ["*"], начнёт получать полные записи вместо объектов с одним id.
FIX-0728-18: оконный поиск останавливается, набрав запрошенное, и сообщает о неполном окне
Было
POST /v1/{entity}/search с широким диапазоном дат разбивает диапазон на временные окна и объединяет их результаты. Обход шёл до конца диапазона даже тогда, когда запрошенных limit записей уже набрано: поиск с limit: 50 по диапазону в несколько месяцев вычитывал весь диапазон целиком — отвечал долго и создавал на аккаунте Битрикс24 нагрузку, несопоставимую с размером ответа. Если внутри одного окна подходящих записей оказывалось больше, чем отдаёт одно чтение окна, окно возвращало только начало своего набора, и делало это молча: ни признака в ответе, ни способа дочитать остаток (оконный поиск отвергает offset > 0 кодом UNSTABLE_OFFSET_PAGINATION).
Молчала и вторая причина неполноты, на аккаунтах, где окна читаются пакетами: набрав предельные 5000 записей, поиск перестаёт отправлять оставшиеся окна и отдаёт срезанный префикс — в ответе об этом тоже ничего не было.
Стало
Обход окон прерывается, как только набрано больше уникальных записей, чем запрошено в limit. В ответе по-прежнему не больше limit записей, а признак «есть ещё» несёт hasMore. При досрочной остановке meta.total равен количеству набранного, то есть это нижняя оценка числа подходящих записей, а не полный счёт по диапазону — ровно так уже вёл себя этот поиск на аккаунтах с пакетным чтением окон, теперь поведение единое.
Неполная выдача больше не молчит — ни по одной из двух причин, независимо от того, читаются окна по одному или пакетами, на сущностях, чей метод списка Битрикс24 отдаёт постранично. Ответ дополняется предупреждением { "code": "WINDOW_TRUNCATED", "field": "…", "message": "…" } в массиве meta.warnings, где field — поле диапазона, по которому шло разбиение. Код предупреждения один и тот же в обоих случаях — ветвиться по нему можно, не разбирая текст; message называет сработавшую причину: одно окно держало больше записей, чем отдаёт одно чтение окна, либо набраны предельные 5000 записей и оставшиеся окна не отправлялись.
Исключения названы прямо. Три сущности предупреждения не получат никогда, потому что их метод списка Битрикс24 не отдаёт постранично: файлы и папки (/v1/files, /v1/folders) и рабочие группы (/v1/workgroups). Там запрос идёт одиночным вызовом, limit в Битрикс24 не передаётся вовсе, и аккаунт отдаёт свою страницу примерно на 50 записей: окно, в котором лежит 200 дисковых объектов, вернёт 50 и промолчит, как и до правки. У страниц (/v1/pages), сайтов (/v1/sites) и событий календаря (/v1/calendar-events) метод списка тоже не постраничный, но он отдаёт весь запрошенный набор за один вызов — там предупреждение просто недостижимо, а неполноты не возникает.
Дополнительно снижена нагрузка, которую этот поиск создаёт на аккаунте Битрикс24: вырожденная нижняя граница по id больше не уходит в Битрикс24. Снимаются две формы, и опираются они на разное. >= со значением 0 или меньше и > с отрицательным значением исключают только отрицательные id — они тавтологичны при одном допущении неотрицательности. > ровно с нулём (filter[>id]=0 — именно её передают в начале обхода курсором) исключает запись с id = 0, то есть дополнительно опирается на автоинкрементную нумерацию записей Битрикс24 от единицы; это целевой случай правки, и он снимается сознательно. Граница >=id=1 сохраняется — гард намеренно узкий и смотрит только на значения 0 и меньше.
Состав выдачи не меняется ни на одной сущности, где Битрикс24 действительно применяет фильтр по id. Известное исключение — воронки (/v1/categories): среди них есть запись с id: 0 («Общая»), но метод списка воронок игнорирует filter целиком, поэтому и до, и после правки в ответ приходит полный набор воронок. Форма ответа прежняя.
Влияние на интеграторов
Не считайте meta.total точным числом подходящих записей на широком диапазоне дат — при досрочной остановке это нижняя оценка; ориентируйтесь на hasMore. Дочитать оконный поиск постранично нельзя (offset > 0 отвергается), поэтому «есть ещё» закрывается либо большим limit (до 5000), либо более узким диапазоном дат.
Проверяйте meta.warnings на WINDOW_TRUNCATED: это признак неполной выдачи, и пагинацией он тоже не лечится — сузьте диапазон дат или добавьте фильтров, чтобы поиск перестал упираться в потолок. Одного hasMore для этого недостаточно: оконное разбиение работает только при offset === 0, поэтому запрос следующей страницы уйдёт уже не оконным и даст другой результат. Поиск по узкому диапазону, который не разбивается на окна, не затронут.
Учтите границу оконного поиска: сортировка применяется внутри окна, а не поверх объединения окон. Окна строятся от старых к новым и склеиваются в этом же порядке, после чего результат режется до limit; глобальной сортировки по объединению нет. Поэтому запрос с сортировкой по убыванию и небольшим limit по широкому диапазону дат возвращает самые СТАРЫЕ подходящие записи, а не самые новые. Само поведение не новое, но досрочная остановка закрывает сортировку после слияния как способ починки (записи поздних окон больше не вычитываются), поэтому называем это прямо. Нужен настоящий «последние N по дате» — либо сузьте диапазон так, чтобы разбиение на окна не включалось, либо возьмите диапазон одним запросом с большим limit и отсортируйте на своей стороне.