Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-08-20.md индекс документации — /llms.txt

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

← Журнал изменений · Август 2026

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 мог сообщать персональному ключу права placement, entity и userfieldtype, хотя эти возможности требуют контекста OAuth-приложения. Создание и изменение ключа также принимало userfieldtype как обычное право.

Стало

GET /v1/me, создание и изменение персональных ключей исключают 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, выход из чата, передача владения — отвечали ошибкой 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 для REST не менялся: там по-прежнему нужно брать chat.dialogId, а не числовой chat.id. Запрос GET /v1/bots/:botId/chats/:dialogId и остальные действия принимают и 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 описан для всех сущностей, но у адресов он не делал ничего. Список, поиск и получение записи по составному ключу отвечали полной записью со всеми полями, сколько бы имён ни перечислил вызывающий, а незнакомое имя пропадало без следа — ни ошибки, ни предупреждения. Это была единственная сущность, где отбор полей молчал полностью.

Стало

Все три двери адресов применяют 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,… работал как ожидается. Но есть две, где ключ маршрута зовётся иначе, и отбор полей его выбрасывал: у смарт-процессов это 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.

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 и через кабинет. Ссылки, выданные ключами, которые отозвали РАНЬШЕ этого обновления, тоже закрыты. Прочие изменения ключа (имя, лимит, режим доступа) токены по-прежнему не трогают.