Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-09-18.md индекс документации — /llms.txt
Изменения API: 18 сентября 2026
← Журнал изменений · Сентябрь 2026
FIX-0918-1: фильтр и сортировка предложений по невозвращаемому полю contacts отвечают отказом платформы, а не ошибкой Битрикс24
Было
У предложений поле contacts помечено как не возвращаемое (item-API Битрикс24 никогда его не отдаёт, привязанные контакты — в contactIds), но ?filter[contacts]=…, ?sort=contacts и ?order[contacts]=… уходили в Битрикс24 и отвечали 422 BITRIX_ERROR с текстом Unknown field definition CONTACTS — словами Битрикс24, тогда как у компаний, лидов, сделок и счетов те же запросы отвечают 400 UNKNOWN_FILTER_FIELD / 400 UNKNOWN_SORT_FIELD.
Стало
У предложений filter, sort и order по contacts отклоняются до обращения к Битрикс24: 400 UNKNOWN_FILTER_FIELD и 400 UNKNOWN_SORT_FIELD, сообщение перечисляет допустимые имена — как у остальных сущностей CRM. Остальное поведение поля не изменилось: запись — 400 READONLY_FIELD, select — 400 SELECT_FIELD_NOT_RETURNED.
Влияние на интеграторов
Никакого: такие запросы не работали и раньше. Фильтруйте по contactId (основной контакт) или по contactIds.
Затронутые эндпоинты: GET /v1/quotes, POST /v1/quotes/search, POST /v1/quotes/aggregate, POST /v1/{entity}/batch, POST /v1/batch.
BC-0918-2: Участник команды разработки сервера получает собственный ключ, и у блока key появилось значение collaborator
Поддержка старого формата до: не предусмотрена
Было
Ключ приложения выдавал только владелец приложения, а slot в блоке key карточки принимал
auth, api или null. Маршруты разработки сервера отвечали участнику команды отказом.
Стало
Участник команды разработки сервера (сотрудник портала с ролью ADMIN или DEVELOPER) получает
собственный ключ через POST /v1/cowork/applications/:id/key и видит sources и
activeOperation чужого приложения. В карточке такой ключ приходит со значением
slot: "collaborator"; ключ владельца участнику не показывается. Ключ работает на тринадцати
парах маршрутов разработки своего сервера, включая снятие замка выкладки и короткие
api-bearer access-token с обязательным ttlSeconds не больше 600. Иконка сервера в перечень
не входит — она принадлежит владельцу и администратору. Режим share-url закрыт с
403 PORTAL_COLLABORATOR_TOKEN_MODE_FORBIDDEN, неверный TTL — 400 INVALID_TTL, отозвать можно
только свой токен (чужой отвечает 404). Новый ответ может содержать
COLLABORATOR_KEY_REQUIRES_SERVER, COLLABORATOR_MEMBERSHIP_BIND_CONFLICT,
PORTAL_COLLABORATOR_KEY_OUT_OF_SCOPE, PORTAL_COLLABORATOR_KEY_WRONG_SERVER,
PORTAL_COLLABORATOR_NOT_A_MEMBER и предупреждение ENV_SYNC_NOT_APPLICABLE_FOR_COLLABORATOR.
Что делать интеграторам
Если клиент разбирает slot закрытым перечнем, добавьте в него collaborator либо сводите
незнакомое значение к null. Обращение ключом участника к паре «метод + маршрут» вне перечня
ниже отвечает 403 PORTAL_COLLABORATOR_KEY_OUT_OF_SCOPE.
Затронутые эндпоинты: POST /v1/cowork/applications/:id/key,
GET /v1/applications,
GET /v1/applications/:id и тринадцать пар, на которых работает ключ
участника: GET /v1/infra/servers/:id,
POST /v1/infra/servers/:id/deploy,
POST /v1/infra/servers/:id/exec,
POST /v1/infra/servers/:id/upload,
GET /v1/infra/servers/:id/logs,
POST /v1/infra/servers/:id/wake,
GET /v1/infra/servers/:id/sources,
POST /v1/infra/servers/:id/sources,
GET /v1/infra/servers/:id/sources/:versionId,
GET /v1/infra/servers/:id/sources/:versionId/download,
DELETE /v1/infra/servers/:id/lock,
POST /v1/infra/servers/:id/access-tokens,
DELETE /v1/infra/servers/:id/access-tokens/:tokenId.
NEW-0918-3: Приложению из Коворка права можно не указывать
b24Scopes в POST /v1/cowork/applications стало необязательным. Поле пропущено — ключ
получает все права Битрикс24, которые может выдать этот портал: каталог без прав,
закрытых фича-флагом, плюс те из них, что порталу разрешены, минус права, которые
Битрикс24 не хранит на входящем вебхуке. Явный список по-прежнему принимается и нужен,
чтобы попросить МЕНЬШЕ прав; пустой массив отбивается как раньше — ключ без прав портала
расширить потом нечем. Молчанием такая выдача не остаётся: в warningCodes ответа приходит
B24_SCOPES_DEFAULTED_TO_ALL, а в журнале портала у записей о создании приложения и выдаче
ключа появилось поле scopesSource — default или explicit. Пропуск поля и явный полный список считаются разными телами:
отпечаток идемпотентности берёт тело как пришло, а не результат подстановки.
BC-0918-4: Поле envSync при замене ключа приложения-галактики возвращает реальный исход доставки
Поддержка старого формата до: 17.03.2027
Было — для приложения на платформе Вайбкод, чей сервер живёт контейнером в Галактике,
замена ключа с syncServerEnv: true всегда отвечала { "status": "skipped", "reason": "galaxy" }:
доставить ключ в контейнер платформа не умела, и поле сообщало только об этом.
Стало — платформа доставляет ключ в окружение контейнера, и поле возвращает исход этой
доставки: { "status": "recreated", "variable": "..." } (ключ доставлен, контейнер пересоздан
из того же образа; alsoBakedInImage: true добавляется, когда СТАРОЕ значение вдобавок зашито
в образ и продолжит отвечать до пересборки из исходников, а bakedVariable называет эту
переменную образа), { "status": "not_required" } (ключа платформы в окружении контейнера нет
вовсе), { "status": "baked_in_image", "bakedVariable": "..." } (ключ пришёл из образа, а не
задан при запуске: перекрыть переменную можно, окончательно лечит пересборка), { "status": "recreate_failed", "reason": "..." } (доставка
не удалась, причина в reason), { "status": "unreachable" } (хост Галактики или приложение
спит — ничего не тронуто), { "status": "not_found" } (в контейнере ключ неизвестного платформе
поколения), { "status": "superseded" } (доставку опередила более новая замена ключа) или
{ "status": "failed" } (платформа не смогла определить, куда доставлять ключ; исход общий для
обоих видов серверов, не только для галактических).
Прежний { "status": "skipped", "reason": "galaxy" } остаётся достижимым — он приходит, когда
доставка в контейнеры для аккаунта выключена.
Что делать интеграторам — разберите все перечисленные значения envSync.status, а не
только skipped. Ветка, считающая { "status": "skipped", "reason": "galaxy" } единственным
возможным ответом для приложения-галактики, теперь получает значения, которых не ожидает.
- Считайте ключ доставленным ТОЛЬКО на
recreated. Наrecreate_failed,unreachable,baked_in_image,failedиskippedв контейнере остался прежний ключ; наnot_foundплатформа не знает, какой ключ там стоит вообще — в окружении значение поколения, которого она не выписывала. В любом из этих случаев впишите ключ ЭТОЙ замены вручную, и успеть нужно доpreviousKey.graceUntilиз того же ответа. Срок не всегда сутки и бывает пустым:nullозначает, что отсрочки нет вовсе (прежний ключ заблокирован) и доступ уже потерян. superseded— особый случай: ключ этой замены уже вытеснен более новой заменой, и вписывать его в контейнер НЕЛЬЗЯ — так приложение получит устаревший ключ. Разбирайтесь по исходуenvSyncТОЙ, более новой замены и по её сырому ключу: секрет отдаётся один раз, в ответе на саму замену, и восстановить его потом нечем — карточка приложения отдаёт только метаданные. Того ответа под рукой нет — сделайте ещё одну замену с НОВЫМIdempotency-Keyи работайте по её ответу.- На
recreatedсalsoBakedInImage: trueи наbaked_in_imageдополнительно пересоберите приложение из исходников: старое значение зашито в образ (переменная названа вbakedVariable), и образ отдаст его снова на любом развёртывании без пересборки. Ручная запись переменной из пункта 1 действует — она перекрывает значение образа, — но перекрытие живёт лишь до следующего развёртывания: пересборка лечит окончательно, ручная запись только закрывает срокpreviousKey.graceUntil. - Незнакомое значение
statusсчитайте недоставленным ключом, а не успехом: набор исходов будет пополняться.
Сама замена ключа по-прежнему завершается успешно независимо от исхода envSync, а
пересоздание контейнера перезапускает приложение и рвёт его открытые соединения на время
перезапуска. Прежний ответ { "status": "skipped", "reason": "galaxy" } остаётся достижимым
и в течение окна поддержки: он приходит, когда доставка в контейнеры для аккаунта выключена.
Затронутые эндпоинты: POST /v1/cowork/applications/{id}/key
FIX-0918-5: загрузка иконки отличает отказ в правах от отсутствующего сервера
Было
POST /v1/infra/servers/:id/icon отвечал 404 SERVER_NOT_FOUND и тогда, когда сервер на портале есть, но привязан к другому API-ключу. Отказ в правах был неотличим от опечатки в id или удалённого сервера: ключ, которым проходят GET /v1/infra/servers/:id, выкладка и депонирование исходников, получал на иконке «сервера нет» — без указания, что именно не так и как это исправить.
Стало
Иконка отвечает тем же кодом, что и остальные операции контрол-плейна: сервер есть на вашем портале, но управляет им другой ключ — 403 WRONG_KEY, и в теле приходит error.hint с порядком восстановления (перепривязать сервер в кабинете, затем отправлять новый ключ в заголовке X-Api-Key). 404 SERVER_NOT_FOUND остаётся ровно на прежних основаниях: сервера с таким id нет, он удалён либо принадлежит другому порталу. Права загрузки не изменились — иконка по-прежнему требует управляющего ключа, потому что едет на карточку приложения в каталоге. Подробности — Иконка приложения и Восстановление доступа к серверу.
FIX-0918-6: внешний API приложения доходит до приложения, а не отвечает «недоступно»
Было
Канал ANY /v1/applications/{id}/api/* отвечал 503 с кодом APP_API_UNAVAILABLE и
сообщением «Application is not reachable» на каждый вызов, прошедший проверки допуска, —
даже когда приложение было запущено и открывалось из кабинета и по ссылке внешнего доступа.
Отказ приходил мгновенно, без заголовка X-Vibe-Request-Id, и не зависел от размещения
приложения.
Стало
Вызов доходит до приложения: ответ приложения отдаётся как есть — его собственный HTTP-статус,
заголовки и тело сохраняются, успешный вызов остаётся успешным. Транзиентный 503
APP_API_UNAVAILABLE с Retry-After теперь означает ровно то, что заявлено в описании
канала, — приложение действительно не отвечает, а не «канал не работает вообще».
FIX-0918-7: ход с вызовом функции больше не дублирует рассуждение в content
Было
Когда модель с рассуждением вызывала функцию, ответ POST /v1/chat/completions без потока приходил с finish_reason: "tool_calls", рассуждением в reasoning_content и той же цепочкой ещё и в content: клиент получал рассуждение модели как реплику ассистента. В потоке рассуждение в content не попадало.
Стало
У хода с вызовом функции content равен null, рассуждение приходит только в reasoning_content, как в примере вызова функций. Ответы без рассуждения и ответы с итоговым текстом не изменились.
Затронутые эндпоинты: POST /v1/chat/completions.
FIX-0918-10: аккаунт, тариф которого не спрашивали, больше не получает отказ «нужен платный тариф»
Было
Отказ 403 PORTAL_TARIFF_UNREADABLE («тариф прочитать не удалось») выносился, только если последняя проба лицензии закончилась с записанным неудачным исходом. Аккаунт, у которого кода тарифа нет И исхода пробы нет вовсе — пробы не было либо она прошла до появления этой метки, — попадал в прежнюю ветку и получал 402 с советом подключить платный тариф Битрикс24. Совет опирался на пустой код тарифа, а пустой он и у аккаунта, чью лицензию платформа ни разу не спрашивала.
Стало
Оба состояния «спросить не удалось» разведены с «аккаунт на бесплатном тарифе» одинаково: кода тарифа нет И проба либо провалилась, либо не записана — ответ 403 с кодом PORTAL_TARIFF_UNREADABLE, details.requiredTariffs пуст, а details.upgradeUrl и alternatives[0].url ведут в поддержку. Аккаунт с УСПЕШНО прочитанной лицензией поведение не меняет: пустой код при успешной пробе по-прежнему означает бесплатный тариф и по-прежнему отвечает 402 с прежним текстом.
FIX-0918-11: отказ доступа отличает непрочитанную подписку от её отсутствия
Было
Аккаунт, состояние подписки которого платформа Вайбкод прочитать не смогла, получал на создании сервера и на выписке ключа 402 с кодом MARKETPLACE_REQUIRED и предложением оформить подписку. Совет мог быть неверным: состояние подписки приезжает только в конверте market пробы лицензии, а её отдаёт ключ разработчика участника аккаунта — ключу с узким набором прав Битрикс24 отвечает отказом, и тогда аккаунт с действующей подпиской выглядел для платформы так же, как аккаунт без неё.
Стало
Эти два состояния разведены. Если состояние подписки прочитать не удалось, ответ теперь 403 с кодом PORTAL_SUBSCRIPTION_UNREADABLE: поле details.requiredTariffs пустое — покупка этот отказ не снимает, — а details.upgradeUrl и alternatives[0].url ведут в поддержку. Поле userMessage называет исполнимое действие: переподключить приложение под главным администратором аккаунта, чтобы ключ разработчика получил права на чтение лицензии. Код MARKETPLACE_REQUIRED остаётся за своим состоянием — подписка прочитана, и её нет: там по-прежнему 402 и прежний текст. Доступ этой правкой никому не открывается: отказ остаётся отказом, меняются код, статус и предлагаемое действие.
NEW-0918-12: сервер можно создать сразу в нужном режиме работы
POST /v1/infra/servers принимает необязательный блок runMode той же формы, что и
PATCH /v1/infra/servers/{id}/run-mode: {"mode": "ALWAYS"}, {"mode": "IDLE", "idleMinutes": 60}
или {"mode": "SCHEDULE", "scheduleId": "..."}. Машина рождается уже в этом режиме — «создать, а
потом переключить» стоило лишнего вызова, а машине — часов работы по умолчанию, за которые уже идёт
счёт.
Отказ приходит до создания, поэтому неудачный запрос не оставляет машину: WORK_SCHEDULE_NOT_FOUND
— расписания с таким идентификатором в аккаунте нет, WORK_SCHEDULE_EMPTY — у расписания нет ни
одного окна, RUN_MODE_UNAVAILABLE — режимы работы для аккаунта ещё не включены. Тело разбирается
по полю mode, поэтому лишнее поле рядом с режимом отвергается, а не выбрасывается молча. Запрос
без блока runMode работает как прежде.
NEW-0918-13: потолок хранилища и числа ключей у аккаунта без коммерческого тарифа
У аккаунта Битрикс24 без коммерческого тарифа появились два необязательных потолка, включаемых платформой: на объём хранилища и на число живых ключей аккаунта. Аккаунт на коммерческом тарифе — и любой, который когда-либо был на нём, — потолков не получает.
Запись в хранилище, которая выводит аккаунт за потолок объёма, отвечает 507 с кодом STORAGE_QUOTA_EXCEEDED. Выписка ключа сверх потолка их числа отвечает 409 с уже существующим кодом KEY_LIMIT_REACHED; в объекте details такого ответа добавлено поле scope со значением portal — по нему потолок аккаунта отличается от лимита на одного сотрудника, у которого поля scope нет. Поле аддитивно: клиент, который его не читает, разницы не заметит. Запросы под потолком отвечают ровно как прежде.