Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-08-06.md индекс документации — /llms.txt
Изменения API: 6 августа 2026
← Журнал изменений · Август 2026
NEW-0806-1: 402 при исчерпанной квоте Cowork/Code несёт заголовок Retry-After
Ответ 402 с кодом cowork_quota_exhausted на POST /v1/chat/completions теперь несёт заголовок Retry-After — число секунд до сброса исчерпанного окна квоты (5h, week или month). Раньше момент сброса был виден только в поле resetAt тела ответа; заголовок понимают и обычные HTTP-клиенты без разбора тела. Ответ 402 с кодом insufficient_balance заголовок не несёт — у пустого баланса нет времени сброса.
FIX-0806-2: Веб-поиск: статус ответа различает отказ ключа провайдером и сбой провайдера
Было
Любая ошибка поискового провайдера в POST /v1/search приходила как 502 UPSTREAM_ERROR — и отказ провайдера принять ключ (401/403), и его троттлинг (429), и настоящий сбой. Клиенты повторяли запросы, которые не могли пройти.
Стало
Для BYOK-ключа ответы провайдера 401 и 403 сохраняют свой статус — провайдер отверг ваш ключ, замените его. Ответ провайдера 429 сохраняет статус для любого ключа и несёт заголовок Retry-After. Код ошибки во всех случаях остаётся UPSTREAM_ERROR, а тело дополнительно несёт поле upstream_status с исходным статусом провайдера. Остальные ошибки провайдера, включая отказ ключа платформенного движка, по-прежнему приходят как 502. Дополнительно ограничена длина поля message в ответе 400 INVALID_REQUEST — присланное значение больше не отражается целиком.
Влияние на интеграторов
Обработчик, который повторял запрос на любой 5xx, продолжает работать. Если вы ветвились на 502 как на «любую ошибку провайдера», добавьте ветки для 401/403 (замените BYOK-ключ) и 429 (повторите по Retry-After); надёжный признак «это ошибка провайдера, а не авторизации» — поле upstream_status в теле.
FIX-0806-3: реестр операций в GET /v1/guide перечисляет то, что действительно работает
Было
Список операций сущности в GET /v1/guide расходился с набором работающих эндпоинтов сразу в двух направлениях.
Он молчал о рабочих операциях. Ни одна сущность не объявляла fields, хотя
GET /v1/{entity}/fields отвечает у 46 из 49 сущностей. У бронирований
отсутствовали list и search, хотя GET /v1/bookings и POST /v1/bookings/search
обслуживаются отдельными обработчиками, — робот читал сущность как «только на запись»
и не мог получить идентификатор. У конфигураций открытых линий отсутствовали
list, search, create, update и delete — в реестре оставались только
getById, aggregate и batch. Тем же механизмом были скрыты create шаблонов
документов, list и create адресов, search узлов оргструктуры и delete
пользователя, а у поиска адресов реестр печатал описание общего оконного поиска,
которого этот обработчик не выполняет.
И он обещал то, чего у сущности нет: пример пакетного вызова у восьми сущностей
называл действие create, которое для них возвращает 400 ACTION_NOT_SUPPORTED.
Стало
Операция объявлена ровно тогда, когда её маршрут действительно зарегистрирован.
Появились fields у сущностей, где этот маршрут есть, list и search у
бронирований (с обязательными параметрами dateFrom и dateTo в описании),
полный набор list / search / create / update / delete у конфигураций
открытых линий, create у шаблонов документов, list / search / create у
адресов, search у узлов оргструктуры и delete у пользователя. Описания этих
операций перечисляют параметры, которые читает их собственный обработчик, а не
общий контракт поиска: оконного поиска (autoWindow, windowCount) у них нет.
Пример пакетного вызова называет действие, которое сущность принимает, и ключ,
который читает это действие: ids для удаления, items для остальных записей,
calls для чтения. У сущности без доступных операций записи пример читающий.
Заметка у такой сущности больше не перечисляет набор чтения одной строкой-константой
«принимаются list, get, fields»: она называет действия, которые у ЭТОЙ сущности
действительно отвечают данными, и отдельно — что конверт делает с остальными. Причин
слепоты три: fields у сущности без метода схемы полей отвечает пустым объектом (и
заметка ведёт к GET /v1/{entity}/fields, если этот маршрут есть); get у сущности без
адресного метода чтения отдаёт первую запись коллекции, а не запрошенную; у сущности на
REST 3.0 пакетный подвызов вообще не доходит до метода и возвращает пер-вызовную ошибку
внутри 200; а list у конфигураций открытых линий уходит в Битрикс24 без конверта,
которого требует imopenlines.config.list.get, и отвечает 200 со всей коллекцией,
молча выбросив фильтр.
То же утверждение исправлено ещё в двух местах, где клиент его видит: тело отказа
400 ACTION_NOT_SUPPORTED больше не заканчивается фразой «Supported batch actions: list,
get, fields» (теперь там тот же вычисленный набор — прежде клиент, прочитавший честный
реестр и споткнувшийся об отказ, получал вводящий в заблуждение список назад), и описание
пакетного чтения конфигураций открытых линий в схеме OpenAPI: список принимаемых действий
там сохранён, но сказано, какие из них отвечают данными.
Там же исправлено описание select у списка конфигураций открытых линий: перечисление
через запятую (?select=id,name) читается, не читается только форма с индексом
(?select[0]=id).
Сущность, у которой операции нет, её и не получает: fields не появился у
комментариев к задачам, у разделов календаря и у почтовых ящиков. Осталось необъявленным и то, что
объявлять не следует: маршруты, существующие только чтобы отбить вызов с указанием
верного пути, и aggregate у сущности, где работает лишь подсчёт, — про него
по-прежнему сообщает описание поиска.
Влияние на интеграторов
Изменение аддитивное: прежние поля operations не переименованы и не удалены.
Клиент, который строил список доступных вызовов по этому реестру, теперь видит
операции, которые раньше приходилось угадывать или искать в документации. Клиент,
который копировал пример пакетного вызова как есть, перестанет получать
400 ACTION_NOT_SUPPORTED на сущностях только для чтения.
FIX-0806-4: служебные поля задачи принимаются на записи — так же, как их принимает сам Битрикс24
У задачи семь служебных полей: постановщик (createdBy), кто изменил (changedBy), кто закрыл (closedBy), кто изменил статус (statusChangedBy), а также даты создания, изменения и закрытия (createdDate, changedDate, closedDate). Битрикс24 принимает и сохраняет их все — и при создании задачи, и при обновлении. Вайбкод отклонял шесть из семи, то есть был строже платформы на ровном месте.
Было
POST /v1/tasks и PATCH /v1/tasks/:id отвечали 400 READONLY_FIELD на changedBy, closedBy, statusChangedBy, createdDate, changedDate, closedDate и до Битрикс24 не доходили. Так же отклонялись написания верхним регистром — CHANGED_BY и остальные. Отказ приходил и в подзапросе POST /v1/batch. Седьмое поле, createdBy, при создании работало, а при обновлении отклонялось.
Стало
Все семь принимаются на обеих операциях и на всех трёх поверхностях записи — одиночный маршрут, пакетный запрос сущности и общий пакетный запрос. Принимаются оба написания, createdBy и CREATED_BY. Значение применяется в пределах прав вызывающего пользователя: если Битрикс24 отказывает в правке задачи, отказ приходит как есть — 422 с его собственным текстом, без подмены на нашу ошибку и без ложного успеха.
Смену постановщика Битрикс24 пишет в журнал изменений задачи, и там остаётся настоящий вызывающий пользователь. Для остальных шести полей записи в журнале не предусмотрено. Ещё одна тонкость — у трёх дат значение без часового пояса в написании createdDate получает смещение из заголовка X-Vibe-Timezone, а в написании CREATED_DATE уходит как есть. Обе тонкости разобраны на странице PATCH /v1/tasks/:id.
Что НЕ изменилось: id по-прежнему отклоняется — Битрикс24 присваивает идентификатор сам и переданное значение игнорирует, поэтому явный отказ честнее молчаливой потери. dateStart, activityDate и realStatus тоже остаются закрытыми, но по другой причине: их поведение на записи мы не проверяли, а объявлять поле открытым без проверки не станем.
Передавайте только существующего сотрудника — во всех четырёх полях с идентификатором пользователя. Битрикс24 не проверяет значение на существование и запишет любое число, а задача с несуществующим постановщиком перестаёт управляться через API: отказ приходит и на дальнейшее обновление, и на удаление, причём даже ключу администратора и напрямую в Битрикс24, минуя нас. Предупреждение добавлено на страницу обновления задачи.
Влияние на интеграторов
Ничего менять не нужно: запросы, которые раньше отклонялись, теперь выполняются. Если ваш код полагался на 400 READONLY_FIELD как на защиту авторства и истории — эту роль он не играл: те же значения принимает сам Битрикс24 по своему интерфейсу, в обход нашего слоя. Ограничить подмену служебных полей может только модель прав Битрикс24 — это отдельная доработка на стороне платформы. У лидов и сделок поле автора закрыто по-прежнему, и это не изменилось: там Битрикс24 значение молча игнорирует, поэтому явный отказ остаётся честным ответом.
FIX-0806-5: карточка приложения в каталоге открывает подпуть, а не корень сервера
Было
Карточка приложения в каталоге Битрикс24 всегда открывала корень Black Hole-сервера. Приложение, которое отдаёт интерфейс из подкаталога, из каталога открыть было нельзя: переход отвечал HTTP 200 и показывал то, что живёт в корне того же сервера. Адрес приложения (appUrl) на это никак не влиял, а его правка через PATCH /v1/apps/:id до карточки не доходила.
Стало
Карточка ведёт по полному адресу связанного приложения вместе с подпутём, query и fragment, если этот адрес указывает на тот же поддомен Black Hole, что и сервер карточки. Во всех остальных случаях — прежний корень сервера: другой поддомен, свой домен, другая схема, пустой или неразбираемый адрес.
Правка appUrl через PATCH /v1/apps/:id теперь ставит карточку в очередь на обновление, поэтому новый адрес доезжает до Битрикс24 сам. Уже опубликованные карточки тоже обновлены — от интегратора действий не требуется.
Влияние на интеграторов
Ничего менять не нужно. Приложение, отдающее интерфейс из корня, работает как прежде. Приложение в подкаталоге больше не требует ручного обхода: достаточно, чтобы appUrl содержал нужный подпуть.
FIX-0806-6: распознавание речи сообщает о временной паузе провайдера
Было
При временной недоступности кластера POST /v1/audio/transcriptions мог отвечать 502 ai_provider_unavailable, не сообщая клиенту, сколько ждать перед повтором.
Стало
В этом состоянии метод отвечает 429 ai_provider_cooldown с заголовком Retry-After в секундах. Запрос не выполняется и не списывает квоту или деньги. Дождитесь указанного интервала и повторите тот же запрос.
FIX-0806-7: распознавание речи действительно ждёт ответа заявленные 15 минут
Было
Для длинной записи POST /v1/audio/transcriptions мог ответить 503 ai_provider_timeout примерно через 5 минут, хотя в описании метода заявлено ожидание до 15 минут. В тексте ошибки при этом говорилось о сетевом таймауте.
Стало
Метод ждёт ответа весь заявленный срок — до 15 минут — и отвечает 503 ai_provider_timeout с заголовком Retry-After только по его истечении. Ограничение на длительность записи не изменилось: для файлов длиннее ~30 минут по-прежнему разбивайте запись на части.
FIX-0806-8: exec для galaxy-приложения обращается к контейнеру по его настоящему имени
Было
POST /v1/infra/servers/{id}/exec для приложения в галактике всегда обращался к контейнеру по имени из subdomain. Приложение, восстановленное из клона, работает под другим именем, поэтому команда уходила к контейнеру, которого нет: вызов завершался ошибкой, а в неудачном случае мог попасть в оставшийся от прежнего развёртывания контейнер. Остальной жизненный цикл галактики (развёртывание, переезд, остановка) уже учитывал переименование — расходился только exec.
Стало
Имя контейнера резолвится единым правилом для всех операций: используется имя на хосте, если приложение переименовано, иначе subdomain. Имя дополнительно проверяется перед подстановкой в команду; при непригодном имени возвращается 409 GALAXY_APP_NOT_READY с текстом invalid on-host name вместо запуска команды. Для приложений, которые не восстанавливали из клона, поведение не меняется.
BC-0806-9: V1: статус сервера в JSON всегда строчными буквами
Поддержка старого формата до: 06.09.2026
Было
GET /v1/infra/servers и GET /v1/infra/servers/:id отдавали status строчными (running, sleeping), а POST /v1/infra/servers/:id/wake, POST /v1/infra/servers/:id/refresh, поле currentState.status в ответах 422 у POST /v1/infra/servers/:id/start, POST /v1/infra/servers/:id/stop, POST /v1/infra/servers/:id/reboot и infra.unhealthyServers[].status в GET /v1/me — значение перечисления как в базе, ЗАГЛАВНЫМИ (RUNNING, SLEEPING, PROVISIONING). Клиент, выучивший status === 'running' по документации и GET, ломался на ответах пробуждения и обновления состояния.
Стало
Во всех перечисленных полях публичного V1 JSON значение статуса сервера — строчные литералы: provisioning, running, stopped, sleeping, error, deleted. Поле data у обновления состояния по-прежнему строка, а не объект: сравнивайте data === 'running', не data.status. Поле blackholeStatus не изменилось — оно остаётся ЗАГЛАВНЫМИ (CONNECTED, DISCONNECTED, NONE).
Влияние на интеграторов
Замените сравнения с 'RUNNING' / 'SLEEPING' / 'PROVISIONING' и остальными заглавными значениями на строчные либо сравнивайте без учёта регистра. Читайте статус из структурных полей (data, currentState.status), а не из текста message / userMessage — там статус по-прежнему может встречаться заглавными.
NEW-0806-10: деплой galaxy-приложения по ссылке и по сохранённой версии
Раньше galaxy-приложение принимало только встроенный архив: source.url и source.versionId отклонялись с 400 GALAXY_DEPLOY_CONTENT_ONLY. Теперь POST /v1/infra/servers/:id/deploy принимает обе формы там, где платформа включила выкладку по ссылке для вашего аккаунта Битрикс24; где не включила — код GALAXY_DEPLOY_CONTENT_ONLY возвращается как прежде, и встроенный source.content продолжает работать всегда.
Ссылку скачивает сам хост, поэтому архив не проезжает через тело запроса: потолок на встроенный архив (413 GALAXY_UPLOAD_TOO_LARGE) на этот путь не распространяется, и слот одновременных «толстых» запросов (429 DEPLOY_BACKEND_BUSY) он не занимает. source.versionId выкладывает версию, уже лежащую в хранилище исходников: платформа сама минтит подписанную ссылку и связывает версию с этим деплоем, поэтому в истории видно, что именно уехало в прод.
Ссылка у galaxy-приложения ведёт только в хранилище исходников — подойдёт подписанная ссылка сохранённой версии. Сторонний адрес отклоняется кодом 400 GALAXY_SOURCE_URL_NOT_ALLOWED, поэтому крупный архив сначала сохраняют версией, а выкладывают по source.versionId. У отдельной виртуальной машины такого ограничения нет.
Создание сервера с источником (POST /v1/infra/servers) принимает source.url на тех же условиях. source.versionId там не принимается: сервера, чьё хранилище задавало бы область поиска версии, в момент создания ещё нет — выкладывайте версию вторым шагом, через /deploy.
FIX-0806-11: справочник полей элементов смарт-процессов больше не показывает поле contacts
Было
GET /v1/items/:entityTypeId/fields показывал поле contacts с типом crm_contact. Значения по нему не приходило ни в списке, ни в карточке элемента, а записать его было нельзя: Битрикс24 принимал только пустой массив, а любое непустое значение отклонял ошибкой своего внутреннего слоя данных. Поле попадало в справочник сквозным пробросом схемы Битрикс24, а не объявлялось платформой.
Стало
Поле убрано из справочника. Привязанные контакты читаются и пишутся через contactId и contactIds — они не изменились. Фильтр и сортировка по contacts как и раньше отклоняются с кодом UNKNOWN_FILTER_FIELD и UNKNOWN_SORT_FIELD.
Влияние на интеграторов
Действий не требуется: значения по полю не существовало, поэтому клиент, читавший его, всегда получал пустоту. Если вы строили модель данных по справочнику — уберите contacts из неё и опирайтесь на contactIds.
FIX-0806-12: справочник полей страниц сайта сообщает, какие поля могут быть пустыми
Было
Ответ GET /v1/pages/fields не позволял отличить поле, у которого значение есть всегда, от поля, приходящего null. Вдобавок два описания обещали не то, что приходит: datePublic описывался как «приходит пустым объектом», а dateCreate, dateModify и datePublic — как дата фиксированного шаблона. Клиент, написавший разбор по этим описаниям, спотыкался на пустом значении, а фильтр по дате в чужом формате возвращал пустой список с кодом 200.
Стало
Девять полей, которые Битрикс24 заполняет не всегда, помечены признаком nullable: description, xmlId, tplId, tplCode, folderId, searchContent, initiatorAppCode, rule, datePublic. Набор получен замером по всей коллекции страниц живого портала, а не выведен из описания метода Битрикс24.
datePublic описан честно: обёртка отдаёт null, и это обычное значение даже для опубликованной страницы, поэтому факт публикации читайте из active или public. Описания dateCreate, dateModify и datePublic больше не обещают фиксированный шаблон: это строка в формате локали портала, одинаковая в списке и в карточке. Тот же формат нужен и в фильтре: значение в формате другой локали или в ISO Битрикс24 не распознаёт и возвращает пустой список с кодом 200.
Тем же признаком помечены поля в генерируемой схеме OpenAPI: там тип теперь записан как ["string", "null"], поэтому клиент, который валидирует ответ по схеме, больше не падает на пустом значении. Контракт записи не затронут.
Влияние на интеграторов
Действий не требуется: состав полей, типы и значения не изменились — добавился только признак nullable и уточнились описания. Если вы определяли публикацию страницы по наличию datePublic, переключитесь на active или public.
NEW-0806-13: отказ по лимиту ключей называет числа
POST /v1/apps при отказе KEY_LIMIT_REACHED (409) теперь кладёт в
error.details состояние квоты: limit — сколько ключей на человека разрешил
администратор портала, used — сколько занято сейчас.
Было
{
"success": false,
"error": { "code": "KEY_LIMIT_REACHED", "message": "Maximum number of API keys reached" }
}
Стало
{
"success": false,
"error": {
"code": "KEY_LIMIT_REACHED",
"message": "Maximum number of API keys reached",
"details": { "limit": 10, "used": 10 }
}
}
Поле аддитивное — клиенты, читающие только code, ничего не заметят. В used
входят и ключи, выписанные платформой (приложения, агенты, боты), поэтому число
может превышать длину списка из GET /v1/keys.
NEW-0806-14: справочники полей сайтов и сотрудников отдают подписи, описания и перечни значений
GET /v1/sites/fields теперь отдаёт подпись label и описание description у всех 22 полей — раньше они были только у поля type, а остальные 21 приходили с одним типом и признаком «только для чтения». Описания сообщают то, чего по типу не видно: что active через API не устанавливается, что code хранится в форме, обрамлённой слешами, что landingIdIndex/landingId404/landingId503 задаются только при обновлении, а dateCreate и dateModify приходят строкой в формате локали портала, а не в ISO 8601.
GET /v1/users/fields получил перечень допустимых значений enum у пола (personalGender: M, F) и у типа учётной записи (userType: employee, extranet, email) — каждое значение с английской подписью label и русской labelRu. Кроме этого подписи и описания появились у десяти полей рабочих сведений, у которых их не было в Битрикс24 вовсе и вместо подписи приходило само имя поля: WORK_FAX, WORK_PAGER, WORK_STREET, WORK_MAILBOX, WORK_STATE, WORK_ZIP, WORK_COUNTRY, WORK_PROFILE, WORK_LOGO, WORK_NOTES. Если портал такое поле подписал сам, его подпись сохраняется без изменений.
У пола появился ещё и признак nullable: true, а в схеме OpenAPI тип этого свойства объявлен как ["string", "null"]. Незаполненный пол приходит пустым (null) — на замеренном портале так отвечали 48 сотрудников из 50, — а схема без этого признака обещала строку и ничего кроме строки, поэтому клиент, проверяющий ответ по нашей же опубликованной схеме, получал ошибку почти на каждой записи. Признак описывает только чтение: в схеме тела запроса тип поля остался строкой.
Перечни значений приходят и в двух других машиночитаемых поверхностях — GET /v1/guide (блок fieldsDetailed сущности) и схема OpenAPI (x-enumValues у свойства). Подписи и описания объявленных полей схемы отдаёт только OpenAPI (title и description у свойства), поэтому клиент, сгенерированный по схеме, получает их без дополнительных вызовов; путеводитель подписи не несёт намеренно. Подписи и описания десяти полей рабочих сведений приходят только в самом справочнике полей.
Изменения аддитивные: ответы дополнены новыми ключами, набор полей и их значения те же, существующие интеграции продолжают работать без правок.
FIX-0806-15: разделы товаров: поле sort помечено «только для чтения» и «не возвращается»
Было
GET /v1/product-sections/fields объявлял sort записываемым, POST /v1/product-sections и PATCH /v1/product-sections/:id принимали его без ошибки, а Битрикс24 значение не сохранял. При этом ни один ответ на чтение — карточка, список, поиск, отклик создания — поле не содержал, даже если запросить его явно в select. Клиент получал «успех» и продолжал считать, что порядок задан.
Стало
Поле помечено только для чтения и notReturned: true. Запись sort в теле создания или обновления отклоняется с 400 READONLY_FIELD до вызова Битрикс24; в справочнике полей поле осталось видимым вместе с описанием причины, чтобы её можно было прочитать на месте. Упорядочивание по нему работает как раньше: ?sort=sort&order=asc и order=desc дают разный порядок. Фильтрация по sort по-прежнему отклоняется с 400 UNSUPPORTED_FILTER.
Влияние на интеграторов
Уберите sort из тела запросов создания и обновления разделов товаров — иначе запрос целиком получит 400 READONLY_FIELD вместо прежнего «успеха». Если код читал sort из ответа, его там никогда и не было: значение приходило undefined. Менять порядок разделов можно в интерфейсе Битрикс24, читать порядок — упорядочиванием списка по этому полю. Параллельная поддержка прежнего поведения не предусмотрена: прежнее поведение состояло в том, что значение молча терялось, — сохранять было бы нечего.
FIX-0806-16: у сайтов поле active стало только для чтения — включение идёт через публикацию
Было
GET /v1/sites/fields описывал active как обычное записываемое поле, и запрос с ним проходил: POST /v1/sites и PATCH /v1/sites/:id возвращали успех. Значение при этом терялось. Битрикс24 не принимает ACTIVE ни в landing.site.add, ни в landing.site.update — их контракт этого поля не объявляет, а новый сайт всегда создаётся неактивным. Живая проверка обоих вызовов подтвердила потерю: и создание с active: true, и обновление на active: true отвечали успехом, а признак оставался выключенным.
Стало
active помечено readonly. Передача его в теле создания или обновления отклоняется с 400 READONLY_FIELD до вызова Битрикс24. В ответе list/get и в справочнике /fields поле остаётся — читается оно по-прежнему, в том числе фильтрацией и группировкой по нему.
Активность сайта включается публикацией в интерфейсе портала Битрикс24.
Влияние на интеграторов
Если код передавал active в теле создания или обновления сайта — уберите его. Значение всё равно никогда не сохранялось, но теперь запрос отклоняется целиком, поэтому вместе с ним не применятся и остальные поля тела: название, символьный код, домен, описание. Параллельная поддержка прежнего поведения не предусмотрена: прежнее поведение состояло в том, что значение молча терялось, — сохранять было бы нечего.
FIX-0806-17: недоступный склад образов на сборке galaxy-приложения — временная ошибка, а не отказ
Было
Если публичный склад образов был недоступен в момент сборки, POST /v1/infra/servers/:id/deploy
отдавал 502 с сырым текстом Docker, а приложение помечалось как сломанное — повтор приходилось
запускать вручную, и подсказки в ответе не было.
Стало
Ответ несёт код GALAXY_BASE_IMAGE_UNAVAILABLE, признак retryable: true и поле hint с
инструкцией повторить тот же запрос через 2-3 минуты. Слот не помечается сломанным, поэтому
повтор ложится на него же. Для агентов платформа повторяет сама. Одношаговое создание с
исходниками (POST /v1/infra/servers с source) HTTP-ответа уже не держит, поэтому там
приложение по-прежнему помечается сломанным, но текст ошибки называет причину и просит повторить
развёртывание.
FIX-0806-18: отказ выписки при живой подписке больше не выдаёт «демо уже использована»
Было
Если Битрикс24 отказывал в выписке ключа или установке приложения по линии подписки, ответ строился по признаку «демо когда-то активировали». Признак остаётся поднятым всё время действия демо, поэтому портал с ДЕЙСТВУЮЩЕЙ демо-подпиской получал 403 B24_MARKET_TRIAL_USED и текст «демо-подписка уже использована, оформите платную» — при том, что подписка работала и покупать было нечего.
Стало
Пока подписка или демо действуют, отказ выписки отдаётся как 502 CONNECTOR_REST_UNAVAILABLE с текстом «повторите попытку / обратитесь в поддержку» и без предложения оформить подписку. В ответе есть error.details.reason (исходная причина отказа) и error.details.retryable: true. Если демо действительно израсходовано, ответ прежний — 403 B24_MARKET_TRIAL_USED; если подписки не было ни разу — 403 B24_MARKET_SUBSCRIPTION_REQUIRED. Затронут POST /v1/apps. Дополнительно: отказ вида «REST недоступен» повторяется автоматически один раз — это снимает гонку сразу после активации демо.
FIX-0806-19: платформа сообщает приложению его порт в переменной PORT
Было
Платформа согласовывала порт приложения на трёх уровнях — проброс публичного трафика, EXPOSE в образе и проверка работоспособности, — но самому приложению его не сообщала. Приложение, написанное по общей конвенции облачных платформ (listen(process.env.PORT)), получало пустое значение, занимало случайный свободный порт, и на нужном порту никто не слушал: шлюз отдавал «Приложение не обнаружено», хотя POST /v1/infra/servers/:id/deploy рапортовал успех.
Стало
Платформа передаёт номер порта в переменной окружения PORT — всегда равной полю port запроса (по умолчанию 3000). На отдельной виртуальной машине это отдельный платформенный файл .vibe-platform.env, который systemd-юнит подключает после вашего .env; ваш .env не читается и не перезаписывается. В приложении галактики PORT приходит в окружение контейнера при запуске. В ответе появился шаг platform_env.
Ключ PORT теперь зарезервирован платформой: если прислать свой env.PORT, отличный от поля port, платформа его перекроет и скажет об этом строкой в warnings[] ответа. Прислать совпадающее значение можно — предупреждения не будет.
Влияние на интеграторов
В обычном случае менять ничего не нужно: приложение, слушающее process.env.PORT, теперь работает без явного env.PORT, а уже работающие приложения получат PORT при следующем деплое. Есть одно исключение, и его стоит проверить: если вы держали в env.PORT не порт своего приложения, а что-то другое (порт базы, внешнего сервиса), — переименуйте эту переменную, потому что теперь PORT принадлежит платформе и ваше значение до приложения не дойдёт. В ответе на деплой в таком случае приходит предупреждение в warnings[]. Если вы читаете файл .env напрямую, а не переменные окружения процесса, — читайте process.env.PORT: платформенное значение живёт в отдельном файле. Со своим systemd-юнитом (systemd: false) платформенный файл создаётся, но подключаете его вы — пока не подключили, побеждает ваш env.PORT, и предупреждение в ответе говорит именно об этом; как подключить, описано в POST /v1/infra/servers/:id/deploy.
BC-0806-20: расход квоты отдаётся только в процентах
Поддержка старого формата до: 06.02.2027
Было
GET /v1/ai/quota возвращал в data.byModel[] абсолютные счётчики расхода — tokensIn, tokensOut и audioSeconds — рядом с долей лимита pctOfLimit.
{ "modelId": "bitrix/bitrixgpt-5.5", "calls": 1240, "tokensIn": 800000, "tokensOut": 350000, "audioSeconds": 0, "pctOfLimit": 1.2 }
Стало
Три поля убраны. Расход квоты — как и сам лимит — раскрывается только относительной величиной: pctOfLimit (доля месячного лимита, израсходованная моделью) и calls (количество вызовов).
{ "modelId": "bitrix/bitrixgpt-5.5", "calls": 1240, "pctOfLimit": 1.2 }
Что делать интеграторам
Авторитетная цифра по аккаунту одна — data.pctUsed: именно она считается по леджеру списаний и учитывает скидку за время суток. Разбивка byModel[].pctOfLimit показывает, КУДА ушла квота, и считается пересчётом журнала вызовов по действующим сейчас ценам, поэтому суммировать доли по моделям и сравнивать сумму с pctUsed не нужно — величины разойдутся. Если вам нужны токены для собственного учёта, берите их из GET /v1/ai/usage или снимайте на вызове модели: ответ POST /v1/chat/completions по-прежнему содержит блок usage с prompt_tokens и completion_tokens.
FIX-0806-21: исчерпанная квота Cowork/Code больше не обслуживается подменной моделью
Было
При исчерпании квоты Cowork/Code запрос от ключа десктопа обслуживался резервной моделью, причём инструменты (tools) и системный промпт запроса передавались ей без изменений. Модель отвечала связно и могла сообщить о выполненной работе, которой не было. Ответ приходил с кодом 200 и заголовком X-Cowork-Fallback: true.
Стало
Ответ один для всех ключей: tools, tool_choice и response_format снимаются, модель сообщает об исчерпанном лимите и о том, когда он сбросится. Код ответа 200 при настроенной резервной модели, иначе 402 cowork_quota_exhausted — как раньше. Заголовок X-Cowork-Fallback: true и предупреждение COWORK_QUOTA_FALLBACK остаются, но означают теперь «лимит объявлен», а не «запрос обслужен другой моделью».
Влияние на интеграторов
Не ожидайте tool_calls и структурированный ответ при исчерпанной квоте: response_format снимается, поэтому вернётся текст, а не JSON. Признак состояния — заголовок X-Cowork-Fallback, предупреждение COWORK_QUOTA_FALLBACK или код 402.
Отдельно исправлена дата обновления месячного лимита на бесплатном тарифе. Раньше resetAt.month (GET /v1/cowork/me), windows.month.resetAt и subscription.currentPeriodEnd (GET /v1/cowork/state) отдавали дату из строки подписки, а у бесплатного места она не сдвигалась после окончания периода — то есть приходила дата в прошлом, и отсчёт до обновления показывал «меньше минуты» бесконечно. Теперь все три поля отдают период, в котором место находится фактически: месячный счётчик обнуляется при первом обращении после окончания периода. В теле отказа 402 cowork_quota_exhausted поле resetAt для месячного окна больше не приходит равным 1970-01-01.
Влияние на интеграторов
Если вы кэшировали currentPeriodEnd бесплатного места как неизменную дату — перечитайте её: на просроченном месте она сдвинется вперёд.
FIX-0806-22: починка сервера сообщает причину отказа и больше не оставляет агента выключенным
Было
GET /v1/infra/servers/:id/repair-status при неудаче возвращал error без причины —
SSH install failed (exit 255); serial fallback: Serial console install failed. По этому
тексту нельзя было отличить закрытый порт от недоступной машины или от сорвавшегося
скачивания. Кроме того, установка агента останавливала работающий сервис ДО того, как
скачивала новую версию: если скачивание не удавалось (нет выхода в интернет, недоступен
адрес раздачи), агент оставался выключенным, а следующая попытка починки повторяла то же
самое.
Стало
error несёт причину: для обычного входа — сообщение SSH (Connection refused,
Connection timed out и т.п.), для установки через аварийную консоль — короткий отрывок
вывода консоли (например curl: (6) Could not resolve host: …). Отрывок очищен от
секретов и ограничен по длине. Установка теперь сначала скачивает новую версию агента и
только потом останавливает сервис, а при отказе любого последующего шага возвращает
агента в работу.
FIX-0806-23: выписка ключа проверяет доступ к платформе
Было
POST /v1/keys и POST /v1/apps выписывали новый ключ любому порталу, прошедшему авторизацию, — даже если доступ к платформе у портала закрыт. Ключ при этом работал: выписка проверку доступа не спрашивала.
Стало
Перед выпиской проверяется доступ портала. Порталу без доступа приходит тот же код, который он уже получает на других поверхностях, — MARKETPLACE_REQUIRED, KZ_PAID_ONLY, UZ_PAID_ONLY или INT_TARIFF_REQUIRED, в зависимости от региона лицензии.
Уже выданные ключи продолжают работать. Проворот ключа, автоматическое восстановление и передача владения не затронуты: клиент с закончившимся доступом должен уметь закрыть свои дела.
Влияние на интеграторов
Обработайте отказ на выписке так же, как на остальных поверхностях: оформите доступ и повторите запрос. Ранее выписанные ключи менять не нужно.
NEW-0806-24: понятный отказ, когда личному ключу оставили только placement или entity
Личный ключ работает через входящий вебхук Битрикс24, а тот не хранит права placement
и entity — они требуют контекста приложения. Раньше такой запрос падал невнятно: при
создании ключа приходил 502 DEVKEY_MINT_FAILED с советом обратиться к администратору
портала, при правке прав — 502 DEVKEY_SCOPE_SYNC_FAILED.
Теперь оба случая отвечают 400 PERSONAL_KEY_WEBHOOK_SCOPES_INVALID с текстом, который
говорит, что делать: добавить хотя бы одно обычное право (например crm или user_brief)
либо создать OAuth-приложение, если нужны встраивания.
Отказ приходит, только когда после отбрасывания этих двух прав не остаётся ни одного,
которое Битрикс24 может привязать к вебхуку. Смешанный набор (placement + crm)
по-прежнему проходит.
Затронутые эндпоинты: POST /v1/keys, PATCH /v1/keys/{id}, POST /v1/keys/{id}/rotate
Смежное изменение ответа: у личного ключа в поле scopes ответа на создание и правку
больше не возвращаются placement и entity — вебхук их всё равно не несёт, и раньше
ответ обещал право, которого у ключа нет. Ключи приложений и системные ключи не затронуты.
FIX-0806-25: сборка Python-приложения в галактике больше не падает на существующей версии пакета
Было
Деплой с runtime: python311* и requirements.txt падал с No matching distribution found for <пакет> — на версии, которая существует и ставится. Причина не в версии: контейнер собирался в изоляции и не знал про каталог пакетов, доступный из нашего облака. Рядом с этим текстом платформа не показывала ничего, и ошибка читалась как ваша.
Стало
Платформа задаёт образу каталог пакетов по умолчанию. Ваш собственный --index-url в requirements.txt или в команде установки по-прежнему сильнее нашего.
Если каталог всё же не ответит, error.category теперь INSTALL_REGISTRY_UNAVAILABLE (было GENERIC), а error.buildHint и одноимённое поле в GET /v1/infra/servers/:id несут понятную причину вместо пустоты. Значение аддитивное: прежние коды не менялись. Отказ терминальный — автоматически платформа его не повторяет.