# Изменения API: 31 августа 2026

[← Журнал изменений](/docs/changelog) · [Август 2026](/docs/changelog/2026-08)

### FIX-0831-1: сервер, у которого не поднялся агент, больше не числится рабочим

**Было**

Если установка агента при старте машины обрывалась, виртуалка всё равно доходила до
`running`, и сервер так и оставался в этом состоянии. В карточке и в списке серверов
приходил `status: "running"` с пустыми `provisionError` и `provisionErrorCode` — по ответу
этих эндпоинтов отличить рабочий сервер от неработающего было нельзя, а тарификация
продолжалась.

```json
{ "status": "running", "blackholeStatus": "NONE", "provisionError": null, "provisionErrorCode": null }
```

**Стало**

Такой сервер переводится в `error` с объяснением и новым кодом
`provisionErrorCode: "AGENT_NEVER_CONNECTED"`, и тарификация закрывается.

```json
{ "status": "error", "blackholeStatus": "NONE", "provisionError": "Сервер загрузился, но агент так и не подключился — …", "provisionErrorCode": "AGENT_NEVER_CONNECTED" }
```

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

Менять ничего не нужно: `error` — существующий статус, новых полей не появилось. Что стоит
учесть:

- Цикл ожидания готовности сервера теперь завершается: `running` при `blackholeStatus: "NONE"`
  больше не длится вечно. Если ждёте пары `running` + `CONNECTED`, добавьте выход по `error`.
- Восстановление — [`POST /v1/infra/servers/:id/repair`](/docs/infra/lifecycle/repair): он
  ставит агента заново по SSH. Пересоздавать сервер стоит, только если починка не помогла.
- `POST /v1/infra/servers/:id/start` на таком сервере отвечает `422` с кодом
  `AGENT_NEVER_CONNECTED`. Статус ответа не изменился: по такой машине `/start` и раньше отдавал
  `422` (`SERVER_WRONG_STATE`, потому что она числилась `running`) — меняется код, не статус. Запуск тут не чинит ничего, а объяснение стирает — поэтому он и
  отклоняется. Клиент, который перезапускает упавшие серверы по расписанию, должен читать код и
  звать починку.
- Три операции жизненного цикла на такой машине переходят из успешного ответа в отказ, потому
  что требуют `running`: `POST /v1/infra/servers/:id/stop` и `POST /v1/infra/servers/:id/reboot`
  отвечают `422` с кодом `SERVER_WRONG_STATE`, а `POST /v1/infra/servers/:id/sleep-now` — `400`
  с кодом `NOT_RUNNING`. Выключать такую машину и не нужно: тарификация закрывается вместе с
  вердиктом, так что плановая остановка ради экономии на ней ничего не экономит. Рабочие
  действия — [`repair`](/docs/infra/lifecycle/repair) (починить) и `DELETE /v1/infra/servers/:id`
  (удалить); их же перечисляет `availableActions` в ответе.
- Вердикт выносится только что созданным серверам, уже работающие он не трогает. Перед ним
  платформа сверяется со шлюзом, поэтому живой туннель с потерянным уведомлением чинится, а не
  помечается ошибкой. Если агент подключится позже, сервер сам вернётся в `running`, а
  `provisionError` и `provisionErrorCode` очистятся.

### FIX-0831-2: отказ выписки на бесплатном тарифе называет причину вместо «повторите через минуту»

**Было**

Портал с оплаченной подпиской на Маркетплейс, но на бесплатном тарифе Битрикс24, получал на выписку ключа и на установку приложения `502 CONNECTOR_REST_UNAVAILABLE` с текстом «Битрикс24 сейчас не выдал ключ. Повторите попытку через минуту». Повтор не помогал никогда: на бесплатном тарифе Битрикс24 не считает подписку действующей и отказывает в REST целиком, а ответ об этом не сообщал.

**Стало**

Та же ситуация отвечает `402 B24_PAID_TARIFF_REQUIRED`. Поле `userMessage` называет оба условия доступа и говорит, какое из них не выполнено: подписка у портала есть, нужен платный тариф Битрикс24. Успешные ответы не изменились и по-прежнему отдают HTTP 200, прочие причины отказа по-прежнему отвечают `502 CONNECTOR_REST_UNAVAILABLE`.

### FIX-0831-3: поиск и исследование через провайдера Linkup

**Было**

Любой вызов `POST /v1/search` или `POST /v1/research` с `provider: "linkup"` отклонялся провайдером: платформа не передавала обязательное поле `outputType`. По этой же причине не проходила проверка собственного ключа Linkup — подключение BYOK-ключа возвращало `INVALID_CREDENTIAL` с текстом `HTTP 400` даже для действующего ключа.

**Стало**

Вызовы к Linkup выполняются, подключение BYOK-ключа отражает реальное состояние ключа: действующий ключ сохраняется, недействующий отклоняется.

В `/v1/search` поле `answer` заполняется при `include_answer: true` и равно `null` при `include_answer: false`; в этом случае текст страницы приходит в `results[].content`. Поле `results[].published_date` у Linkup всегда `null` — провайдер не отдаёт дату публикации, и матрица возможностей в `GET /v1/search/providers` теперь сообщает об этом честно.

### FIX-0831-6: Пакетное создание линий телефонии отдаёт адресуемый номер в results[].id

**Было**

`POST /v1/telephony-lines/batch` с `action: "create"` отвечал `200`, но в `results[].id` приходил внутренний числовой идентификатор строки Битрикс24. Подставить его в `PATCH` или `DELETE /v1/telephony-lines/:number` было нельзя — линия ищется по номеру, и запрос отвечал `422`. Одиночный `POST /v1/telephony-lines` при этом уже отдавал правильный номер, то есть две двери на одно и то же создание расходились в ответе.

**Стало**

`results[].id` — тот же номер, что передан в поле `number` этого элемента, и то же значение, что отдаёт одиночный [POST /v1/telephony-lines](/docs/telephony/lines/create). Значение возвращается без изменений, включая номера с `+` и другими символами. Ответ по-прежнему `200`, состав остальных полей не менялся.

### FIX-0831-7: повторный вход в Коворк на бесплатном месте больше не отбивается

**Было**

Если человек отменял бесплатную подписку Коворка, повторный вход десктопа отбивался
`403 COWORK_SUB_CANCELLED`: отменённое место не оживало, а ключ выдаётся только активному.
Из приложения выхода не было — браузерного пути к возврату бесплатного места в этом
сценарии не существует, и человек оставался без входа насовсем.

**Стало**

Место с нулевой ценой возвращается в активное состояние прямо на входе, и ключ выдаётся.
Платное место по-прежнему отвечает `403 COWORK_SUB_CANCELLED` / `COWORK_SUB_PAUSED` —
его возобновление это оплата, и оно делается осознанно в кабинете.

### FIX-0831-8: `TOKEN_MISSING` для личного ключа называет причину отказа в вебхуке

**Было**

Если у личного ключа (`vibe_api_*`) не было вебхука Битрикс24 из-за того, что портал
отказал владельцу ключа в праве на входящие вебхуки, либо прошлая попытка выпустить
вебхук завершилась ошибкой, ответ `401 TOKEN_MISSING` всё равно называл общую причину
(например, `WEBHOOK_NOT_CONFIGURED`) и отправлял читать `GET /v1/me`, не объясняя,
что вебхука не будет и кто должен это исправить.

**Стало**

В этих двух сценариях `error.details.reason` возвращает `WEBHOOK_MINT_REFUSED_BY_PORTAL`
(нужны действия администратора портала) или `WEBHOOK_MINT_FAILED` (платформа повторяет
попытку сама), а `error.message` называет причину и адресата действия явно. Для
`WEBHOOK_MINT_REFUSED_BY_PORTAL` совет переподключить ключ
больше не приходит — платформа выпустит вебхук автоматически, как только администратор
портала откроет право на входящие вебхуки, и повторный запрос переподключения не поможет.
Код ответа, HTTP-статус и структура `error` не изменились.

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

Обрабатывайте `WEBHOOK_MINT_REFUSED_BY_PORTAL` и `WEBHOOK_MINT_FAILED` как отдельные
значения `details.reason` наравне с уже документированными — не пересоздавайте ключ и не
дёргайте `reconnect` в цикле по этим причинам, ждите действия администратора портала или
автоматический повтор платформы.

Отдельно про текст сообщения. `error.message` теперь ветвится по причине и по тому,
доступно ли этому ключу переподключение, — и это касается НЕ только двух новых причин.
У ключа без скоупов Битрикс24 (`VIBE_SCOPES_ONLY`) текст стал своим, а ключам, которым
платформа переподключение отобьёт (коворк-ключи, ключи приложений, ключи с привязанным
сервером или живым агентом), вместо совета переподключиться приходит совет создать новый
ключ. Значения `details.reason` в этих сценариях прежние. Если ваш код разбирает
`error.message` поиском по строке — переключитесь на `details.reason`: текст сообщения
контрактом не является и меняется.

### FIX-0831-9: пополнение вайбов коробочному порталу открыто на международной установке

**Было**

Коробочному порталу на международной установке пополнение всегда отвечало
отказом `BOX_TOPUP_NOT_AVAILABLE`. Превью подписки
`GET /v1/cowork/subscription/preview` возвращало такому аккаунту
`topUpAvailable: false`, а каталог пакетов приезжал пустым.

**Стало**

Коробочный портал на международной установке пополняется наравне с облачным —
получает каталог пакетов, ссылку на оплату и `topUpAvailable: true` в превью
подписки. Отказ `BOX_TOPUP_NOT_AVAILABLE` остаётся только там, где пополнение
коробочным порталам закрыто для региона портала. Формат ответа не меняется,
успешный ответ остаётся HTTP 200.
