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

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

### NEW-0630-1: POST /v1/cowork/deploy-key — получить проектный ключ для деплоя из Cowork/Code

Ключ Cowork/Code (`vibe:cowork`) работает только с data-plane и блокируется на control-plane инфраструктуры с 403 `INFRA_FORBIDDEN_FOR_COWORK_KEY`. Новый эндпоинт [POST /v1/cowork/deploy-key](/docs/cowork) позволяет агенту самому получить отдельный проектный ключ с правом деплоя: вызовите его этим же Cowork-ключом, возьмите поле `key` из ответа (тело — плоский объект, без обёртки `data`) и используйте его как заголовок `X-Api-Key` для деплоя/provision/exec под `/v1/infra/*`.

Возвращаемый ключ несёт скоупы `vibe:infra` + `vibe:storage` (без `vibe:cowork`), действует 7 дней и привязан к владельцу и порталу Cowork-ключа. На каждый вызов выдаётся свежий ключ, прежний проектный ключ при этом отзывается (активен всегда один). Требуется скоуп `vibe:cowork` и активная подписка Cowork/Code; коды отказа — 403 `INSUFFICIENT_SCOPE` / 403 `COWORK_NOT_ACTIVATED` / 503 `DEPLOY_KEY_DISABLED` / 503 `INFRA_DISABLED`.

### NEW-0630-2: Self-hosted placement получает одноразовый код авторизации на appUrl

Для приложения с собственным `appUrl` (вне Black Hole), открытого как placement, платформа теперь добавляет к редиректу на `appUrl` одноразовый код авторизации (`?code=...`) вместо внутреннего gateway-токена. Приложение обменивает этот код на `vibe_session` существующим запросом `POST /v1/oauth/token` — `redirect_uri` должен точно совпадать с настроенным `appUrl`. Раньше такие приложения получали невостребуемый токен и не могли авторизовать пользователя.

### NEW-0630-3: Новый эндпоинт POST /v1/oauth/placement-session для self-hosted приложений

Self-hosted приложение (на собственном сервере, не на Black Hole), открытое как placement (iframe) в Битрикс24, теперь может обменять токен пользователя Битрикс24, полученный в placement-колбэке на своём обработчике, на `vibe_session`. Запрос `POST /v1/oauth/placement-session` с телом `{ app_key, access_token, member_id, domain }` (необязательно `refresh_token`, `expires_in`) идёт сервер-к-серверу — токен сессии не попадает в браузер. Раздел авторизации документации описывает обе топологии placement.

### FIX-0630-4: PATCH права OAuth-app-ключа: честный отказ вместо ложной выдачи

**Было**

`PATCH /v1/keys/:id` с добавлением права Bitrix24 к ключу OAuth-приложения (`vibe_app_*`), как и `PATCH /v1/apps/:id` с расширением `scopes` приложения, возвращал `200` и сохранял новый набор прав. Но права OAuth-приложения фиксируются при выпуске и от такой правки на стороне Bitrix24 не меняются, поэтому `GET /v1/me` затем сообщал право, которого Bitrix24 не выдавал, а реальный вызов отклонялся.

**Стало**

Добавление права Bitrix24 к ключу OAuth-приложения или к приложению теперь отклоняется с `403 OAUTH_SCOPE_CHANGE_REQUIRES_REISSUE`. Снятие прав и изменение `vibe:*`-прав работают по-прежнему. Чтобы получить новое право, выпустите новый ключ авторизации с нужным набором.

### FIX-0630-5: ключ со скоупом `tasks` теперь реально открывает методы задач

**Было**

Ключ, выписанный со скоупом `tasks` (множественное число — его предлагает UI-пикер), на dev-key-портале минтил вебхук, который Bitrix24 принимал, но к REST-методам модуля Задач не привязывал. `GET /v1/me` рапортовал `tasks`, но вызовы методов задач отклонялись на стороне Bitrix24. Скоуп `task` (единственное число) работал.

**Стало**

При выписке и правке ключа набор прав канонизируется к написанию, которое Bitrix24 реально привязывает к методам (`tasks` → `task`), поэтому ключ открывает методы задач независимо от выбранного написания. На уже выписанные ключи изменение не распространяется ретроактивно — перевыпустите ключ.

### FIX-0630-6: неверный формат FILES в комментарии таймлайна отклоняется с 400

**Было**

[POST /v1/timelines](/docs/entities/timelines/create) и `PATCH /v1/timelines/:id` принимали поле `FILES` в любом виде и отвечали `200`/`201`. Если форма отличалась от массива пар `[[имяФайла, base64Содержимое]]` — например плоский массив строк или одиночная пара без внешнего массива — комментарий создавался, но файл прикреплялся как мусорный (со случайным именем и нечитаемым содержимым) либо терялся молча, без признаков ошибки.

**Стало**

Поле `FILES`, переданное не в виде массива пар `[[имяФайла, base64Содержимое]]`, отклоняется до обращения к Битрикс24 ошибкой `400 INVALID_FILES_SHAPE` с подсказкой о правильной форме. Пустой `FILES` (`[]`) и отсутствие поля по-прежнему допустимы. Проверка действует на одиночных `POST`/`PATCH` и в батче (`POST /v1/batch`, `POST /v1/timelines/batch`).

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

Кто передаёт `FILES` в задокументированной форме `[[имяФайла, base64Содержимое]]` — изменений нет. Кто полагался на другие формы — теперь получит явную `400` вместо молча испорченного вложения, и сможет исправить запрос.

### FIX-0630-7: пустые поля ботов и сотрудников приходят как null/[], а не false/{}

**Было**

В ответах карточки бота ([GET /v1/bots/:botId](/docs/bots/management/get), [POST /v1/bots](/docs/bots/management/create), [PATCH /v1/bots/:botId](/docs/bots/management/update)) незаполненные поля в `users[]` отдавались неверным примитивом: даты `lastActivityDate`, `mobileLastDate`, `desktopLastDate` приходили как булево `false`, а пустой список `phones` — тоже как `false`. То же поле `lastActivityDate` в `GET /v1/users` приходило как пустой объект `{}`. Из-за этого `new Date(lastActivityDate)` молча давал начало эпохи, а `phones.map(...)` падал с ошибкой типа.

**Стало**

Незаполненная дата на всех путях кодируется единообразно как `null`, а пустой список телефонов — как `[]`. Заполненная дата по-прежнему приходит ISO-строкой, заполненный список — массивом.

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

Менять ничего не нужно — типы стали корректными. Код, который опирался на сравнение с `false` для пустых значений, перестанет срабатывать: проверяйте дату на `null`, а список телефонов — как массив.

**Затронутые эндпоинты:** [GET /v1/bots/:botId](/docs/bots/management/get), [POST /v1/bots](/docs/bots/management/create), [PATCH /v1/bots/:botId](/docs/bots/management/update), `GET /v1/users`

### NEW-0630-8: Пересвязка OAuth-credentials приложения без удаления

Новый эндпоинт [POST /v1/apps/:id/relink-oauth](/docs/apps) обновляет `bitrixClientId` и `bitrixClientSecret` у существующего приложения, не удаляя его. Это нужно, когда локальное OAuth-приложение пересоздали на портале Битрикс24 и у него сменился `client_id`: раньше единственным путём было удалить приложение (что рвало связанные бот, openline и привязки) и создать заново.

Тело запроса: `{ bitrixClientId, bitrixClientSecret }` (оба обязательны). Парный ключ, бот и привязки сохраняются. Если этот `client_id` уже привязан к другому приложению — `409 OAUTH_CLIENT_ID_IN_USE`. Ключом самого OAuth-приложения вызвать нельзя — `403 OAUTH_APP_KEY_CANNOT_RELINK` (нужен личный ключ или кабинет). После пересвязки переустановите приложение на портале — это восстановит подписку на события.

### NEW-0630-9: Веб-поиск: полный текст страниц, изображения, режим новостей и фильтры по доменам в research

**Было**

`POST /v1/search` принимал `include_raw_content` как булев флаг, но полный текст найденных страниц в ответ не попадал. Не было параметров для режима новостей и для запроса изображений. `POST /v1/research` принимал `include_domains` и `exclude_domains`, но молча их отбрасывал.

**Стало**

`POST /v1/search` получил два новых необязательных параметра: `topic` (`general` или `news`, по умолчанию `general`) и `include_images` (булев, по умолчанию `false`). Булев `include_raw_content` теперь действительно возвращает полный текст: у каждого результата появилось поле `rawContent` (полный текст страницы, ограниченный по размеру). В ответе добавились верхнеуровневые `images` (массив объектов с полем `url`) и `ignored_filters` (массив строк — переданные фильтры, которые провайдер не смог применить). Эти поля приходят и в синхронном теле ответа, и в кадре `done` потоковой передачи. Заголовок `X-Search-Filters-Ignored` сохранён и теперь может перечислять `topic` и `include_images`. `POST /v1/research` теперь применяет `include_domains` и `exclude_domains` (до 20 каждый) у провайдеров с поддержкой и сообщает о превышении через `ignored_filters` в кадре `done`. Какие именно возможности доступны у выбранного движка — возвращает `GET /v1/search/providers`. Клиентам со строгой валидацией схемы по `additionalProperties` нужно учесть новые поля ответа.

### NEW-0630-10: Чтение AI-расшифровок звонков клиентов через API

Новый эндпоинт [GET /v1/activities/:activityId/transcript](/docs/entities/activities/transcript) возвращает готовую AI-расшифровку звонка клиента по идентификатору CRM-активности «Звонок». Метод только читает уже готовую расшифровку — генерацию не запускает. Требует скоуп `crm`. Если расшифровки для звонка ещё нет, поле `data.transcription` равно `null` — это штатный ответ, а не ошибка.
