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

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

← Журнал изменений · Сентябрь 2026

FIX-0908-1: склады не подставляют чужой номер и открыто отказывают в неподдерживаемом фильтре

Было

Номер склада в адресе запроса читался нестрого: GET /v1/warehouses/12.5 не отклонялся, а тихо превращался в 12, и чтение, изменение или удаление уходило в другой, реально существующий склад под видом успеха. Так же вели себя 12abc, 1e2, 007, номер с пробелом и номер за пределом точности целых чисел; то же нестрогое чтение применялось к productId и limit. Параметр filter[] на списке складов, на остатках склада и на сводке остатков не читался вовсе: любое условие — и выдуманное, и настоящее имя поля — молча игнорировалось, а в ответ приходил полный список. В описании API семь операций складов и операция агрегации объявляли единственный вариант ответа — успех, а удаление склада было объявлено ответом 200, хотя отвечало пустым 204.

Стало

Номер склада, productId и limit принимаются только в канонической форме — одни цифры, без знака, ведущего нуля, дроби и экспоненты, в пределах точности целых чисел. Всё прочее отклоняется кодом 400 INVALID_PARAMS до обращения к Битрикс24, поэтому опечатка в номере больше не может попасть в чужой объект. Переданный filter[] на трёх перечисленных ручках отклоняется кодом 400 UNSUPPORTED_FILTER с перечнем полученных ключей — вместо полного списка, выглядевшего как отфильтрованный. Запросы с каноническим номером и без filter[] работают как прежде, и их успешный ответ 200 не изменился. В описании API у операций складов и у агрегации появились реальные коды отказа (400, 401, 403, 404, 422), а удаление склада объявлено как 204 — тем ответом, который оно и отдавало.

BC-0908-2: Значение не того типа в поле записи отклоняется вместо тихой порчи данных

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

Было

Поле, объявленное в схеме сущности числом, принимало любую строку: {"amount":"сто тысяч"} на POST /v1/deals отвечал 201, а сумма сохранялась нулевой — Битрикс24 приводит нечисловую строку к 0. На обновлении это стирало уже записанную сумму: PATCH с непарсящимся значением отвечал 200 и обнулял поле. Так же вели себя все прочие числовые поля реестра (sort у справочников и товаров), булевы поля принимали любое слово, а строковое поле color у статусов заказа молча обрезалось до ширины колонки базы.

Стало

Такое значение отклоняется 400 с кодом INVALID_PARAMS до обращения к Битрикс24: числовое поле принимает JSON-число или числовую строку с точкой как десятичным разделителем; булево — true/false и распознаваемые строковые формы ("yes"/"no", "y"/"n", "1"/"0", "true"/"false"); строковое поле с объявленным ограничением длины — значение в пределах этой длины. Поля priority и status у задач принимают только значения из своего перечня.

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

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

FIX-0908-3: Постраничное чтение последних диалогов не теряет и не дублирует записи

Было

GET /v1/chats/recent передавал размер страницы и смещение в Битрикс24 как есть, а там они ограничивают внутреннее соединение таблиц, а не число диалогов. Из-за этого страница отдавала меньше записей, чем запрошено, при обещании следующей страницы; последняя запись страницы приходила с пустыми полями чата и последнего сообщения; соседние окна перекрывались, так что обход смещение += размер выдавал одни диалоги дважды, а другие терял.

Стало

Страница читается с запасом и режется на стороне Вайбкод: окно содержит ровно запрошенное число полностью заполненных записей, недозаполненные строки не отдаются, а признак наличия следующей страницы считается от фактически отданного окна. Окно за концом списка приходит пустым и следующей страницы больше не обещает. Запрос без указания размера страницы отдаёт 50 записей — раньше размер выбирал Битрикс24, теперь он назван явно.

Оговорка про глубокие окна: защита от перекрытия работает, пока смещение плюс размер страницы не превышает 190 — окно вместе с запасом на недозаполненные строки должно помещаться в одну страницу Битрикс24, а это 200 записей. Дальше смещение уходит в Битрикс24, и на очень длинных списках соседние окна снова могут перекрыться — это ограничение самого метода, а не платформы.

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

Ничего: запросы прежние, ответ стал честным. Если ваш код обходил дубли вручную — эта защита больше не нужна.

BC-0908-4: Поля, которые Битрикс24 назначает сам, объявлены только для чтения

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

Было

Пять полей были объявлены доступными для записи, принимались с ответом 200/201, но Битрикс24 их не сохранял — значение оставалось пустым, и отличить это от успешной записи по ответу было нельзя: признаки происхождения у воронок продаж, модуль-владелец у шаблонов документов, а также пометка проблемной оплаты и её причина у платежей при изменении.

Стало

Эти поля объявлены назначаемыми сервером: попытка записи отклоняется 400 с кодом READONLY_FIELD до обращения к Битрикс24, а описание поля прямо говорит, что значение проставляет платформа. Пометка проблемной оплаты и её причина по-прежнему принимаются при создании платежа — закрыто только их изменение, где значение и терялось. Признаки происхождения воронки раньше вовсе не были объявлены в схеме и подхватывались как записываемые; теперь они объявлены и отклоняются.

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

Уберите эти поля из тела запроса на изменение. Модуль шаблона платформа проставляет сама, признаки происхождения воронки не сохраняются вовсе, а пометку проблемной оплаты задавайте при создании платежа.

FIX-0908-5: поиск и сводные отчёты отвечают ошибкой на параметр неверного типа, а не тихой пустотой

Было

В теле POST /v1/{entity}/search поля limit и select принимали значение любого типа. Нечисловой limit (например, "abc") давал HTTP 200 с пустым списком записей и одновременно meta.hasMore: true — клиент, который листает страницы, пока платформа обещает продолжение, уходил в бесконечный цикл, не получая ни одной записи и ни одной ошибки. Значение select, не являющееся строкой или перечнем строк, превращалось в имя поля вида "999" или "[object Object]", уходило в Битрикс24 и возвращалось как HTTP 502 с кодом BITRIX_UNAVAILABLE — платформа сообщала о собственной недоступности там, где ошибка была в запросе клиента.

В теле POST /v1/{entity}/aggregate поле groupBy проверялось, только если пришло строкой или перечнем строк. Число, логическое значение или объект молча отбрасывались: ответ приходил с HTTP 200, без ключа groups и без предупреждения — клиент просил разрез отчёта, а получал общий итог и не мог этого заметить.

В meta.total списочных ответов на страницах за пределами коллекции попадало выдуманное число, растущее вместе со смещением: на портале с пятью хранилищами GET /v1/storages?offset=100 отвечал total: 100, а GET /v1/storages?offset=1000 — total: 1000.

Стало

limit неверного типа отклоняется кодом INVALID_LIMIT, select неверного типа — кодом INVALID_SELECT_TYPE, groupBy неверного типа — кодом INVALID_PARAMS; все три отказа приходят как HTTP 400 с указанием, какого типа значение пришло. Числовой limit работает как раньше, включая строковую запись числа ("50"), а null, пустая строка и пустой перечень по-прежнему означают «параметр не задан» и ошибкой не считаются.

Ключ meta.total не выдаётся, когда страница пуста, а смещение больше нуля: подтвердить счёт в этом случае нечем, а описание поля и без того предупреждает, что на ненулевом смещении ключа может не быть. Там, где страница непуста или смещение нулевое, meta.total приходит как прежде, и ответ по-прежнему HTTP 200.

FIX-0908-6: избранное, комментарии и записи времени задачи отвечают честно

Было

Добавление задачи в избранное и удаление из него отвечали 200 и success: true даже для задачи, которой нет: Битрикс24 подтверждает это действие для любого идентификатора, ничего при этом не сохраняя. Обещанный в описании API код 404 TASK_NOT_FOUND не приходил никогда.

Список комментариев задачи на запросе без фильтра и с сортировкой по идентификатору не учитывал offset — одна и та же страница приходила при любом значении, — а meta считалась по сырым сообщениям чата. На задаче, у которой в срезе только системные уведомления, ответ был data: [] вместе с total: 1 и hasMore: true, поэтому обход while (hasMore) offset += limit не завершался.

Обращение к несуществующему пункту чек-листа или записи учёта времени давало 422 BITRIX_ERROR с текстом внутреннего исключения Битрикс24 (TASKS_ERROR_EXCEPTION_#512; …; 512/TE/ITEM_NOT_FOUND_OR_NOT_ACCESSIBLE), причём на маршруте учёта времени этот текст говорил о чек-листе.

Параметры from и to у GET /v1/task-time не проверялись: ?from=notadate молча отдавал весь диапазон со статусом 200, как будто период не запрашивали.

Стало

Перед добавлением в избранное и удалением из него сервис проверяет, что задача существует и доступна ключу, и отвечает 404 TASK_NOT_FOUND, если нет. На существующей задаче ответ по-прежнему 200. Ограничение скорости и отказ авторизации задачей «не найдено» не подменяются.

Список комментариев учитывает offset на всех путях чтения, а meta.hasMore и meta.total считаются по комментариям, а не по сырым сообщениям чата: срез из одних системных уведомлений дочитывается дальше, и hasMore: false с total: 0 означает, что комментариев нет.

Отсутствующий пункт чек-листа и отсутствующая запись времени отвечают 404 NOT_FOUND — без внутреннего текста Битрикс24 и в терминах запрошенного ресурса. Код объявлен в описании API у всех методов, которые обращаются к одной записи.

Неразбираемое значение from или to отвечает 400 INVALID_PARAMS до обращения к Битрикс24; принимаются YYYY-MM-DD и ISO 8601. Пустое значение по-прежнему означает отсутствие фильтра. В описании API у GET /v1/tasks/{taskId}/comments объявлены реально работающие limit и offset.

BC-0908-7: Конвертация лида проставляет обратные связи и отвечает в общем формате чтения

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

Было

POST /v1/leads/{id}/convert отвечал 200, но созданные сделка, контакт и компания не несли ссылки на лид, из которого возникли: запрос сделок с фильтром по лиду ничего не находил, и связать сделку с её источником было нельзя. Сам ответ приходил в сыром формате Битрикс24 — с ключами в верхнем регистре через подчёркивание и числами-строками, — единственный такой ответ среди маршрутов раздела: платформа читала созданные записи устаревшими методами, чьи имена полей не совпадали со схемой, и значения проходили мимо нормализации.

Стало

Каждая созданная запись получает ссылку на исходный лид, а сам лид — ссылки на созданные контакт и компанию (только на те, что действительно созданы). Ответ читается тем же методом, что и обычное чтение сделки, контакта и компании, поэтому его формат совпадает с GET /v1/deals/{id} и соседними — имена полей в общем стиле платформы, числа числами.

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

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

BC-0908-8: валюта оплаты, расходящаяся с валютой заказа, больше не подменяется молча

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

Было

Создание оплаты принимало любую currency с ответом 201, а Битрикс24 сохранял оплату в валюте её заказа — присланная валюта отбрасывалась без единого замечания. Описание поля при этом обещало свободный выбор со ссылкой на GET /v1/currencies, так что расхождение всплывало только при сверке.

Стало

Если currency передана и не совпадает с валютой заказа orderId, запрос отклоняется 409 с кодом CURRENCY_MISMATCH до обращения к Битрикс24; сообщение называет обе валюты и заказ. Совпадающая валюта принимается по-прежнему, поэтому оплата, прочитанная и отправленная обратно целиком, работает как раньше. То же правило действует в batch-создании оплат. Если валюту заказа прочитать не удалось, запрос пропускается, а не отклоняется.

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

Не передавайте currency вовсе, чтобы унаследовать валюту заказа, либо передавайте ровно ту, что стоит у заказа: её показывает GET /v1/orders/:id.

NEW-0908-9: Политика авто-сна standalone-сервера теперь видна в API

POST /v1/infra/servers возвращает сохранённый data.sleepAfterMinutes для каждого успешного создания, reuse и idempotency replay. Это поле ответа, а не новый параметр создания. Успешный standalone-деплой возвращает тот же снимок политики в data.sleepAfterMinutes, а SSE — в sleepAfterMinutes события done. Для обычного standalone-сервера, не защищённого политикой авто-сна агента или бота, при числовом таймауте и отсутствии включённых повторяющихся окон пробуждения в конец warnings[] добавляется предупреждение с префиксом AUTO-SLEEP POLICY: и двумя вариантами: окно пробуждения для задачи, которая успевает завершиться до таймаута, либо осознанный режим «Всегда онлайн» на невытесняемом тарифе. Окно только будит сервер и не удерживает фоновый процесс включённым. Для POST /v1/infra/servers/:id/sleep-now теперь документирован существующий успешный исход slept: false, reason: "WAKE_IMMINENT", когда ближайшее окно пробуждения уже на подходе. Сам ответ HTTP 200 не изменился.

BC-0908-10: запись суммы у смарт-процесса без товарной части больше не отвечает ложным успехом

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

Было

POST /v1/items/{entityTypeId} и PATCH /v1/items/{entityTypeId}/{id} принимали opportunity и isManualOpportunity у любого типа смарт-процесса и отвечали 201/200. Если у типа выключена товарная часть (isLinkWithProductsEnabled: false), Битрикс24 эти поля не сохраняет — сумма пропадала молча, а клиент видел успех и уходил.

Стало

Платформа сверяет запрошенное с перечитанной записью — она и раньше перечитывалась перед ответом, так что лишних обращений к Битрикс24 не появилось. Если запрос ЯВНО просил ручной режим (isManualOpportunity: true) и не получил его, приходит 422 AMOUNT_NOT_APPLIED: error.details.unappliedFields перечисляет неприменённые поля, а data несёт фактическое состояние уже созданной или изменённой записи. Сумма, присланная БЕЗ этого флага, не проверяется: по ответу её не отличить от законного пересчёта по товарным позициям, который работает штатно, — поэтому такие запросы отвечают как раньше. Проверка не затрагивает сделки, лиды, счета и коммерческие предложения — у них товарная часть есть всегда.

FIX-0908-11: хост из galaxyId теперь доступен для чтения

Было

Ответ создания galaxy-приложения уже содержал galaxyId, но GET /v1/infra/servers не показывал этот общий хост, а GET /v1/infra/servers/:id отвечал 404 NOT_FOUND тому же API-ключу.

Стало

Оба вызова чтения возвращают ограниченную проекцию хоста с access.via: "galaxy-reference". Она содержит только безопасные поля для чтения. Управление хостом и операции приложения по-прежнему требуют ресурса текущего ключа.

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

Изменять запросы не нужно. Клиенту, который использует появившийся в ответе общий хост, следует проверять access.via: значение galaxy-reference означает доступ только для чтения.

NEW-0908-12: выдача ключа говорит, получил ли он доступ к данным Битрикс24

POST /v1/connect/token теперь отдаёт необязательное поле b24_credentials, а GET /v1/cowork/me — такое же b24Credentials. Оно отвечает на вопрос, может ли выданный ключ читать данные аккаунта Битрикс24: ready: true — права рабочие, ready: false — нет, и тогда приезжает reason из закрытого набора (WEBHOOK_NOT_CONFIGURED, WEBHOOK_MINT_FAILED, WEBHOOK_MINT_REFUSED_BY_PORTAL, B24_MARKET_SUBSCRIPTION_REQUIRED, B24_MARKET_TRIAL_USED, INT_TARIFF_REQUIRED, VIBE_SCOPES_ONLY), а для причин про оплату — ещё и upgradeUrl. Тот же набор причин уже несёт тело 401 TOKEN_MISSING, так что клиент разбирает его одной веткой кода.

Зачем это нужно. Ключ выдаётся и тогда, когда аккаунт отказал платформе подключить его к своим данным: сам ключ работает для вызовов ИИ, а каждый запрос к данным аккаунта отвечает 401 TOKEN_MISSING. Раньше клиент узнавал об этом, только напоровшись, и не мог отличить отсутствующее право от сетевого сбоя. Теперь состояние приезжает вместе с ключом и переспрашивается на GET /v1/cowork/me в любой момент.

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

FIX-0908-13: история рабочих дней возвращается, когда день ещё не закрыт

Было

GET /v1/workday/records отвечал 502 BITRIX_UNAVAILABLE, если в выборку попадала запись незакрытого рабочего дня. У такой записи ещё нет времени окончания, длительности и признака подтверждения, а ручка требовала эти поля заполненными и отбраковывала всю страницу целиком — включая закрытые дни, которые пришли в том же ответе. На практике это означало отказ у любого сотрудника, который сейчас на смене.

Стало

Запись незакрытого дня возвращается как есть, вместе с остальной страницей: ответ остаётся HTTP 200, поля окончания приходят такими, какими их отдал Битрикс24. Проверки сохранены там, где ответ иначе стал бы неверным незаметно: страница по-прежнему отбраковывается, если запись принадлежит другому сотруднику или у неё нет корректного времени начала — от него считается tzOffset. Клиентам ничего менять не нужно.

NEW-0908-14: агенты доступны для привязки к Открытым линиям

Добавлен GET /v1/agents: метод возвращает агентов владельца API-ключа и bitrixBotId, который можно передать в welcomeBotId конфигурации Открытой линии. Поле agentId для Hermes-агента не используется; queue по-прежнему содержит ID операторов-людей.

NEW-0908-15: include отделов в записях сотрудников

Параметр include=department добавляет в запись сотрудника массив _included.departments с карточками всех отделов из departmentId. Для сотрудника без отдела приходит пустой массив. Запросу нужны скоупы user и department.

Затронутые эндпоинты: GET /v1/users, GET /v1/users/:id, POST /v1/users/search

NEW-0908-16: названия и описания всех базовых полей

В ответе GET /v1/{entity}/fields все объявленные базовые поля теперь содержат локализованные название и описание: русские для русскоязычных порталов и английские для международных.

NEW-0908-17: защита от записи поверх более свежих исходников

POST /v1/infra/servers/{id}/sources принимает необязательный заголовок X-Parent-Version: v<N> — «я правил вот эту версию». Если к моменту записи последняя версия уже другая, запись отбивается кодом SOURCE_VERSION_CONFLICT (409), а error.details.latestVersionId называет актуальную версию (null — живых версий нет вовсе). Кривая форма заголовка — 400 INVALID_VERSION_ID. Без заголовка ручка работает как прежде.

«Актуальная» здесь — самая свежая ЖИВАЯ версия, та же, что стоит первой в списке версий и скачивается: названную в отказе версию всегда можно взять и повторить запись. Удалённые версии в счёт не идут, но их номера не переиспользуются. Дедупликация исключением не является: архив, побайтно совпавший с уже существующей версией, тоже получит 409, если верхушка ушла вперёд.

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

Ответ POST /v1/cowork/deploy-key получил два поля о переносе на новый ключ: repointTruncated — переехало не всё, остаток уедет на следующем вызове, и applicationSlotBlocked — карточка приложения осталась на прежнем ключе, потому что слот свежего занят другой карточкой. Раньше частичный исход был виден только в журнале платформы.

Затронутые эндпоинты: POST /v1/infra/servers/{id}/sources, POST /v1/cowork/deploy-key

NEW-0908-18: замена ключа приложения одним запросом и маска ключа в карточке

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

Появилась ручка POST /v1/cowork/applications/{id}/key, которая приводит ключ приложения в рабочее состояние одним запросом. Слот личного ключа пуст — ключ выдаётся, занят — перевыпускается; что именно произошло, говорит поле issued (minted или rotated). Сырой ключ приходит один раз, как при создании приложения. Заголовок Idempotency-Key обязателен, повтор с тем же ключом отвечает rawApiKey: null и KEY_NOT_REPLAYABLE. Если запрос упал уже ПОСЛЕ выдачи (500 с orphanKeyId в теле), ключ идемпотентности считается израсходованным навсегда: повтор с ним получит IDEMPOTENCY_KEY_ALREADY_USED, а не второй ключ. Прочитайте карточку и повторяйте с НОВЫМ ключом идемпотентности. Отдельный случай — ключ выдан, а карточку прочитать не удалось: ответ всё равно 201 с секретом, application приезжает пустым, и об этом говорит код APPLICATION_CARD_UNAVAILABLE в warningCodes. Карточку возьмите GET /v1/applications/{id}: терять из-за неё единственную копию секрета незачем.

Прежний ключ не отзывается мгновенно: ему ставится срок в сутки, поэтому идущая публикация доработает. Поле previousKey.graceUntil называет момент, когда он перестанет аутентифицироваться. Тело запроса принимает syncServerEnv: true — тогда платформа заменит ключ в переменных окружения задеплоенного сервера и перезапустит приложение, а поле envSync скажет, чем это кончилось: заменено, строки в файле нет, сервер спит, перезапуск не удался и так далее. Без этого приложение продолжит работать со старым ключом и через сутки начнёт получать отказы.

Отказы приходят отдельными кодами, а не общим 400: NOT_APPLICATION_OWNER — приложение чужое; KEY_ROTATE_OAUTH_APP_KEY, KEY_ROTATE_SYSTEM_KEY, KEY_ROTATE_LIVE_OAUTH_GRANT, KEY_ROTATE_NOT_ACTIVE — ключ в слоте заменить нельзя, причина в коде; KEY_ROTATE_KEY_VANISHED — ключ исчез, пока летел запрос; KEY_LIMIT_REACHED — исчерпана квота ключей; APPLICATION_KEY_REPLACE_IN_PROGRESS — замена этого приложения уже идёт. Замена идёт по одной на приложение, с каким бы ключом идемпотентности ни пришёл второй запрос: иначе оба выдали бы по ключу, а слот достался бы тому, кто финишировал вторым. Брошенная упавшим запросом замена перестаёт мешать через две минуты.

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

Карточка приложения получила блок key: slot (auth или api — какой ключ показан), present, prefix, suffix, status, expiresAt, lastUsedAt, rotatable и rotateBlockedReason (сработает ли замена и почему нет), affectsShownKey (тронет ли она именно показанный ключ). Маска собирается клиентом из prefix и suffix. Поле rotatable говорит о том, что платформе УЖЕ известно, и гарантией не является ни одной стороной: false — «известен отказ, вот его причина» (rotateBlockedReason, в него входит и право доступа), true — «известных отказов нет». Кнопку по нему рисовать удобно — гасите её при false и показывайте причину, — но тупиком false делать не стоит: отказ мог уже отпасть, а карточка ещё не узнать (про запаздывание и про два гейта вне поля — ниже). Судите по ответу двери, а не только по полю. Блок приходит ВСЕГДА; тому, кому приложение просто открыли, поля приезжают пустыми (present: false), а rotatable — false с причиной NOT_MANAGER: это значит «не положено», а не «ключа нет». На ПУСТОМ слоте, где вызов выдал бы ключ, поле учитывает и гейты выдачи: ISSUANCE_BLOCKED (у аккаунта нет доступа к платформе), INFRA_DISABLED (инфраструктура выключена), KEY_QUOTA_REACHED (квота ключей исчерпана), READONLY_POLICY (аккаунт выдаёт только ключи для чтения). Про сам вызывающий ключ поле говорит теми же кодами, что и дверь, и они повторяются на КАЖДОЙ карточке ответа: INSUFFICIENT_SCOPE (у ключа нет скоупа vibe:cowork) и COWORK_HARNESS_KEY_FORBIDDEN (ключ выписан внешнему агенту). Точность у поля односторонняя намеренно: false на пустом слоте читается по уже известному платформе состоянию доступа — только что изменившийся доступ может ещё показываться как false, пока это состояние не обновится. ДВА гейта Коворк/Код остаются ВНЕ поля и могут отказать при true: платформенный рубильник (503 COWORK_FEATURE_DISABLED) и состояние вашего места Коворк/Код (403 COWORK_NOT_ACTIVATED, о котором и так говорит GET /v1/cowork/state). Ни то ни другое не относится к самой карточке, поэтому по карточкам не размножается — обрабатывайте отказ двери, а не читайте true как гарантию.

Затронутые эндпоинты: POST /v1/cowork/applications/{id}/key, GET /v1/applications, GET /v1/applications/{id}

NEW-0908-19: чтение списка, активного спринта и спринта по ID

API Вайбкод добавляет GET /v1/scrum/sprints для чтения доступных спринтов, GET /v1/scrum/sprints/active для чтения текущего спринта проекта и GET /v1/scrum/sprints/:id для чтения одного спринта по ID. Ответ содержит название, даты, статус и связь с проектом. Если активного спринта нет, соответствующая ручка возвращает data: null.

BC-0908-20: приостановленное место Коворк/Код больше не открывает Битрикс24 в обход подписки Маркетплейса

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

Было

Ключ десктопа Коворк/Код и ключ агента открывали REST Битрикс24 на аккаунте без подписки Маркетплейса независимо от того, действует ли само место. Приостановленное место сохраняло эту возможность до тех пор, пока не гасился ключ, — около месяца.

Стало

Возможность привязана к состоянию места. Пропуск действует только у места в состоянии ACTIVE, включая место с назначенной отменой — до конца оплаченного срока. У приостановленного, отменённого и припаркованного места ключ обслуживается общим правилом аккаунта: там, где подписка Маркетплейса куплена, не меняется ничего, а без неё вызовы к Битрикс24 получают тот же отказ аккаунта, что и любое другое приложение.

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

Возобновить подписку Коворк/Код либо оформить подписку Маркетплейса на аккаунте. Текущее состояние места приходит в поле subscription.state ответа GET /v1/cowork/state.

NEW-0908-21: каталог инструментов 1С доступен через клиентский API

GET /v1/onec/tools возвращает последний проверенный каталог инструментов портала вместе с признаками loaded, stale, версиями и временем обновления. Каждый инструмент содержит method, title, description и inputSchema. Эндпоинт требует scope vibe:onec, включённый коннектор на портале и сегмент RU, но не требует связи текущего пользователя с пользователем 1С. Пока каталог не загружен, ответ явно содержит loaded: false, пустой массив tools и null в полях ревизии и времени.

POST /v1/onec/tools/{method}/call теперь принимает вложенные JSON-значения в filters: до 200 элементов в массиве, 50 ключей в объекте, 1024 символов в строке, глубины 6 и 2000 узлов на весь объект filters. Ключи __proto__, prototype и constructor запрещены на любом уровне. Поля user, portal и requestId по-прежнему назначает сервер. Вызов остаётся асинхронным: успешный запрос отвечает 202, а результат читается через GET /v1/onec/operations/{operationId}.

FIX-0908-22: реестр исходников больше не обещает дверь, которая ответит вызывающему ключу 403

Было

GET /v1/me/sources считал reachableViaApi по одной достижимости СТРОКИ — «жив ли сервер, не удалено ли приложение» — и не смотрел на КЛЮЧ, которым пришли. А двери, на которые ведут его указатели, скоуплены по ключу и отбивают ключ OAuth-приложения, если сервер принадлежит не ему.

Наблюдаемо это выглядело так. Выдача перечисляет владельцев снимков по ПОЛЬЗОВАТЕЛЮ, а не по ключу, поэтому, придя ключом своего приложения, вы получали свои серверы, заведённые ЛИЧНЫМИ ключами, с reachableViaApi: true и рабочим с виду listEndpoint — а GET /v1/infra/servers/{id}/sources по этому адресу отвечал тому же ключу 403 NOT_AUTHORIZED.

Та же ложь была на строке приложения: автор приложений A и B, пришедший ключом приложения B, видел строку A с рабочим указателем, по которому дверь отвечала 403 SOURCE_APP_ID_MISMATCH.

Стало

reachableViaApi отвечает на один вопрос: пустит ли ВЫЗЫВАЮЩИЙ КЛЮЧ детальный переход. Строка, чью дверь этот ключ не откроет, несёт reachableViaApi: false, а listEndpoint и latestDownloadEndpoint — null. Обе kind-ветки выдачи (server и legacy-app) считают это тем же предикатом, что и сама дверь.

Строка из выдачи НЕ пропадает: снято ложное обещание, а не видимость. Владелец по-прежнему видит, что снимки существуют, и по user.id понимает, чьи они.

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

Проверяйте reachableViaApi перед тем, как идти по listEndpoint или latestDownloadEndpoint. Оба поля и раньше были объявлены как string | null и уже приходили пустыми у осиротевшего сервера и мягко удалённого приложения, а reachableViaApi: false уже был документированным значением для тех же двух случаев, — поэтому клиент, который соблюдал контракт, менять ничего не обязан. Получили false там, где ждали true, — значит вы пришли ключом приложения: повторите вызов личным ключом (своим или владельца сервера) либо ключом администратора портала. Для строки приложения то же самое: ключ приложения открывает только своё приложение.

Чего это НЕ меняет

Доступ. Ни одна дверь не стала пускать или не пускать кого-то нового: правило доступа осталось прежним, изменилось только то, что выдача перестала обещать доступ, которого нет. Сведение дверей одного сервера к единой модели владения — отдельное ломающее изменение, и оно едет отдельной записью; там же поедут подсказки отказов publish и deploy, потому что у них тот же адрес снимается ВМЕСТЕ с полем hint.requiredAction, а это уже удаление документированного поля.