# Изменения API: 21 июля 2026

[← Журнал изменений](/docs/changelog) · [Июль 2026](/docs/changelog/2026-07)

### FIX-0721-1: имя и описание встроенного поискового движка, имя облачного провайдера

Публичное имя платформенного поискового движка приведено к продуктовому: `GET /v1/search/providers`
и `/v1/me` возвращают `Bitrix24 AI Search` в поле `name` (латинские локали). Идентификатор
провайдера `bitrix-search` не менялся — клиентам ничего делать не нужно.

Из описания того же провайдера снято упоминание цитирования источников: возможность зависит от
движка, привязанного к инстансу, и объявляется машинно в `capabilities.output.citations` того же
ответа.

`GET /v1/infra/providers` на международном сегменте возвращает в поле `name` бренд `Bitrix24 Cloud`
вместо `Bitrix Cloud`. Идентификатор провайдера `bitrix-cloud` не менялся.

**Было**

`"name": "Bitrix AI Search"` · `"description": "Platform AI search with agentic mode and source citations"` · `"name": "Bitrix Cloud"`

**Стало**

`"name": "Bitrix24 AI Search"` · `"description": "Platform AI search with agentic mode"` · `"name": "Bitrix24 Cloud"`

### FIX-0721-2: создание шаблона бизнес-процесса теперь принимает файл шаблона

**Было**

[POST /v1/bizproc-templates](/docs/entities/bizproc-templates) отвечал `422 Incorrect field TEMPLATE_DATA!` при любом теле — создать шаблон было невозможно: поле с содержимым файла `.bpt` не входило в схему сущности и до Битрикс24 не доходило.

**Стало**

Поле `templateData` (файл `.bpt` в виде массива `[имя файла, содержимое в base64]`) принимается и передаётся в Битрикс24, шаблон создаётся. Поле обязательно на создание: без него запрос отклоняется с `400 MISSING_REQUIRED_FIELDS` до обращения к Битрикс24 (раньше приходила сырая ошибка `Incorrect field TEMPLATE_DATA!`). Оно доступно на запись и в описании полей `GET /v1/bizproc-templates/fields`, но не возвращается при чтении.

### NEW-0721-3: Сводный реестр исходников — GET /v1/me/sources

Новый эндпоинт [GET /v1/me/sources](/docs/source-storage) — программный аналог кабинетной страницы «Исходники приложений». Возвращает снапшоты исходников по всем серверам и приложениям, которыми владеет ключ (а ключ администратора аккаунта — по всему аккаунту), с пагинацией (`page`/`limit`/`search`) и стандартным конвертом `{ success, data, total, page, limit }`. Каждая строка несёт указатель для перехода вглубь — `listEndpoint` и `latestDownloadEndpoint` — плюс `reachableViaApi` и, для строк-серверов, `blackholeStatus`. В отличие от [GET /v1/infra/servers](/docs/infra/servers/list), который ограничен серверами вызывающего ключа, этот реестр охватывает и сервер на другом ключе того же владельца.

Ответы server-scoped эндпоинтов исходников ([POST /v1/infra/servers/:id/sources](/docs/source-storage) и соседние list/download/tag/cleanup) теперь описаны в документации; поле `versions[].serverContext` (`{ serverId, serverName, serverDisplayName, linkedApp }`) закреплено в контракте.

### NEW-0721-4: необязательное поле error.b24Code в ответах 422 BITRIX_ERROR

В ответах `422 BITRIX_ERROR` появилось необязательное поле `error.b24Code` — сырой код ошибки Битрикс24 для программной обработки (например, `PERIOD_REQUIRED`, `INVALID_FILTER`). Изменение аддитивно: прежние клиенты, разбирающие только `error.code` и `error.message`, не затронуты.

### NEW-0721-5: Статистика Открытых линий — 6 методов дашборда

Новый раздел API для дашбордов контакт-центра: [POST /v1/openlines/stats](/docs/openlines/stats) (агрегаты за период), [GET /v1/openlines/operators](/docs/openlines/operators) (real-time нагрузка операторов), [POST /v1/openlines/sessions/search](/docs/openlines/sessions), [POST /v1/openlines/sessions/stats](/docs/openlines/sessions/stats), [POST /v1/openlines/sessions/transfers](/docs/openlines/sessions/transfers), [POST /v1/openlines/ratings/search](/docs/openlines/ratings). Требуется скоуп `imopenlines` и право тарифа `report_open_lines` (иначе `403 B24_TARIFF_RESTRICTION`).

**В процессе раскатки** — методы выходят в обновлении Битрикс24 `imopenlines 26.700.0` и доступны не на всех порталах. Пока обновление не приехало на портал, методы возвращают `422 METHOD_NOT_YET_AVAILABLE` с целевой версией в ответе — это признак раскатки, а не ошибка интеграции.

### FIX-0721-6: тарифный отказ Битрикс24 отдаётся как 403 B24_TARIFF_RESTRICTION на всех эндпоинтах

**Было**

Отказ Битрикс24 по тарифному праву приходил как `422 BITRIX_ERROR` с непрозрачным сообщением — отличить его от прочих ошибок Битрикс24 программно было нельзя.

**Стало**

Такой отказ отдаётся как `403` с кодом `B24_TARIFF_RESTRICTION`. Правило общее для всего V1 API, а не только для Открытых линий: любой эндпоинт, вызвавший метод Битрикс24, недоступный на тарифе портала, теперь отвечает этим кодом.

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

Клиенты с обычной обработкой ошибок продолжают работать без изменений — отказ остаётся ошибкой, просто становится точнее. Если вы отдельно ветвились на `422` для тарифных отказов, перенесите ветку на `403` и `error.code === 'B24_TARIFF_RESTRICTION'`. Этот код не означает сбой интеграции: возможность не входит в тариф портала Битрикс24, и повторять запрос бессмысленно до смены тарифа.

### FIX-0721-7: Версионные рантаймы деплоя ставят заявленную версию на Ubuntu 24.04

**Было**

Рантайм `node20` устанавливал Node.js 18 (в репозиториях Ubuntu 24.04 нет Node 20), а `python311` и RAG-рантаймы (`node20-rag`, `python311-rag`) падали на шаге установки — нужных пакетов в дистрибутиве нет. В ответе `GET /v1/infra/runtimes` поле `packages` показывало `postgresql-14`, хотя ставилась PostgreSQL 16.

**Стало**

`node20` ставит Node.js 20 (с проверкой мажорной версии), `python311` — Python 3.11, RAG-рантаймы — PostgreSQL 16 с расширением pgvector в базе приложения. Поле `packages` отражает фактическую версию (`postgresql-16`). Публичные идентификаторы рантаймов и формат запроса `/deploy` не изменились.

### FIX-0721-8: статус ремонта сервера корректен при опросе

**Было**

Опрос [GET /v1/infra/servers/:id/repair-status](/docs/infra/lifecycle/repair-status) при многоузловом бэкенде мог кратковременно вернуть `idle`, даже когда ремонт ещё шёл, — если запрос попадал на другой обслуживающий узел, чем тот, что выполняет ремонт. Клиент, опрашивающий статус в цикле, мог из-за этого ошибочно решить, что ремонт завершился, ещё до его старта.

**Стало**

Эндпоинт надёжно возвращает реальный прогресс ремонта (`running` / `done` / `failed`) независимо от того, на какой узел попал опрос.

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

Форма ответа не изменилась, действий со стороны клиента не требуется.

### FIX-0721-9: приложение на standalone-сервере больше не работает с правами администратора

**Было**

Приложение, задеплоенное на standalone Black Hole сервер, запускалось с правами администратора и без изоляции. Любая уязвимость в самом приложении (например, выполнение произвольного кода) сразу давала полный контроль над всей виртуальной машиной: доступ к ключам подключения сервера, к служебным настройкам и к системным файлам.

**Стало**

Приложение работает под выделенной непривилегированной учётной записью и видит только свой каталог (`extractTo`, по умолчанию `/opt/app`), которым владеет. Системные каталоги защищены от записи, повышение привилегий запрещено. Порт ниже 1024 по-прежнему работает — платформа выдаёт для него отдельное разрешение.

Команды деплоя (`install`, `preStart`) и `/exec` по-прежнему выполняются с правами администратора — здесь ничего не изменилось, `sudo` не нужен.

Ничего менять не требуется: если приложению для запуска действительно нужны права администратора, деплой автоматически возвращает прежний режим, завершается успешно и добавляет предупреждение с причиной. Чтобы сразу пропустить эту попытку (актуально для nginx в качестве команды запуска, MySQL через системный сокет и запуска через Docker), передайте `"hardening": "off"` в теле деплоя.

В `data.steps[]` появились два новых значения `step`: `service_user` — передача каталога деплоя непривилегированной учётной записи, и `hardening` — предупреждение о возврате приложения к прежнему режиму. Клиентам, которые разбирают шаги по имени, стоит их учесть.

### BC-0721-10: битый кандидат в image_url больше не роняет весь запрос

> Поддержка старого формата до: 21.01.2027

**Было**

Массив `content` мог нести несколько частей `image_url`. Если хотя бы одна из них
содержала не изображение — например HTML-страницу с ошибкой, закодированную в Base64
и объявленную как `image/png`, — платформа передавала её модели как есть. Модель не
могла её декодировать, и весь запрос завершался ошибкой `502` с кодом
`ai_provider_unavailable`, даже когда остальные изображения были корректны.

Отдельно: части с неподдерживаемым MIME-типом, повреждённым Base64 или превышением
лимита 20 МиБ отклонялись ответом `400 invalid_image_payload` — тоже на весь запрос
целиком.

**Стало**

Перед отправкой модели платформа проверяет фактическое содержимое каждой части
`image_url` по сигнатуре байтов, а не по заявленному MIME-типу. Часть, содержимое
которой является веб-ответом (HTML, XML, JSON, ответ HTTP) либо не декодируется,
заменяется на своей позиции текстовой заглушкой `[image unavailable: <причина>]`.
Остальные изображения обрабатываются как обычно, запрос завершается успешно.

Позиции частей сохраняются: длина массива `content` не меняется, поэтому нумерация
кандидатов на стороне клиента остаётся верной.

Отклонённые части видны в ответе — в поле `warnings` появляется запись с кодом
`IMAGE_CONTENT_REJECTED`, а в заголовках `X-Image-Parts-Rejected` с их количеством.
Для потоковых ответов заголовок приходит вместе с началом потока.

Ответом `400` теперь завершаются только структурные ошибки: отсутствующее поле
`url`, строка, не являющаяся ни URL, ни data-URI, неподдерживаемая схема и `http://`
в production.

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

Если ваш код полагался на `400 invalid_image_payload` как на признак того, что
изображение не принято, — читайте вместо этого `warnings` или заголовок
`X-Image-Parts-Rejected`. Запрос теперь завершается успешно, и молчаливой потери
изображения не происходит: факт замены всегда отражён в ответе.

Дополнительно изменилось поведение при отказе модели. Раньше любой не-2xx ответ
провайдера приходил как `502`, теперь статус отражает причину:

- ответ модели `400` или `422` → `400` с кодом `ai_provider_rejected`. Повторять
  такой запрос без изменений бесполезно;
- превышение лимита на стороне модели (`429`) → `429` с заголовком `Retry-After`.
  Повторить нужно, выдержав указанную задержку. В потоковом ответе заголовок
  невозможен, поэтому задержка приходит полем `retryAfter` в кадре ошибки;
- таймаут на стороне модели (`408`) → `503` с кодом `ai_provider_timeout`.

Ответы `401`, `403` и `5xx` по-прежнему приходят как `502`. Изменение затрагивает
[POST /v1/chat/completions](/docs/ai/chat/completions) и
[POST /v1/embeddings](/docs/ai/embeddings).

Ошибки со стороны модели теперь дополнительно несут поле `providerStatusCode` —
исходный HTTP-статус ответа модели. По нему `429` от модели отличается от `429`
собственного лимита платформы (у последнего поля нет): код `rate_limit_exceeded`
у обоих одинаковый, чтобы SDK ретраили единообразно, а различитель — это новое
необязательное поле.

Также в data-URI теперь допускаются параметры между типом и `;base64` —
`data:image/jpeg;name=photo.jpg;base64,...` больше не отклоняется.
