# Изменения API: 2 августа 2026

[← Журнал изменений](/docs/changelog) · [Август 2026](/docs/changelog/2026-08)

### FIX-0802-1: подкоманда batch со своим start=-1 больше не отдаёт выдуманный total

Подкоманда `POST /v1/batch` со своим `params.start: -1` больше не получает выдуманное количество записей. Значение `-1` — это инструкция Битрикс24 «не считай коллекцию», поэтому счёта в ответе портала нет; конверт же брал за размер то, что оказалось под рукой — эхо `result_total` от методов, которые в этом режиме отдают `0` рядом с полной страницей, либо просто длину первой страницы. Затронуты обе ветки: подкоманда с `limit` до 50 и подкоманда с `limit` больше 50, которая читается отдельной автопагинацией.

**Было**

`{"entity":"activities","action":"list","params":{"start":-1}}` → `meta.<id>.total: 0` и `data.totals.<id>: 0` рядом с 50 записями, `meta.<id>.hasMore: false`.
`{"entity":"deals","action":"list","params":{"limit":5000,"start":-1}}` → 50 записей, `meta.<id>.total: 50`, `meta.<id>.hasMore: false` — то есть на запрос 5000 записей приходил уверенный ответ «их всего 50».

**Стало**

На такой подкоманде ключей `total` нет ни в `meta.<id>`, ни в `data.totals` — счёт не заказывался, и придумывать его нечем. `hasMore` определяется полнотой страницы: заполненная до запрошенного лимита → `true`, короткая → `false`. Полнота считается против того ограничения, которое реально ушло в Битрикс24, поэтому `{"limit":10,"start":-1}` при 10 записях в ответе — это полная страница, и `hasMore` там теперь `true`, а не `false`. Обход не строит план дочитывания из выдуманного размера и возвращает непрерывный префикс.

Признак «счёт не заказан» читается по нормализованному значению: `start` приводится к целому числу так же, как это делает Битрикс24 (усечение к нулю, строка читается по числовому префиксу), поэтому `-1`, `"-1"`, `-1.5`, `"-1abc"`, `"-1 x"` — одно и то же. Положительное смещение (`start: 100`) — обычный счётный курсор, `total` по нему приходит как раньше.

Значение, которое числом не является вовсе (`"abc"`, пустая строка, `null`, объект, массив, `true`), в Битрикс24 больше не уходит: оно читается как непереданное. Страница от этого не меняется — «начать с нуля» и «`start` не передан» это одна и та же страница, — но такая подкоманда попадает под общий выбор платформы и может прийти без `total`.

Отдельно: подкоманда, завершившаяся ошибкой, больше не публикует `data.totals.<id>` рядом с этой ошибкой.

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

Клиент, который передавал `start: -1` и читал `total`, получал заведомо неверное число: у методов формы «эхо `result_total: 0`» это был ноль, у остальных — длина страницы. Если цикл чтения останавливался по `meta.hasMore`, он обрывался на первой странице. Проверяйте наличие ключа `total` (`meta.<id>.total !== undefined`), а продолжение обхода ведите по `meta.<id>.hasMore`. Нужен точный счёт — не передавайте `start: -1`: этим значением подсчёт отменяет сам клиент, поэтому вернуть по такой подкоманде нечего, и `withTotal: true` его не восстановит.

### BC-0802-2: доступ коробочного портала больше не выдаётся безусловно

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

**Было**

Коробочный (self-hosted) портал считался коммерческим всегда: отметка ставилась при подключении портала, а не по факту оплаты. Ни подписка Маркетплейса Битрикс24, ни её окончание на доступ к платформе Вайбкод не влияли.

**Стало**

Доступ коробки определяется её подпиской Маркетплейса Битрикс24 — как у облачного портала. Ответы меняются там, где раньше доступ был всегда: [POST /v1/infra/servers](/docs/infra) у портала без действующей подписки отвечает `402` с кодом отказа вместо создания сервера, а `capabilities.servers.create` в [GET /v1/me](/docs/quickstart) приходит недоступной, с причиной. Те же правила действуют на создании агентов и ботов, которые заводят сервер.

Платная лицензия Битрикс24 сама по себе доступ к платформе Вайбкод не даёт: лицензия — про коробку, подписка — про Маркетплейс. Портал с оплаченной коробкой, но без подписки, попадает под отказ.

Пока состояние подписки прочитать не удалось, доступ **не** ограничивается: отсутствие сигнала не приравнивается к отсутствию подписки.

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

- `wasEverCommercial` в [GET /v1/me](/docs/quickstart) у коробочных порталов перестаёт быть односторонним: у портала, за которым не нашлось ни подписки, ни платежей, значение однократно меняется с `true` на `false` — прежнее ставилось при подключении, а не по наблюдению.
- `placements.bindPrerequisite` в том же ответе у коробки начинает описывать подписочную модель (другой набор `errorCodes`, другой `note`) — раньше портал без определённого региона описывался как международный.

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

Проверять `capabilities.servers.create` в [GET /v1/me](/docs/quickstart) перед созданием инфраструктуры и обрабатывать `402` на создании — код и текст отказа приходят в теле ответа. Если подписка оформлена, а отказ приходит, поможет принудительное обновление: `GET /v1/me?refresh=tariff`. Не полагаться на монотонность `wasEverCommercial` для коробочных порталов.
