Для 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, а это уже удаление документированного поля.