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

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

### NEW-0820-1: снимок подписки Коворка описан в спецификации API

**Было**

Ручка `GET /v1/cowork/me` работала и была указана в путеводителе `/v1/guide`, но в спецификации V1 её не было. Сгенерировать по спеке клиент или проверить форму ответа было нельзя — оставалось читать путеводитель глазами.

**Стало**

Операция описана: тариф и состояние подписки, три окна квоты как целые проценты с датой сброса, дата следующего списания. Отдельно отмечено, что тело успешного ответа — сам объект, без обёртки `success`, тогда как ошибки приходят в обычном конверте `{ success: false, error: { code, message } }`. Блоки `offPeak` и `relief` описаны как отсутствующие при выключенной возможности: проверять нужно наличие ключа, а не сравнивать значение с `null`.

### FIX-0820-2: примеры `include` используют имена связей

**Было**

OpenAPI и MCP показывали для параметра `include` имена связанных сущностей во множественном числе, из-за чего запрос завершался ошибкой `INVALID_INCLUDE`.

**Стало**

Примеры используют фактические имена связей `contact,company`.

### FIX-0820-3: MCP корректно передаёт параметры действий с записями таймлайна

**Было**

Инструмент `manage_timeline_log` принимал только строковый `id`, не передавал тело запросов `pin` и `unpin`, а также query-параметры запросов `get_note` и `delete_note`.

**Стало**

Инструмент принимает строковый или числовой `id` и передаёт обязательные параметры этих действий в `/v1/timeline-logs/*`. Описание удаления теперь прямо сообщает, что personal-ключи не могут удалять такие записи: удаление доступно только тому же OAuth-приложению, которое создало запись.

### NEW-0820-4: разделы календаря получили маршруты схемы и поиска

**Было**

Для `calendar-sections` отсутствовали `GET /v1/calendar-sections/fields` и `POST /v1/calendar-sections/search`, поэтому агент не мог заранее узнать поля и допустимые типы календарей или использовать стандартную поверхность поиска.

**Стало**

`GET /v1/calendar-sections/fields` возвращает статическую схему с обязательными полями и типами `user`, `group`, `company_calendar`, `location`. `POST /v1/calendar-sections/search` поддерживает owner-контекст через `filter.type` и `filter.ownerId`; дополнительные фильтры честно отклоняются как неподдерживаемые методом Битрикс24.

### FIX-0820-5: персональные ключи показывают только исполнимые права

**Было**

[GET /v1/me](/docs/management-keys) мог сообщать персональному ключу права `placement`, `entity` и `userfieldtype`, хотя эти возможности требуют контекста OAuth-приложения. Создание и изменение ключа также принимало `userfieldtype` как обычное право.

**Стало**

[GET /v1/me](/docs/management-keys), создание и изменение персональных ключей исключают `placement`, `entity` и `userfieldtype`. Право `userfieldconfig` остаётся доступным. OAuth-ключи приложений не изменились.

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

Дополнительных действий не требуется. Для встраиваний и пользовательских типов полей используйте OAuth-ключ приложения.

### FIX-0820-6: право на задачи действует на всех операциях задач, как бы ключ ни был выписан

**Было**

У ключа с правом на задачи часть операций задач отвечала отказом по правам — какая именно, зависело от того, каким способом портал выписал вебхук ключа. В журнале задачи Битрикс24 различает два написания одного права (`task` и `tasks`), и они открывают разные группы операций: старые операции задач требуют первого написания, новые — второго. Ключ сохранял то написание, которое выбрал владелец, и на части путей выписки на портал уходило только оно. Внутри `POST /v1/batch` такой отказ приходил внутри ответа `200` — по подкоманде, а не по всему запросу.

**Стало**

Право на задачи регистрируется на портале в обоих написаниях независимо от способа выписки, поэтому операции задач доступны все. Ключи, выписанные раньше, приводятся к тому же состоянию при переподключении вебхука. Состав прав самого ключа и ответ `GET /v1/me` не меняются — клиенту менять ничего не нужно.

### FIX-0820-7: создание бот-чата отдаёт идентификатор, который принимают остальные действия

**Было**

Инструмент `manage_bot_chat` после создания чата показывал на виду числовой идентификатор — `data.chat.id` и `data.recentConfig.chatId`. Следующие действия с этим числом — [GET /v1/bots/:botId/chats/:dialogId](/docs/bots/chats/get), выход из чата, передача владения — отвечали ошибкой `BITRIX_ERROR` «Указанный чат не существует»: для Битрикс24 голое число в `dialogId` означает личный диалог с пользователем с таким номером, а не групповой чат с таким id. Пригодный идентификатор вида `chat471` лежал глубже, в `data.chat.dialogId`, и в описании инструмента этот формат назван не был.

**Стало**

Ответ создания чата начинается с поля `chatId` со значением вида `chat471` — именно его принимают остальные действия инструмента. Поля Битрикс24 `data.chat.id` и `data.recentConfig.chatId` не изменились и остались числовыми. Описание параметра `chatId` теперь называет оба формата: `chatN` — групповой чат, голое число — личный диалог с пользователем.

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

Клиентам MCP дополнительных действий не требуется. Ответ [POST /v1/bots/:botId/chats](/docs/bots/chats/create) для REST не менялся: там по-прежнему нужно брать `chat.dialogId`, а не числовой `chat.id`. Запрос [GET /v1/bots/:botId/chats/:dialogId](/docs/bots/chats/get) и остальные действия принимают и `chatN`, и число как идентификатор личного диалога.

### FIX-0820-8: отказ ИИ-провайдера: понятный текст вместо чужой прозы и одинаковая форма ошибки в потоке и без него

**Было**

Когда ИИ-провайдер отклонял обращение платформы, `POST /v1/chat/completions`, `POST /v1/embeddings`
и `POST /v1/audio/transcriptions` отдавали `502 ai_provider_unavailable`, а в `error.message`
приезжал текст провайдера дословно. Провайдер при этом мог назвать ошибкой авторизации собственный
инфраструктурный сбой — и клиент читал в ответе слово про авторизацию там, где ни его ключ, ни его
сеть ни при чём, и уходил проверять их.

Поток (`stream: true`) отдавал ту же ошибку в другой форме, чем обычный запрос: `code` приходил
заглавными буквами вместо строчных, поля `type` не было вовсе, а `retryAfter` и `retryable`
доставались только обрыву простоя и перегрузке. Клиент, который ветвится по `error.type` или по
`retryable`, не мог отличить временный отказ от окончательного и не знал, сколько ждать.

**Стало**

Текст ответа зависит от того, чей креденшл отклонил провайдер. Свой ключ, подключённый вызывающим
(BYOK), — сообщение провайдера проходит как раньше: оно адресовано владельцу ключа и говорит ему,
что делать. Креденшл портала — ответ называет объект и того, кто может его обновить, и прямо
предупреждает, что повтор не поможет. Креденшл платформы — ответ сообщает, что дело не в ключе
вызывающего и не в его сети. Статус `502`, код `ai_provider_unavailable` и поле `providerStatusCode`
во всех случаях прежние.

Ошибка в потоке приняла ту же форму, что и без потока: `code` строчными буквами, поле `type` на
месте, а всякий кадр с паузой `retryAfter` теперь несёт и `retryable: true`. Поля появились у
временной недоступности провайдера, у ограничения частоты и у остывания после череды неудачных
вызовов — раньше их нёс только обрыв простоя.

Признаки повторяемости согласованы с текстом ответа: отказ, который повтор не вылечит, не несёт
ни паузы, ни `retryable`. Это отказ по содержимому запроса (`ai_provider_rejected`) и отклонённый
провайдером креденшл портала или свой ключ вызывающего — там ответ прямо говорит, что нужно
обновить креденшл. Временная недоступность провайдера повторяемой остаётся.

### FIX-0820-9: вложение с расширением, не совпадающим с содержимым, больше не отклоняется

**Было**

`POST /v1/feedback/attachments` сверял тип, объявленный клиентом, с сигнатурой самого файла и отвечал `400 MIME_MISMATCH`, если они расходились. Тип клиент берёт из расширения, поэтому JPEG, сохранённый как `image.png`, приезжал как `image/png` и получал отказ — хотя оба формата разрешены, а файл цел.

**Стало**

Обработка ведётся от фактического формата файла. Расхождение между двумя разрешёнными форматами (PNG, JPEG, WebP, GIF) принимается, файл переупаковывается по содержимому, и его `mime` в ответе — результат переупаковки, как и раньше. `MIME_MISMATCH` остался за единственным случаем: сигнатура файла не распознана вовсе.

### FIX-0820-10: MCP сохраняет единый формат идентификатора чата

**Было**

Действие `manage_chat.add_users` передавало значение вида `chat457` в числовой backend-маршрут без нормализации, поэтому Bitrix24 отвечал ошибкой про пустой ID чата. Созданный чат нельзя было покинуть через тот же MCP-инструмент, а `find` выглядел как текстовый поиск.

**Стало**

`add_users` и новое действие `leave` принимают стандартное значение `dialogId` вида `chatN` и передают числовой ID маршруту. `add_users` сохраняет прежний положительный числовой ID чата для совместимости, а новое необратимое действие `leave` требует однозначный `chatN`; вызывающий должен преобразовать числовой ID из ответа создания в `chatN` перед вызовом `leave`. Отсутствие или некорректный ID отклоняется до сетевого вызова. Инструмент предупреждает, что владелец должен сначала передать владение чатом, используя числовой ID без префикса `chat`. Описание `find` прямо указывает обязательные `entityType` и `entityId` для поиска чата, связанного с CRM-сущностью.

### FIX-0820-11: адреса применяют select — запись сужается, а незнакомое имя больше не теряется

**Было**

Параметр `select` описан для всех сущностей, но у [адресов](/docs/entities/addresses/list) он
не делал ничего. Список, поиск и получение записи по составному ключу отвечали полной записью
со всеми полями, сколько бы имён ни перечислил вызывающий, а незнакомое имя пропадало без следа —
ни ошибки, ни предупреждения. Это была единственная сущность, где отбор полей молчал полностью.

**Стало**

Все три двери адресов применяют `select` так же, как остальные сущности: в записях остаются
только перечисленные поля, принимаются канонические имена и исходные имена Битрикс24
(`CITY` проецирует `city`), а `*` по-прежнему означает «вернуть все поля».

Незнакомое имя ведёт себя по-разному на разных дверях. Получение записи по составному ключу
отбирает поля на стороне Вайбкод, поэтому имя, которого нет в схеме, приходит предупреждением
`UNKNOWN_SELECT_FIELD` в `meta.warnings`, а сама запись возвращается — блок `meta` там
добавляется только при наличии предупреждений. Список и поиск передают перечисленные имена
дальше в Битрикс24, поэтому исход там задаёт аккаунт: не знающий такого поля отклоняет весь
вызов — ответ `422 BITRIX_ERROR`, имя названо в сообщении, данные не приходят.

Составной ключ адреса — `typeId`, `entityTypeId`, `entityId` — возвращается всегда, даже если в
`select` его не перечислили. У большинства сущностей ту же роль играет одно поле `id`: по нему
запись отличают от соседней и по нему же строят адрес для изменения и удаления. У адресов эту
роль выполняют все три поля сразу.

Отдельно: имя `id` в `select` подчиняется тому же разделению. На получении по составному ключу
оно больше не считается опечаткой — собственного `id` у адресов нет, поэтому раньше
`select=id,city` приносил предупреждение о поле `id`, а теперь такой запрос читается как
«покажи, что это за запись» и возвращает составной ключ. На списке и поиске имя `id` уходит в
Битрикс24 и подчиняется той же проверке аккаунта.

**Отбор полей перестал срезать ключ маршрута у смарт-процессов и телефонных линий**

У большинства сущностей адрес операции строится по `id`, и `select=id,…` работал как ожидается.
Но есть две, где ключ маршрута зовётся иначе, и отбор полей его выбрасывал:
у [смарт-процессов](/docs/entities/smart-processes/list) это `entityTypeId`, у телефонных линий
(`/v1/telephony-lines`) — `number`. Теперь оба поля остаются в ответе, даже если в `select` их
не перечислили: `GET /v1/telephony-lines?select=name` отдаёт `{name, number}` вместо `{name}`.

У смарт-процессов это снимает ловушку: в записи есть ещё и внутреннее поле `id`, которое в
адресах операций не участвует, — раньше при отборе полей оставалось именно оно, и адрес,
собранный по нему, приводил к другой записи.

На остальных сущностях правило прежнее и его стоит помнить: **если вы перечисляете поля в
`select`, перечисляйте и `id`** — методы Битрикс24, которые отбор уважают (сделки, контакты,
компании, лиды, предложения, элементы смарт-процессов), возвращают ровно запрошенное, и
незапрошенный `id` в ответ не попадёт.

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

Менять ничего не нужно, если `select` к адресам не передавался — ответ такой же, как раньше.
Вызов, который передавал `select` и рассчитывал получить полную запись, теперь получит только
запрошенные поля: это и есть задокументированное поведение параметра, приведённое в
соответствие с остальными сущностями. Имена полей сверяйте с
[GET /v1/addresses/fields](/docs/entities/addresses/fields).

### BC-0820-12: подставленный токен бота проверяется по длине и алфавиту

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

**Было**

В `PATCH /v1/bots/:botId` можно было подставить любое значение `fields.botToken` — например `support-bot-2026`. Вызов отвечал `200`, портал принимал новый токен. Проверок длины и формы не было: кап в 40 символов Битрикс24 применяет при регистрации бота и при переводе его в режим вебхука, а на обычном обновлении — нет.

**Стало**

Подставленный токен проверяется до вызова портала: от 32 до 40 символов из алфавита `[A-Za-z0-9_-]`. Любое присутствующее в запросе значение, которое в эту границу не укладывается — короткое, пустое, с посторонними символами или вовсе не строка, — отбивается с `400` и кодом `BOT_TOKEN_INVALID`; портал при этом не вызывается и токен бота не меняется. Границы те же, что и при регистрации бота, а нижняя совпадает с длиной токена, который платформа выдаёт сама.

Причина в том, что этот же токен аутентифицирует события, которые Битрикс24 доставляет боту через платформу: короткий или угадываемый токен позволял бы подделать событие бота без всякой аутентификации.

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

Если вы подставляете токен сами, используйте случайное значение на 32 символа и длиннее (например 32 шестнадцатеричных символа) из алфавита `[A-Za-z0-9_-]`. Ничего не подставляете — делать нечего: токен выдаёт платформа, и он границу проходит. Окно поддержки прежнего поведения не предусмотрено намеренно: слабый токен и раньше оставлял бота нерабочим, потому что платформа такое значение у себя не сохраняла.

### FIX-0820-13: события бота, приходящие вебхуком без адреса портала, больше не теряются

**Было**

Приёмник событий ботов на платформе опознавал бота по паре «портал + номер бота»: номер бота — внутренняя последовательность портала, а не глобальный идентификатор, поэтому портал приходилось определять по `auth.domain` или `auth.member_id` из тела запроса. У бота, зарегистрированного через входящий вебхук, ни одно из этих полей не является надёжным: адрес портала приходит не в каждом конверте, а `member_id` опознаётся только у порталов, у которых он известен платформе. Событие без адреса портала приёмник отбивал `403 AUTH_FAILED`, а повторных отправок у imbot-вебхуков нет: сообщение пользователя терялось безвозвратно, и на стороне платформы это выглядело как «боту ничего не писали».

**Стало**

Бот опознаётся по `auth.application_token` с верхнего уровня — для вебхук-бота это значение само по себе указывает на конкретного бота, портал для этого больше не нужен. Прежний путь по домену сохранён и работает как раньше: он обслуживает регистрации, у которых токен приходит в другой форме. Проверка подлинности токена не ослаблена — сравнение осталось constant-time, а событие с чужим номером бота в теле по-прежнему отбивается.

Заодно у отбивок приёмника появились отдельные коды — `BOT_WEBHOOK_AUTH_FAILED`, `BOT_WEBHOOK_ID_MISMATCH`, `BOT_WEBHOOK_INVALID_BOT_ID`, `BOT_WEBHOOK_BOT_DISABLED`.

**Ещё одно изменение в `PATCH /v1/bots/:botId`**

Токен, подставленный вызывающим в `fields.botToken`, теперь записывается и на стороне платформы. Раньше он уходил только в Битрикс24, а платформа оставалась на прежнем значении — бот молча становился нерабочим в обе стороны: исходящие вызовы получали `401`, входящие события отбивались.

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

Действий не требуется. HTTP-коды ответов приёмника не изменились (`403` / `400` / `410`), поле `error` в теле осталось прежним — рядом с ним добавилось поле `code`. Ботам, чьи события раньше отбивались, доставка включается сама, без перерегистрации и без смены токена.

### FIX-0820-14: порталу уходят только права Битрикс24, а платформенный ключ не получает вебхук при перевыпуске

**Было**

При выписке вебхука на портал уходил не только набор прав Битрикс24, но и платформенные права Вайбкода — `vibe:infra`, `vibe:ai`, `vibe:search`, `vibe:storage`. Битрикс24 таких прав не знает и молча их игнорировал, поэтому реальные права ключа от этого не менялись, но набор на проводе у разных способов выписки был разный: кабинет отправлял одно, `POST /v1/keys` — другое, коробочный канал — третье.

Из того же расхождения следовал видимый эффект на перевыпуске секрета. Ключ, у которого в наборе только платформенные права, вебхука на портале не получает — регистрировать нечего. Но перевыпуск такого ключа отправлял на портал набор из одних платформенных прав, и в ответ приходил вебхук, которого у ключа до перевыпуска не было: поле `b24Ready` менялось с `false` на `true`, хотя обращаться к Битрикс24 этим ключом по-прежнему было нельзя.

**Стало**

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

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

Форма ответа, коды ошибок и хранимый набор прав ключа не изменились: `vibe:*` по-прежнему видны в `scopes` и по-прежнему открывают платформенные разделы `/v1/ai`, `/v1/search`, `/v1/storage`, `/v1/infra`. Действий не требуется. Отличие заметит только тот, кто перевыпускал ключ без прав Битрикс24 и ожидал у него `b24Ready: true` — теперь такой ключ честно отвечает `false`, как и при создании.

### FIX-0820-15: на международном сегменте отказ по тарифу называет план Vibe+

**Было**

Порталу на бесплатном тарифе Битрикс24 приходил отказ `INT_TARIFF_REQUIRED`, и его
`userMessage` называл условием доступа платный тариф Битрикс24. Страница цен при этом
говорит, что полный доступ к платформе Вайбкод открывает план линейки Vibe+ — клиент
читал два разных условия в одном продукте.

**Стало**

На международном сегменте `userMessage` этого кода называет план Vibe+ — то же условие,
что на странице цен. Затронуты все поверхности кода: тело отказа при создании и
пробуждении инфраструктуры и слот `capabilities.servers.create` в `GET /v1/me`.

Машинное поле `details.requiredTariffs` не изменилось: оно по-прежнему перечисляет тарифы,
которые снимают отказ. Совет о покупке строится по нему, человеческая строка объясняет
причину. Сам код отказа, его HTTP-статус и структура конверта не изменились.

Порталы Казахстана и Узбекистана, самохостящиеся аккаунты и российский сегмент получают
прежнюю копию — линейку Vibe+ там не продают.

### NEW-0820-16: именной промокод — код срабатывает только у адресата

**Было**

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

**Стало**

Код можно выпустить на конкретную почту. Такой код проверяется по почте аккаунта
Вайбкод: не совпала — `POST /v1/cowork/coupon/redeem` отвечает `409` с кодом
`COUPON_NOT_ASSIGNED_TO_YOU`, а сам код остаётся неизрасходованным и по-прежнему
доступен адресату. Предпросмотр `POST /v1/cowork/coupon/preview` возвращает тот же код
в поле `reason`.

Коды без адресата ведут себя как раньше — их погашает любой сотрудник портала.

### FIX-0820-18: отзыв ключа закрывает и выданные им ссылки доступа

**Было**

`PATCH /v1/keys/:id` со статусом `REVOKED` гасил сам ключ, но не трогал токены доступа, которые этот ключ успел выписать: постоянные ссылки на приложение и bearer-токены продолжали работать до собственного срока годности, а он доходит до десяти лет. Владелец отзывал ключ и считал доступ закрытым, хотя ссылки оставались живыми.

**Стало**

Отзыв гасит выданные ключом токены доступа вместе с ним и снимает их в шлюзе. Поведение совпало с удалением ключа, где так было всегда, и одинаково на обеих поверхностях — через API и через кабинет. Ссылки, выданные ключами, которые отозвали РАНЬШЕ этого обновления, тоже закрыты. Прочие изменения ключа (имя, лимит, режим доступа) токены по-прежнему не трогают.
