Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-09-21.md индекс документации — /llms.txt
Изменения API: 21 сентября 2026
← Журнал изменений · Сентябрь 2026
FIX-0921-1: пример пакетного чтения почтовых ящиков показывает подвызов
Было
Карточка справочника для POST /v1/mail/mailboxes/batch печатала тело {"action":"list"} — без массива calls. Скопированный как есть, такой вызов не выполнял ни одного подвызова и возвращал пустой результат, который читался как «у портала нет ящиков», хотя ящики были. Параметры подвызова эта дверь принимает только внутри calls[].params, и передать их было некуда. В машинной спецификации подвызов был описан как произвольный объект, а признак того, поднимает ли дверь обязательные параметры подвызова, не публиковался вовсе.
Стало
Пример показывает рабочую форму: {"action":"list","calls":[{"params":{"limit":5}}]}. Спецификация описывает элемент calls полем params и публикует расширение x-batch-list-lifts-params, как у соседних пакетных дверей. Ответы операции и её поведение не изменились: адрес, тело запроса, коды ответов и требуемое право прежние. В спецификации операция переехала из группы mail в группу mail-mailboxes — к ней же относятся остальные операции почтовых ящиков. Если вы генерируете клиента по GET /v1/openapi.json, при следующей генерации изменится имя класса, в который попадает этот метод; сам вызов менять не нужно.
FIX-0921-2: генерация изображений учитывает output_format и negative_prompt
Было
POST /v1/images/generations принимал output_format и negative_prompt, но сервис генерации их не получал. Запрос с output_format: "jpeg" возвращал картинку в PNG, и поле output_format в ответе тоже приходило равным png. Запрос с negative_prompt давал ту же картинку, что и без него.
Стало
Оба поля доходят до сервиса генерации. output_format: "jpeg" возвращает JPEG, "webp" — WebP, и поле output_format в ответе называет фактический формат. Без этого поля формат по-прежнему PNG. negative_prompt влияет на результат.
Влияние на интеграторов
Менять ничего не нужно. Если вы присылали output_format: "jpeg" и рассчитывали на PNG в ответе, читайте формат из поля output_format ответа, а не считайте его постоянным.
FIX-0921-3: `/exec` больше не портит многобайтные символы в выводе
Было
В ответе POST /v1/infra/servers/:id/exec, а также в потоковом режиме ?stream=true, многобайтный символ UTF-8, попавший на границу внутреннего буфера чтения, приходил как �: например — мог прийти как —��, а следующий фрагмент — начаться с �. Однобайтный вывод это не затрагивало.
Стало
Вывод собирается по границам символов: неполный символ на стыке фрагментов удерживается и дописывается следующим фрагментом, поэтому stdout и stderr доходят без порчи и в потоковом, и в JSON-режиме. Ответ остаётся HTTP 200, exitCode не меняется.
FIX-0921-4: внешний API приложений переживает короткое переподключение туннеля
Было
Вызов ANY /v1/applications/:id/api/*, который попадал в короткое окно переподключения туннеля приложения, мог сразу получить 503 APP_API_UNAVAILABLE с Retry-After, даже если приложение становилось доступно через несколько секунд.
Стало
В таком окне платформа Вайбкод ненадолго удерживает вызов и, если туннель успевает вернуться в общий бюджет запроса, доставляет его в приложение. Если туннель не вернулся вовремя, ответ остаётся 503 APP_API_UNAVAILABLE с Retry-After.
FIX-0921-5: схема 403 на пишущих операциях допускает все опубликованные коды
Было
Пишущие операции V1, которые документируют отказ WRITE_BLOCKED_READONLY_KEY, тем же описанием называли соседние коды 403: SCOPE_DENIED, отказы общего гейта ключа и отказы Битрикс24. При этом схема тела закрывала error.code одним значением WRITE_BLOCKED_READONLY_KEY, поэтому SDK, собранный по OpenAPI, считал остальные коды невозможными.
Стало
Схема этого ответа допускает стандартный V1-конверт { success: false, error: { code, message } } рядом со строгой веткой WRITE_BLOCKED_READONLY_KEY. Типизированные details для READONLY-отказа сохранены, а остальные опубликованные коды 403 больше не запрещены схемой.
FIX-0921-6: polling бота с остановленной подпиской возвращает пустую очередь
Было
GET /v1/bots/{botId}/events для бота, остановленного из-за неактивной подписки Маркетплейса Битрикс24, возвращал 403 B24_MARKET_SUBSCRIPTION_REQUIRED. Клиенты, которые не учитывали этот отказ, могли продолжать частый polling.
Стало
Для такого бота GET /v1/bots/{botId}/events возвращает успешный ответ с пустым списком событий, hasMore:false, сохранённым offset и nextPollAfterMs:60000 — опрашивайте с этим темпом. На запрос с withUserEvents=true поле темпа не приходит, как и в остальных режимах. Остальные операции с остановленным ботом продолжают получать 403 B24_MARKET_SUBSCRIPTION_REQUIRED до восстановления подписки.
BC-0921-7: Поле, которого нет в описании сущности, проверяется на записи по типу из Битрикс24
Поддержка старого формата до: не предусмотрена
Было
Проверка формы значения на записи охватывала только поля, объявленные в описании сущности. Поле, которое сущность отдаёт при чтении, но не объявляет (utmSource и locationId у сделок, birthdate, honorific и categoryId у контактов, employees у компаний, statusDescription у лидов), и пользовательские поля UF_* она не видела: {"locationId": {"a": 1}} на POST /v1/deals отвечал 201, а в карточке сохранялась строка Array; {"categoryId": "abc"} у контакта сохранялся как 0, а {"categoryId": {"a": 1}} — как 1, и контакт переезжал в другую категорию; объект в birthdate сохранялся пустым. Так вели себя все семь дверей записи — одиночные POST и PATCH, пакетная запись по одной сущности и общая, импорт.
Стало
Такое поле проверяется по тому, что о нём сообщает сам Битрикс24 в своём списке полей: объект или массив в поле строкового, числового, логического или датного типа портала и нечисловая строка в числовом отклоняются 400 с кодом INVALID_PARAMS до записи в Битрикс24, а сообщение называет поле и тип, которым портал его объявил. Пустая строка в поле-ссылке (сотрудник, контакт, компания, лид, сделка) и в пользовательском числовом поле не отклоняется — так Битрикс24 снимает привязку и очищает значение; в категории она отклоняется, потому что переносит запись в категорию 0. Поля, которые портал объявляет многозначными или только для чтения, неизменяемые после создания поля на обновлении, поля типов вне перечисленных (файл, перечисление, деньги), имена, которых в списке портала нет, и сущности без признака многозначности в списке полей (задачи) не проверяются — как прежде. Список полей запрашивается только когда в теле есть такое имя, и держится в памяти пять минут; если Битрикс24 его не отдал, запись проходит как раньше, и ближайшие тридцать секунд список перед записью не запрашивается повторно. Границы — в разделе INVALID_PARAMS.
Что делать интеграторам
Проверьте места, где в поля из списка GET /v1/<entity>/fields, отсутствующие в описании сущности, значения собираются структурой или строкой из внешней системы: раньше такой запрос отвечал успехом, а данные терялись или искажались, теперь он честно вернёт ошибку с указанием поля. Значения верного типа проходят без изменений.
BC-0921-8: схемы контакта и сделки достроены: двенадцать полей ответа объявлены только для чтения, тринадцать служебных и пустых ключей убраны
Поддержка старого формата до: не предусмотрена
Было
GET /v1/contacts/{id} (а также список, поиск, include и перечитанная запись в ответах на создание и изменение) отдавал восемь ключей, которых не было ни в схеме, ни в справочнике, ни в машинном описании OpenAPI: phoneWork, phoneMobile, phoneMailing, imol, address, shortName, login и entityTypeId. GET /v1/deals/{id} — семнадцать: isWon, isLose, isWork, hasProducts, receivedAmount, lostAmount, begindateShort, closedateShort, dateCreateShort, dateModifyShort, eventDateShort, eventId, eventDate, eventDescription, orderStage, productId и entityTypeId. Явный select любого из них отвечал 400 UNKNOWN_SELECT_FIELD, сортировка у контактов — 400 UNKNOWN_SORT_FIELD, а у сделок ?sort= по любому из них уходил в Битрикс24 как есть (200, по entityTypeId — сырой 422 BITRIX_ERROR). Значение, присланное в любой из этих ключей при создании, изменении, импорте или в пакете, Битрикс24 не хранил ни на одной двери, но платформа отвечала успехом (201/200): создание и изменение — с предупреждением UNRECOGNIZED_WRITE_FIELD, импорт — молча. Незаполненное значение любого из шести полей контакта (телефоны, контакт открытой линии, адрес, краткое имя) приходило пустой строкой, а не null, как у описанных полей.
Стало
У контакта объявлены шесть полей, все только для чтения: phoneWork, phoneMobile, phoneMailing (телефоны из мультиполя phone по типам), imol (контакт открытой линии), address (старая колонка адреса — заполняет только legacy crm.contact.add, адрес правится в реквизитах) и shortName (фамилия с инициалами, вычисляет Битрикс24). У сделки — шесть полей, которые Битрикс24 вычисляет, все только для чтения: isWon, isLose, isWork (флаги по смысловой категории стадии), hasProducts (есть ли товарные позиции), receivedAmount и lostAmount (сумма сделки в учётной валюте портала — пересчитанная по курсу, если валюта сделки другая, — пока она выиграна или проиграна, иначе 0). Все двенадцать описаны на странице полей контакта и странице полей сделки, в GET /v1/contacts/fields и GET /v1/deals/fields, в справочнике и в машинном описании; типы по живому замеру. Явный select этих полей работает; фильтр и сортировка по phoneWork, phoneMobile, phoneMailing, address, shortName и по receivedAmount/lostAmount работают (по imol — принимаются), receivedAmount/lostAmount принимаются и в sum/avg/min/max POST /v1/deals/aggregate; четыре флага сделки в filter не принимаются (400 UNKNOWN_FILTER_FIELD) — булев фильтр уходит в Битрикс24 как Y/N, а портал сравнивает эти флаги только с булевым значением: по трём флагам стадии строка Y даёт обратный набор (фильтруйте по stageSemanticId), по hasProducts не совпадает ни с одной записью (замены в фильтре нет); сортировка по флагам работает. Шесть вычисляемых полей сделки и shortName контакта Битрикс24 считает только для списка или поиска с явным select без *; одиночный GET, список без select и действие list пакета сущности отдают по ним null. Значение, присланное в любое из двенадцати полей, — которое Битрикс24 и раньше не сохранял — теперь отклоняется: создание и изменение — 400 READONLY_FIELD, импорт — 400 IMPORT_ITEM_VALIDATION, пакетный запрос сущности — 400 BATCH_ITEM_VALIDATION, общий пакетный запрос — READONLY_FIELD под вызовом в data.errors. Незаполненные значения шести полей контакта приходят как null, как остальные пустые строки записи. Тринадцать ключей из ответов убраны: у контакта entityTypeId (константа типа, 3) и login (пустой на любом портале, ни одна дверь его не пишет); у сделки entityTypeId (константа 2), пять коротких дат begindateShort, closedateShort, dateCreateShort, dateModifyShort, eventDateShort (те же даты второй раз) и пять пустых старых граф eventId, eventDate, eventDescription, orderStage, productId (пусты на любом портале, не заполняются ни через API, ни через legacy-методы). Убранные ключи не принимаются в select, filter и сортировке — ?sort=, ?order[], order тела поиска (400 UNKNOWN_SELECT_FIELD / 400 UNKNOWN_FILTER_FIELD / 400 UNKNOWN_SORT_FIELD) — у сделок раньше ?sort= по ним уходил в Битрикс24 насквозь. Исключение прежнее: params.order подвызова POST /v1/batch у контактов и сделок по-прежнему уходит на портал как есть.
Что делать интеграторам
Если вы отправляли любое из двенадцати полей при создании, изменении, импорте или в пакете — уберите его из тела: Битрикс24 не хранил его и раньше, телефоны записываются через phone, адрес — в реквизитах, флаги и суммы считает портал. Если вы читали entityTypeId, login, короткие даты или eventId/eventDate/eventDescription/orderStage/productId — эти ключи больше не приходят: тип сущности задан самим эндпоинтом, даты берите из begindate/closedAt/createdAt/updatedAt, остальные всегда были пустыми. Если вы проверяли phoneWork, phoneMobile, phoneMailing, imol, address или shortName на пустую строку — проверяйте на null. Если вам нужны isWon/isLose/isWork/hasProducts/receivedAmount/lostAmount или shortName — запрашивайте их явным select (без *) на списке или поиске.
Затронутые эндпоинты: GET /v1/contacts/{id}, GET /v1/contacts, POST /v1/contacts/search, GET /v1/contacts/fields, POST /v1/contacts, PATCH /v1/contacts/{id}, GET /v1/deals/{id}, GET /v1/deals, POST /v1/deals/search, GET /v1/deals/fields, POST /v1/deals, PATCH /v1/deals/{id}, POST /v1/deals/{id}/move, POST /v1/{entity}/import, POST /v1/{entity}/batch, POST /v1/batch.
NEW-0921-11: удаление сервера сообщает, чем кончился запрос на удаление машины в облаке
В ответе DELETE /v1/infra/servers/{id} появилось поле cloudDelete: confirmed — облако приняло запрос на удаление машины, already-gone — машины уже не было, failed — облако запрос не приняло, not-applicable — у сервера нет машины в облаке, например у galaxy-приложения. success по-прежнему true во всех четырёх случаях: запись сервера удалена, начисления остановлены. Раньше ответ этого не показывал: при failed запись сервера всё равно удалялась, а машина могла продолжать работать — по ответу это было незаметно. При failed не считайте ресурс уничтоженным.
NEW-0921-12: код DISK_FULL в provisionErrorCode сервера после неудачной починки
Если починка сервера (POST /v1/infra/servers/{id}/repair) не удалась из-за нехватки места на
диске, сервер в GET /v1/infra/servers и GET /v1/infra/servers/{id} получает новое значение
provisionErrorCode: "DISK_FULL" и понятный текст в provisionError: повтор не поможет, сначала
нужно освободить место. Успешная починка снимает DISK_FULL. Уже стоящие вердикты
AGENT_NEVER_CONNECTED и GUEST_NOT_BOOTING значение DISK_FULL не заменяет. Статус сервера не
меняется, прежние запросы работают как раньше.
NEW-0921-13: у дел появился include: responsible, author, editor
Дело теперь объявляет три связи на сотрудников, и их можно затребовать параметром include у GET /v1/activities, GET /v1/activities/{id} и POST /v1/activities/search: responsible — ответственный (по полю responsibleId), author — автор (по authorId), editor — последний редактор (по editorId). Раньше связей у сущности не было объявлено ни одной, поэтому любое имя отвергалось с 400 INVALID_INCLUDE, а список допустимых имён в тексте отказа был пустым.
Запрос вида GET /v1/activities/{id}?include=responsible,author отвечает 200 и кладёт карточки сотрудников в _included. Запрос без include работает как прежде. Связь читает карточку сотрудника, поэтому ключ обязан нести право user — иначе запрос отвечает 403 SCOPE_DENIED. Доступные имена публикует GET /v1/activities/fields и спецификация OpenAPI.
Имя вне этого списка отвергается по-прежнему, но отказ теперь называет доступные связи: Unknown include 'owner'. Available: responsible, author, editor. Родитель дела (ownerTypeId + ownerId) и communications связями не объявлены намеренно: целевая сущность там меняется от записи к записи, и по одному числовому идентификатору невозможно выбрать, чью карточку читать; обе величины и так приезжают полями самой записи.
FIX-0921-14: структурированный ответ проверяется на разбор, а не только на обрыв
Было
При response_format типа json_object или json_schema платформа проверяла только то, что модель не оборвала генерацию и что ответ не пуст. Непустой ответ, который не разбирается как JSON-документ — текст вокруг объекта, ответ в markdown-ограждении кода, одиночное значение, — приходил как обычный ответ HTTP 200, и JSON.parse падал уже в интеграции.
Стало
Платформа разбирает ответ перед выдачей. Успешный ответ 200 не изменился: валидный JSON-объект или массив приходит как прежде, байт в байт. Если ответ непустой, но не разбирается, приходит отказ 422 с кодом structured_output_invalid_json, полем finishReason и подсказкой hint; полей param и suggestedMaxTokens в нём нет — больший бюджет токенов результата не меняет. В потоковом режиме отказ приходит событием {"error":{"code":"structured_output_invalid_json"}} перед data: [DONE], уже переданные фрагменты следует отбросить. Отказ structured_output_truncated остаётся за обрывом и пустым ответом. Вызов, дошедший до модели, тарифицируется так же, как и прежде.