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

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

### BC-0902-1: Документы сообщают состояние преобразования в PDF

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

**Было**

Поля `isTransformationError`, `transformationErrorCode`, `transformationErrorMessage`, `transformationCancelReason` и `pullTag` не были объявлены в контракте документов. Если Битрикс24 возвращал их через [GET /v1/documents/:id](/docs/entities/documents/get), API Вайбкод передавал значения без нормализации. Те же поля в телах [POST /v1/documents](/docs/entities/documents/create) и [PATCH /v1/documents/:id](/docs/entities/documents/update) не отклонялись локальной проверкой полей только для чтения.

**Стало**

Пять полей объявлены как допускающие `null` поля ответа только для чтения. `isTransformationError` возвращается как `boolean | null`, остальные четыре поля — как `string | null`. Пустые строки в строковых полях становятся `null`. Запрос записи с любым из этих полей возвращает `400 READONLY_FIELD`.

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

Не передавать эти пять полей в телах создания и изменения документа, в том числе при повторной отправке ранее полученного объекта. При чтении учитывать `null` и использовать `pullTag` для подписки на обновления состояния преобразования.

### BC-0902-2: Адрес переключателя режима в отказе по режиму доступа больше не фиксирован

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

**Было**

Отказ по режиму доступа `WRITE_BLOCKED_READONLY_KEY` всегда возвращал `details.switchUrl`
равным `"/keys"`, а машинная схема закрепляла это значение перечислением `enum: ["/keys"]`.
Раздел ключей показывает только личные ключи, поэтому для двух других видов путь был
тупиком: ни ключ авторизации приложения, ни менеджмент-ключ там не показываются по
построению — ни владельцу, ни администратору Битрикс24. Держателю сообщали адрес страницы,
на которой переключателя для его ключа нет.

**Стало**

`details.switchUrl` указывает на страницу, где режим переключается именно у этого ключа:
личный ключ — раздел ключей `"/keys"`, ключ авторизации приложения — кабинет приложений
`"/applications"`, менеджмент-ключ — раздел менеджмент-ключей `"/management-keys"`. Текст
сообщения называет тот же адрес, что и поле, — они собираются вместе и разойтись не могут. Перечисление значений снято со схемы: это путь в интерфейсе,
а не константа протокола, и закрепление литерала делало контракт невыполнимым при переезде
страницы. Поле по-прежнему приходит всегда и остаётся обязательным — изменилось значение,
а не наличие.

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

Читать `switchUrl` из ответа, а не подставлять `"/keys"`. Клиентам, которые генерируют типы
из схемы, литеральный тип `'/keys'` больше не выдаётся — обновите сгенерированные типы,
иначе проверка значения не пройдёт.

### FIX-0902-3: поток, который не начался, завершается повторяемой ошибкой у моделей всех поставщиков

**Было**

У моделей `bitrix/*` установка потока уже делала одну попытку с общим бюджетом, а у моделей остальных поставщиков платформа молча отправляла запрос второй раз и ждала ещё один полный бюджет. Клиент в это время не получал ничего — до двух полных бюджетов тишины, — а затем видел общий отказ провайдера, по которому нельзя отличить зависшую установку потока от любой другой неопознанной ошибки.

```
data: { "error": { "code": "ai_provider_unavailable", "type": "server_error", "retryable": true, "retryAfter": 6 } }
data: [DONE]
```

**Стало**

Установка потока делает одну попытку с общим бюджетом у моделей ЛЮБОГО поставщика. Если заголовки не пришли за отведённое время, ожидание не удваивается, а поток завершается тем же событием `stream_idle_timeout`, что и замолчавший в середине ответа, — по нему видно, что молчал именно поток.

```
data: { "error": { "code": "stream_idle_timeout", "type": "server_error", "retryable": true, "retryAfter": 7 } }
data: [DONE]
```

Ожидание больше не удваивается невидимо, а причина отказа названа точно — теперь на всём наборе моделей, а не только на `bitrix/*`.

### NEW-0902-4: список ресурсов бронирования в V1

Появился [GET /v1/booking-resources](/docs/entities/booking-resources) — он возвращает ресурсы бронирования, доступные ключу, и закрывает разрыв в сценарии первого бронирования: [POST /v1/bookings](/docs/entities/bookings/create) требует непустой `resourceIds`, а узнать валидные идентификаторы средствами одного только V1 было нельзя.

Нужен скоуп `booking`. Ключ с режимом «только чтение» подходит — метод читающий. Фильтры `typeId` и `searchQuery` необязательны и комбинируются, любой другой параметр отклоняется с `400 INVALID_PARAMS`.

Каталог собирается целиком, поэтому параметров постраничного вывода нет: `meta.total` равен длине `data`, `meta.hasMore` всегда `false`. Каждая запись несёт ровно четыре поля — `id`, `name`, `typeId` и `isMain`. Поле `description` не отдаётся: это свободный текст портала, для выбора ресурса он не нужен.

Полнота ответа гарантируется для каталога, не менявшегося во время запроса, — снимка коллекции Битрикс24 не предоставляет. Портал больше чем с 500 ресурсами получает `502 BITRIX_RESULT_TOO_LARGE` вместо усечённого списка; сузить выборку помогают те же два фильтра.

### NEW-0902-6: device-flow принимает идентификатор устройства

`POST /v1/connect/device/authorize` принимает необязательный параметр `device_id` — стабильный идентификатор установки клиента (до 128 символов, буквы, цифры, `_.:-`). Он действует для приложения Cowork/Code: при повторном подключении с того же устройства прежний ключ отзывается, а не остаётся в списке рядом с новым. Сторонние клиенты параметр передавать могут, но на выдачу их ключей он пока не влияет.

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

### NEW-0902-7: новый код отказа INT_BOX_PARTNER_REQUIRED для коробок на международной установке

На международной установке доступ коробочного портала к платформе может требовать
подтверждённой партнёрской (NFR) лицензии. Коробка без подтверждения получает HTTP 402 с
новым кодом `INT_BOX_PARTNER_REQUIRED` — на создании сервера, агента, управляемого бота и
на выписке ключа. Тело отказа устроено как у соседних кодов этого семейства
(`userMessage`, `alternatives`, `hint`), но поле `details.requiredTariffs` пустое: переход
на другой тариф Битрикс24 этот отказ не снимает, признак читается при регистрации модуля
коннектора. Тот же код приезжает в поле `reason` слота `capabilities.servers.create` ответа
`GET /v1/me`, а адрес документации — в его `alternatives[].url`. Требование включается отдельно;
пока оно не включено, ни один портал этого кода не увидит и ответы остаются прежними.

### NEW-0902-8: стабильный идентификатор портала в самоописании ключа

[GET /v1/me](/docs/keys-auth/me) возвращает новое поле `portalId` — устойчивый идентификатор портала Битрикс24, к которому привязан ключ. Оно приходит тем же запросом, рядом с уже существующими `portal` и `owner`, и есть у ключей `vibe_api_` и `vibe_app_`.

В отличие от домена в поле `portal`, идентификатор не меняется при переименовании и переезде портала. Берите его, когда локальные данные раскладываются по аккаунтам: ключ аккаунта, собранный из домена, после переезда портала перестаёт совпадать с прежним, и данные того же аккаунта оказываются в новом пустом хранилище.

В успешном ответе поле всегда непустое: ключ без привязанного портала до этого ответа не доходит, он получает `401 NO_PORTAL`. Менеджмент-ключи `vibe_live_` нового поля не получают — они не привязаны к одному порталу и по-прежнему отдают перечень порталов в `portals`.

### NEW-0902-9: создание сервера отвечает 409 `REISSUE_IN_PROGRESS`, пока перевыпускается ключ авторизации приложения

У `POST /v1/infra/servers` появился новый код отказа `REISSUE_IN_PROGRESS` со статусом `409`. Платформа Вайбкод отвечает им, когда владелец карточки приложения в этот момент перевыпускает её ключ авторизации: сервер не создаётся, потому что он оказался бы на ключе, который отзывается в ту же секунду.

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

### FIX-0902-10: методы дашборда Открытых линий появились в OpenAPI

**Было**

Шесть публичных методов статистики Открытых линий были описаны на страницах документации, но отсутствовали в `/v1/openapi.json` и сгенерированных карточках API.

**Стало**

Все шесть методов доступны в OpenAPI и карточках API со скоупом `imopenlines`, параметрами и форматами ответов. Runtime-поведение не менялось: успешный ответ остаётся HTTP 200, прежние статусы и форматы ошибок сохранены.

### NEW-0902-11: код обращения в неопознанном отказе выписки ключа

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

Поле опциональное и добавлено к уже существующему телу ответа: HTTP-статус,
`error.code` и `error.details.reason` прежние, клиентам делать ничего не нужно.

### NEW-0902-12: лимит частоты, ETag и Vary у GET /v1/openapi.json

У [GET /v1/openapi.json](/docs/api-reference) появился лимит частоты на один адрес вызывающего. Точное значение потолка отдаётся в заголовке `x-ratelimit-limit` ответа — читайте его оттуда, а не задавайте числом в коде. Превышение отвечает `429 RATE_LIMITED`. Лимит щедрый и на обычное чтение не рассчитан: спека отдаётся с `ETag`, поэтому дискавери-клиент и генератор SDK повторно получают `304` вместо тела.

Тело спеки может зависеть от ключа в запросе. Поэтому ответ помечен `Vary: Authorization, X-Api-Key` (ключ читается из любого из двух заголовков), а с ключом, для которого тело отличается, отдаётся под `Cache-Control: private` вместо `public`. Не переиспользуйте один сохранённый файл спеки между разными ключами.

### FIX-0902-13: тарифный отказ Битрикс24 при выписке ключа и установке приложения называет причину

**Было**

Когда Битрикс24 отказывал в выписке кодом `FEATURE_NOT_AVAILABLE_ON_CURRENT_PLAN` (тариф портала не включает Вайбкод), ответ был безликим на ЛЮБОЙ ручке выписки — и там, где выпускается ключ ([POST /v1/keys](/docs/management-keys) → `502 CONNECTOR_KEY_ISSUE_FAILED`), и там, где устанавливается приложение ([POST /v1/apps](/docs/apps/create) → `502 CONNECTOR_APP_INSTALL_FAILED`). Текста для человека в теле не было вовсе, а причина оставалась только во внутреннем поле, поэтому клиент читал отказ как временный сбой платформы и повторял запрос. Повтор не помогает никогда: гейт снимается только сменой тарифа Битрикс24.

```
HTTP 502
{ "success": false, "error": { "code": "CONNECTOR_KEY_ISSUE_FAILED", "message": "connector refused to issue the key" } }
```

**Стало**

Отказ разбирается по региону портала. Там, где доступ продаётся, приходит `402` с кодом тарифного пейвола и текстом для человека: на международном сегменте — `INT_VIBE_PLUS_REQUIRED` с `details.requiredTariffs: ["vibe+"]` и `details.upgradeUrl` на страницу подключения тарифа в самом портале, в тарифных регионах СНГ на бесплатном тарифе — `BY_PAID_ONLY`, `KZ_PAID_ONLY` или `UZ_PAID_ONLY`. Там, где предлагать нечего (коробочный портал, портал уже на платном тарифе, нераспознанный регион), ответ остаётся `502`, но получает собственный код `CONNECTOR_PLAN_REQUIRED` и непустой `userMessage` вместо пустого тела.

```
HTTP 402
{ "success": false, "error": { "code": "INT_VIBE_PLUS_REQUIRED", "message": "This action requires a Vibe+ plan on your Bitrix24 account.", "details": { "requiredTariffs": ["vibe+"], "upgradeUrl": "https://example.bitrix24.com/online/?feature_promoter=limit_why_pay_tariff_vibe" } } }
```

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

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

### FIX-0902-14: отказ на странице согласия возвращает пользователя в приложение партнёра

**Было**

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

**Стало**

Отказ несёт готовый адрес возврата: на странице появляется кнопка «Вернуться в приложение», а `redirect_uri` получает `error=access_denied` (`temporarily_unavailable` при недоступности Битрикс24), машинный код причины в `error_description` и исходный `state`. Если у зарегистрированного адреса возврата был свой параметр `code`, при отказе он снимается — отказ не приходит вперемешку с признаками успеха. Так же ведут себя отказы до подтверждения — протухшая ссылка согласия и битый CSRF-токен, в том числе на кнопке «Отклонить».
