# Изменения API: 29 июля 2026

[← Журнал изменений](/docs/changelog) · [Июль 2026](/docs/changelog/2026-07)

### FIX-0729-1: комментарий к задаче больше не отбивается по правам ключа

**Было**

[POST /v1/tasks/:taskId/comments](/docs/entities/task-comments/create) на порталах с новой карточкой задач мог вернуть `403` с сообщением портала «Недостаточно прав доступа: отсутствует необходимый scope» — даже когда у ключа есть право `task`, а соседние вызовы задач в ту же секунду отвечают `200`. Формулировка уводила в тупик: она читалась как «выдайте приложению доступ к задачам», хотя набор прав определяется при выпуске ключа, а не действиями пользователя.

**Стало**

Права на комментарий выдаются ключу в обеих формах, которых требуют старый и новый маршрутизаторы Битрикс24, поэтому вызов проходит. Ключам, выпущенным раньше, набор прав досылается на месте при первом таком отказе, и запрос повторяется — вмешательство не нужно. Если после этого портал всё равно отказывает, ответ `403` теперь прямо называет причину (у вебхука ключа набор прав уже, чем у самого ключа) и подсказывает переиздать ключ — вместо пересказа сообщения портала.

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

Менять ничего не нужно. Клиент, ловивший этот `403` как постоянную ошибку, теперь получает `201`.

### FIX-0729-2: изменение доступа к приложению на общем хосте доезжает до его показа в Битрикс24

**Было**

Для приложения на общем хосте (`kind=GALAXY_APP`), встроенного в интерфейс Битрикс24, изменение списка доступа доезжало до показа не всегда. Пользователь, у которого доступ отозвали, мог продолжать видеть приложение на своём месте встройки — доступ к самому приложению при этом уже был закрыт.

Это касалось смены политики доступа и правки списка через [PATCH /v1/infra/servers/:id/access-policy](/docs/infra/access/access-policy), [POST /v1/infra/servers/:id/access](/docs/infra/access/access-add) и [DELETE /v1/infra/servers/:id/access/:accessId](/docs/infra/access/access-delete).

**Стало**

Изменение доступа отражается на показе: приложение пропадает из интерфейса Битрикс24 у тех, кто доступ потерял, и появляется у тех, кому его выдали.

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

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

### FIX-0729-3: агенты и боты больше не засыпают по простою

**Было**

[PATCH /v1/infra/servers/:id/sleep](/docs/infra/lifecycle/sleep) принимал любое значение `sleepAfterMinutes`, включая серверы, созданные под агента или бота (`createdVia` agent или bot).

**Стало**

Для сервера с `createdVia` agent или bot и ненулевым `sleepAfterMinutes` эндпоинт отвечает `400` с кодом `AGENT_IDLE_SLEEP_FORBIDDEN`. Значение `null` (никогда не засыпать) по-прежнему принимается.

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

Спящий агент или бот перестаёт опрашивать Битрикс24 и не просыпается на новое сообщение, поэтому прежнее значение было нерабочим — менять в рабочем сценарии нечего. Для экономии по расписанию используйте Запланированное пробуждение.

### BC-0729-4: сессия в Authorization должна принадлежать приложению из X-Api-Key

> Поддержка старого формата до: 29.07.2026

**Было**

Сессия (`vibe_session_*`) выписывается одному приложению на одном аккаунте Bitrix24, но при вызове `/v1/*` эта привязка не проверялась. Ключ авторизации приложения B принимал сессию, выписанную приложению A, и запрос выполнялся под правами ключа B — то есть чужая сессия открывала доступ к данным через ключ другого приложения.

**Стало**

`/v1/*` проверяет, что сессия в `Authorization: Bearer` принадлежит тому же приложению и тому же аккаунту Bitrix24, что и ключ в `X-Api-Key`. Несовпадение — `403` с кодом `SESSION_APP_MISMATCH`. Ключ авторизации приложения, у которого приложение отвязано или удалено, сессию больше не принимает. Личных ключей `vibe_api_*` изменение не касается: сессию в `Authorization` они не читают — ни до него, ни после.

Вызовы без `Authorization` (только по ключу) не затронуты. Сессия, предъявленная с ключом своего приложения, работает как раньше.

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

Проверьте, что оба заголовка относятся к одному приложению: `X-Api-Key` — ключ авторизации того приложения, которое выписало сессию через `POST /v1/oauth/token`. Если сервис обслуживает несколько приложений, храните пару «ключ + сессия» вместе и не берите их из разных мест.

Проверка включена с выпуска этого изменения, без переходного периода: она закрывает доступ к данным по чужой сессии. Ошибка `403 SESSION_APP_MISMATCH` описана в справочнике ошибок.

### FIX-0729-5: приложение на личном ключе снова получает X-Vibe-Authorization

**Было**

Приложение, размещённое в Black Hole на личном ключе (`vibe_api_*`), теряло заголовок `X-Vibe-Authorization` примерно через минуту после открытия плейсмента. Первые запросы проходили с сессией, дальше она пропадала и не возвращалась ни через перезагрузку страницы, ни через повторное открытие приложения — только через новое открытие плейсмента, и опять на минуту.

Причина: сессия, которую плейсмент выписывает пользователю, привязана к приложению через его адрес (`appUrl`), а восстанавливалась она только по цепочке «сервер → ключ → приложение». У личного ключа приложения нет, поэтому восстановление отвечало «сервер не найден», и Gateway запоминал этот отказ. `X-Vibe-User-Id` при этом продолжал приходить, поэтому со стороны приложения это выглядело как «пользователь есть, а токена нет».

**Стало**

Когда у ключа-владельца сервера нет приложения, оно ищется по адресу приложения: берутся приложения того же аккаунта Bitrix24, созданные владельцем ключа, чей `appUrl` указывает ровно на этот адрес приложения. Сессия восстанавливается, и заголовок продолжает приходить на всё время жизни сессии.

Приложения на ключе авторизации (`vibe_app_*`) работают как раньше — у них цепочка «сервер → ключ → приложение» есть, и она остаётся главной.

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

Менять ничего не нужно. Если приложение обходило проблему повторным открытием плейсмента или собственным хранением токена — эти костыли можно снять.

### NEW-0729-6: управляющий ключ владельца, аккаунт которого ждёт удаления, получает 503

**Было**

Заморозка аккаунта на время запроса на удаление данных действовала на веб-кабинет и на
обычные ключи приложения, но не на управляющие ключи: владелец с аккаунтом в состоянии
ожидания удаления продолжал выпускать, ротировать и удалять ключи через `/v1/keys`.

**Стало**

Управляющий ключ владельца, аккаунт которого находится в процессе удаления данных,
получает `503` с кодом `ACCOUNT_PENDING_ERASURE` и заголовком `Retry-After: 3600` — так
же, как это давно работает для обычных ключей приложения. Если запрос на удаление
отменён, ключ начинает работать снова без перевыпуска.

### FIX-0729-7: деплой galaxy-приложения проверяет доступность и отдаёт шаги

**Было**

Успешный деплой galaxy-приложения через [POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) возвращал `success: true, status: "running"` без `data.steps[]` и без проверки того, что приложение действительно отвечает по HTTP. Контейнер, который поднялся, но не слушал порт, всё равно рапортовался как успех — отличить рабочий деплой от сломанного было нельзя. Плюс [GET /v1/infra/servers/:id](/docs/infra/servers/get) для такого приложения показывал `runtime: null` и порт по умолчанию — развёрнутый рантайм и порт не сохранялись.

**Стало**

Успешный ответ несёт `data.steps[]`: шаг `{ step: "build", status: "ok" }` и — когда проба выполнялась — шаг `{ step: "healthcheck", status: "ok" | "warning", httpCode, healthPath }`. `status: "ok"` означает, что приложение ответило 2xx/3xx на `data.appUrl`; `warning` — ответило 4xx/5xx (всё ещё достижимо, деплой прошёл). Контейнер, который поднялся, но не ответил по HTTP на своём порту, теперь честно завершается `502 GALAXY_APP_START_FAILED` (то же семейство, что крах после старта — в теле остаётся хвост `buildLog`), а не рапортуется как успех. Необязательное поле `healthPath` (по умолчанию `/`) в теле деплоя задаёт путь пробы. `GET /v1/infra/servers/:id` теперь отражает развёрнутый `runtime` и порт.

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

Приложение, которое отвечает по HTTP на порту деплоя, ничего не заметит. Приложение, которое стартует, но не начинает отвечать в окне пробы, получит `502 GALAXY_APP_START_FAILED` вместо ложного успеха — убедитесь, что оно слушает порт, указанный при деплое, и что `healthPath` возвращает ответ. Шаг `build` в `data.steps[]` и сохранение `runtime`/порта в `GET` доступны сразу; сама HTTP-проба (шаг `healthcheck` и `502 GALAXY_APP_START_FAILED`) раскатывается — включается на платформе постепенно, поэтому до её активации деплой ведёт себя как раньше (без пробы).

### FIX-0729-8: серверы просыпаются после погашения долга и на постоплатном счёте

**Было**

Портал с постоплатным биллингом, ушедший в минус до лимита овердрафта, глушил серверы и помечал их «заморожено биллингом». После пополнения счёта API снова отвечал 200, но серверы так и оставались выключенными: `POST /v1/infra/servers/{id}/wake` возвращал отказ (`SERVER_WAKE_BLOCKED`), и снять пометку можно было только обращением в поддержку. На предоплатном биллинге тот же сценарий отрабатывал нормально.

**Стало**

Как только баланс перестаёт быть отрицательным, пометка снимается и серверы поднимаются автоматически — одинаково на предоплате и постоплате. Частичное пополнение, оставляющее баланс в минусе, снова открывает API, но серверы держит выключенными: они возвращаются к работе, когда долг закрыт полностью. Серверы, остановленные по другим причинам (истёк доступ, остановка вручную), пробуждение не затрагивает.

### FIX-0729-9: деплой не рапортует ложный успех после отката усиленного юнита

**Было**

Деплой на `POST /v1/infra/servers/:id/deploy` мог отрапортовать успех (`healthcheck:ok`, `hardening:warning`), обслуживая при этом ответ **чужого** процесса, занявшего порт приложения. Это происходило, когда усиленный (hardened) юнит падал, деплой автоматически откатывался на обычный юнит, но откат не освобождал порт — а на первой же проверке чужой держатель порта отвечал `200`. В результате выкладка сообщала об успехе, хотя новая версия порт так и не заняла и в продакшене продолжала работать предыдущая.

**Стало**

Если после отката порт по-прежнему держит тот же процесс, что заблокировал усиленный юнит (откатанный юнит порт не занял), деплой завершается ошибкой `healthcheck:error` с явным сообщением о том, что порт всё ещё занят, вместо ложного `healthcheck:ok`. Штатный откат, при котором порт занимает уже новый экземпляр приложения, по-прежнему завершается успехом.

### FIX-0729-10: кэш метаданных учитывает портал и схемы полей

**Было**

Кэш [GET /v1/statuses](/docs/entities/statuses/list) был описан как привязанный к личному ключу, а схемы `GET /v1/{entity}/fields` не были отражены в разделе кэширования. Клиент не видел в документации, какие повторные запросы получают `X-Cache: HIT` и как запросить свежую схему полей.

**Стало**

[GET /v1/statuses](/docs/entities/statuses/list) описан как кэш портала на 5 минут. `GET /v1/{entity}/fields` описан как кэш схемы полей на 5 минут с учётом портала, ключа авторизации, сущности, параметров пути, параметров запроса и языка ответа. Обход кэша через `Cache-Control: no-cache` доступен для всех этих чтений, а для `/fields` также доступен `refresh=true`.

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

Код менять не нужно. Повторные чтения метаданных меньше нагружают очередь портала, а заголовки `X-Cache` и `X-Cache-Bypass-Reason` показывают, был ли использован кэш.

### NEW-0729-11: дельта последних диалогов по параметру updatedAfter

[GET /v1/chats/recent](/docs/chats/discovery/recent) принимает `updatedAfter` — момент в формате ISO 8601, начиная с которого нужно вернуть изменённые диалоги. Это отдельный режим ответа: `data` приходит плоским массивом диалогов, а `meta` несёт `mode` со значением `delta` и `returned` с их числом.

Размером выборки в этом режиме управляет сервер — читается одна страница до 200 диалогов. Переданный `limit` на неё не влияет и возвращается обратно в `meta.requestedLimit` вместе с применённым `meta.appliedLimit`. Когда дельту не удалось подтвердить полной — Битрикс24 сообщил, что за отданной страницей есть ещё диалоги, либо форму ответа не удалось разобрать, — в `meta` приходит `truncated` со значением `true`: в этом случае не сдвигайте `updatedAfter`, а получите полный список постраничным режимом с курсором `lastMessageDate`. Число возвращённых строк признаком полноты не является.

Граница включительна — диалог, у которого `dateUpdate` равен переданному моменту, попадает в ответ. Дата обязана нести явное смещение или `Z`: значение вида `2026-06-29 10:00:00` читается по-разному в зависимости от часового пояса сервера и отклоняется с `400 INVALID_PARAMS`. Тем же кодом отклоняется сочетание `updatedAfter` с `offset` или `lastMessageDate` — постраничная навигация и дельта используют разные курсоры.

### NEW-0729-12: транзиентный 503 на границе платформы теперь говорит, через сколько повторять

Когда платформа на мгновение недоступна — например в момент редеплоя galaxy-приложения — граница платформы отвечает `503 SERVICE_UNAVAILABLE` на префиксе `/v1/`. В теле было только человекочитаемое «Retry in a few seconds», и машинного признака повторяемости не было: клиент не мог отличить секундную дыру от постоянной недоступности и либо ронял задачу, либо ретраил наугад.

Теперь этот ответ несёт HTTP-заголовок `Retry-After: 5` и поле `retryAfter: 5` внутри объекта `error` — рядом с `code` и `message`, ровно так же, как это делает сама платформа для своего транзиентного 503. Прежние вызовы не меняются: код `SERVICE_UNAVAILABLE` и статус остались теми же, добавлены заголовок и поле. Текст сообщения теперь дополнительно ссылается на заголовок — на него по-прежнему не следует опираться, ветвитесь по `error.code`. Полный список кодов — [/docs/errors](/docs/errors).

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

Отдельно стоит сказать, чего это изменение НЕ делает: оно не устраняет причину, по которой апстримы бэкенда оказались недоступны. Оно делает ошибку честной и машинно-понятной, чтобы клиент корректно подождал и повторил.

### BC-0729-13: пакетный запрос отклоняет сортировку у сущностей, чей метод Битрикс24 её не умеет

> Поддержка старого формата до: 29.07.2026

**Было**

Одиночный список сущности и её `POST /v1/departments/search` уже отвечали `400 INVALID_SORT_FIELD`, если метод Битрикс24 за списком не принимает порядок сортировки. Подзапрос общего `POST /v1/batch` этой проверки не имел: та же сортировка уходила в метод, тот её выбрасывал, и подзапрос возвращал успех с несортированным списком. Получалось расхождение на одном и том же запросе — через одиночный маршрут отказ, через пакетный молчание.

**Стало**

Подзапрос `POST /v1/batch` с действием `list` или `search` проверяет то же самое и отвечает `400 INVALID_SORT_FIELD` в `errors` своего подзапроса; остальные подзапросы выполняются как обычно. Отказ приходит до обращения к Битрикс24. Проверяются оба написания — и `sort`, и `order`. Это касается двух сущностей: подразделений (`departments`) и телефонных линий (`telephony-lines`). Хранилищ это НЕ касается — их метод сортировку умеет, и отказ у них снят отдельной записью этого же выпуска.

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

Если подзапрос к одной из этих двух сущностей передавал сортировку — уберите её: она никогда не применялась, список приходил в порядке Битрикс24. Нужен свой порядок — сортируйте полученный список на своей стороне. Подзапросы без сортировки, а также `limit`, `offset`, `select` и фильтр, работают как раньше. Параллельная поддержка прежнего поведения не предусмотрена: прежнее поведение состояло в том, что параметр молча игнорировался, — сохранять было бы нечего.

### BC-0729-14: `defaultOperatorData` у открытых линий стал объектом, пустое значение — `null`

> Поддержка старого формата до: 27.01.2027

**Было**

Поле объявлялось массивом, и незаданное значение приводилось к `[]`. Настоящий тип другой: Битрикс24 отдаёт объект вида `{ "NAME": …, "AVATAR": … }`, когда данные оператора по умолчанию заданы. То есть [GET /v1/openline-configs](/docs/openlines/config/list) и `GET /v1/openline-configs/:id` обещали в `fields` массив, а при заполненном значении присылали объект.

**Стало**

Тип поля — `object`; незаданное значение приходит как `null`, а не как `[]`. Заполненное значение приходит объектом, как и раньше. Соседние `kpiFirstAnswerList` и `kpiFurtherAnswerList` — настоящие массивы строк, они по-прежнему приводятся к `[]`.

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

Код, который считал длину или перебирал это поле (`defaultOperatorData.length`, `.map`, `.forEach`), сломается на `null` — замените проверку на `if (config.defaultOperatorData) { … }` и читайте поля объекта напрямую. Если вы ориентировались на `fields` и ждали массив — сверьтесь с новым типом `object`.

### BC-0729-15: телефонные линии: запись `serverName`, сортировка, фильтр и смещение больше не теряются молча

> Поддержка старого формата до: 29.07.2026

**Было**

`serverName` в схеме числился обычным изменяемым полем, но Битрикс24 его не хранит и не возвращает: [POST /v1/telephony-lines](/docs/telephony/lines/create) с этим полем отвечал `201`, а значение исчезало; `PATCH` того же поля упирался в ошибку самого Битрикс24. Отбор, порядок и смещение вели себя так же тихо: метод Битрикс24 за этим списком не принимает входных параметров вовсе, поэтому `?order[number]=desc`, `?name=…`, `?filter[number]=…`, `?offset=50` и те же значения в теле `POST /v1/telephony-lines/search` отбрасывались, а список приходил `200` — и выглядел отсортированным, отфильтрованным и перелистнутым, хотя не был ничем из этого. В подзапросе `POST /v1/batch` тем же образом терялась сортировка.

**Стало**

Все четыре случая стали явной ошибкой до обращения к Битрикс24. Запись `serverName` — `400 READONLY_FIELD`; любая сортировка — `400 INVALID_SORT_FIELD`; любой фильтр — `400 UNSUPPORTED_FILTER`; ненулевое смещение — `400 UNSUPPORTED_OFFSET`. Отказ фильтру приходит на списке, в поиске, в `POST /v1/telephony-lines/aggregate` и в подзапросах обоих пакетных запросов — общего `POST /v1/batch` и `POST /v1/telephony-lines/batch`; отказ сортировке и смещению — на списке, в поиске и в подзапросе общего пакетного запроса (агрегат этих параметров не читает). В общем `POST /v1/batch` отказ приходит в `errors` своего подзапроса, а остальные подзапросы выполняются как обычно; если отклонены все подзапросы, запрос отвечает `400`, и разбор по подзапросам остаётся в `errors`. В `POST /v1/telephony-lines/batch` иначе: нарушение контракта отбора отклоняет весь пакет одним `400` с номером подзапроса в сообщении, ни один подзапрос не выполняется. Само поле `serverName` осталось видимым в `GET /v1/telephony-lines/fields` с признаком «только для чтения», так что понять его назначение по-прежнему можно.

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

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

### NEW-0729-16: список хранилищ можно сортировать

Сортировка по полям хранилища работает на [GET /v1/storages](/docs/entities/storages/list) и в [POST /v1/storages/search](/docs/entities/storages/search): `?sort=-id`, `?order[name]=desc` и те же значения в теле поиска. Минус перед именем поля означает убывание.

Порядок выдачи меняют `id`, `name`, `entityType`, `entityId`, `rootFolderId` — по каждому из них проверено на живом аккаунте, что по возрастанию и по убыванию приходят разные выдачи. Поля `code` и `module` метод тоже принимает без ошибки, но на проверенных аккаунтах значение этих колонок одинаково у всех хранилищ, поэтому порядок по ним не меняется — не полагайтесь на них как на сортировку.

Раньше любая сортировка хранилищ отклонялась с `400 INVALID_SORT_FIELD`. Отказ был ошибочным: он был выведен из описания метода Битрикс24, а метод порядок сортировки принимает и применяет — это проверено на живом портале, где выдача по возрастанию, по убыванию и без сортировки различаются. Если вы обходили этот отказ, сортируя список у себя, обходной путь можно убрать; он продолжает работать.

Заодно порядок выдачи стал устойчивым. К вашей сортировке добавляется `id` последним ключом, а список без сортировки теперь приходит по возрастанию `id` — раньше он приходил в неопределённом порядке аккаунта. Это не косметика: список отдаётся страницами по 50, и при сортировке по неуникальному полю (например по названию) строка с тем же значением могла на границе страниц попасть в две страницы сразу или пропасть из выдачи вовсе. Теперь порядок полный и однозначный, поэтому и постраничный обход повторяем. Если вы сортировали по `id` сами, ваше направление сохраняется — второй ключ не добавляется.

Разбиение на страницы у хранилищ идёт постранично по 50 записей, поэтому при сортировке запрашивайте нужный объём одним вызовом (`limit` до 5000), а не листайте страницы вручную.

### FIX-0729-17: перезапуск galaxy-приложения через /reboot

**Было**

Для galaxy-приложения (`kind=GALAXY_APP`) у [POST /v1/infra/servers/:id/reboot](/docs/infra/lifecycle/reboot) не было рабочего сценария: вызов возвращал `422 VM_MISSING` (у контейнера нет собственной виртуальной машины), а единственным путём восстановления зависшего приложения оставалось удаление — оно стирает постоянный том `/data`.

**Стало**

`/reboot` перезапускает контейнер приложения как «пинок» самовосстановления — постоянный том `/data` при этом сохраняется. Вызов принимается в статусе `running` или `error` и возвращает совещательный вердикт: `restarted` (контейнер перезапущен) и `healthy` (контейнер запустился и перестал перезапускаться — проверка контейнера, не HTTP-ответа приложения), а при `healthy: false` — поле `hint` о том, как залить исправленную версию. Перезапуск не снимает состояние ошибки — крашащееся приложение авторитетно чинится редеплоем исходников через [POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy). Новые коды ошибок для этого сценария: `GALAXY_APP_REBOOT_USE_AGENT_CONTROLS` (409 — приложением агента или бота управляют из его панели), `GALAXY_APP_BUSY` (409 — на хосте выполняется другая команда, в ответе `Retry-After`), `GALAXY_HOST_UNREACHABLE` (502 — хост недоступен). Перезагрузка обычного сервера не изменилась.

### NEW-0729-18: totalDefault — умолчание по meta.total на самом ключе

У API-ключа появилась настройка `totalDefault`: заказывать ли подсчёт количества спискам этого ключа, когда сам запрос не передал `withTotal`. Значение `true` — присылать `meta.total`, `false` — не присылать, `null` — наследовать платформенное умолчание. По умолчанию у всех ключей `null`.

Настройка правится в кабинете на странице ключей и через [PATCH /v1/keys/:id](/docs/management-keys) полем `totalDefault` (управляющий ключ `vibe_live_`). Перевыпуск ключа через `POST /v1/keys/:id/rotate` настройку сохраняет — как и режим доступа. Изменение попадает в журнал аудита.

Действующее значение видно в [GET /v1/me](/docs/keys-auth/me) — блок `totalDefault` показывает всю цепочку: `key` (настройка ключа), `platform` (платформенное умолчание), `effective` (что получится, если запрос не передаст `withTotal`) и `source` — откуда взялось действующее значение.

Настройка нужна там, где менять код интеграции дороже, чем один раз переключить ключ: она задаёт умолчание сразу всем спискам этого ключа. Точечно её перекрывает параметр запроса `withTotal`.

### NEW-0729-19: meta.nextAfterId — курсор следующей страницы при сортировке по id

Ответы [GET /v1/{entity}](/docs/entity-api) и [POST /v1/{entity}/search](/docs/entity-api) получили необязательное поле `meta.nextAfterId` — идентификатор последней отданной записи, строкой.

Поле приходит, когда выполнены три условия сразу: у сущности числовой идентификатор и поддержка курсорного листания, сортировка запроса — строго `id` по возрастанию, и `meta.hasMore` равен `true`. На последней странице поля нет: идти уже некуда. Сегодня условиям отвечают сделки, лиды, контакты, компании, предложения и элементы смарт-процессов.

Значение передаётся обратно тем же фильтром, которым курсорное листание делалось и раньше: `filter[>id]=<nextAfterId>` при сортировке `id` по возрастанию. Нового параметра запроса не появилось — поле лишь избавляет от чтения идентификатора из последней строки ответа вручную.

Такое листание не зависит от смещения и не дорожает к концу коллекции, поэтому для обходов в десятки тысяч записей оно предпочтительнее, чем растущий `offset`.

### NEW-0729-20: withTotal — списку можно не заказывать подсчёт количества

Списочные вызовы приняли необязательный параметр `withTotal`. У [GET /v1/{entity}](/docs/entity-api) это параметр запроса ровно с двумя допустимыми значениями — `true` и `false`; у [POST /v1/{entity}/search](/docs/entity-api) — поле тела с булевым значением. Любая другая запись читается как «параметр не передан», ошибки не будет.

`withTotal=false` — просьба не считать количество. Там, где платформа может её выполнить, подсчёт у Битрикс24 не заказывается и `meta.total` в ответе отсутствует. Там, где обойтись без подсчёта нельзя, параметр не действует и `meta.total` приходит как раньше. Поэтому наличие поля проверяйте, а не предполагайте.

Листать надо по `meta.hasMore` — он считается по полноте страницы и доводит цикл «читай, пока `hasMore`» до конца независимо от того, был ли подсчёт. При сортировке строго по `id` по возрастанию ответ дополнительно несёт `meta.nextAfterId`, который передаётся обратно в `filter[>id]`.

Если параметр не передан, значение берётся из настройки ключа, а при её отсутствии — из платформенного умолчания. Действующее сейчас значение и всю эту цепочку показывает блок `totalDefault` в [GET /v1/me](/docs/keys-auth/me).

Когда точное количество действительно нужно, спрашивайте его прямо: `POST /v1/{entity}/aggregate` с функцией `count` отдаёт число одним вызовом, без выгрузки записей. Считать количество постраничным обходом коллекции не надо — это десятки вызовов вместо одного и самый дорогой способ узнать одну цифру.

### FIX-0729-21: meta.hasMore в списках считается по полноте страницы, а meta.total может отставать до минуты

**Было**

`meta.hasMore` в ответах [GET /v1/{entity}](/docs/entity-api) и [POST /v1/{entity}/search](/docs/entity-api) выводился из `meta.total`: «есть ещё» означало «`offset` плюс отданные строки меньше общего количества». Пока количество считалось на каждый вызов, это совпадало с правдой.

**Стало**

Платформа перестаёт запрашивать у Битрикс24 подсчёт количества на каждый повторный вызов с той же парой «ключ и запрос» — подсчёт непропорционально дорог для портала. Отсюда два наблюдаемых следствия.

`meta.hasMore` на таких ответах считается по полноте страницы: пришла полная страница — «возможно, есть ещё»; пришла неполная — список закончился. Цикл «читай, пока `hasMore`» по-прежнему доходит до конца всегда. Если коллекция ровно кратна `limit`, последний шаг вернёт пустой список — это штатный признак конца.

`meta.total` остаётся числом и остаётся на месте, но становится информативным: он может отставать до минуты, поэтому число отданных строк может оказаться больше него.

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

Менять ничего не нужно, если листание идёт по `meta.hasMore` — это рекомендованный способ. Если код опирается на `meta.total` как на точную границу цикла или проверяет «отдано не больше, чем total», переключитесь на `meta.hasMore`. Точное количество на момент запроса даёт `POST /v1/{entity}/aggregate` с функцией `count`.
