## Перевыпустить API-ключ

`POST /v1/keys/:id/rotate`

Выпускает новый API-ключ взамен прежнего с теми же настройками и переносит на него привязки прежнего ключа.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|----------|
| `id` (path) | string | да | Идентификатор записи прежнего ключа. Список: [`GET /v1/keys`](/docs/management-keys/list) |

Тело запроса может быть пустым или `{}`: поля тела не читаются, настройки нового ключа берутся с прежнего.

## Примеры

Запрос принимает только менеджмент-ключ — см. [Ограничения](/docs/management-keys#ограничения).

### curl — менеджмент-ключ

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/keys/6dbad0ce-79a9-43f5-8ca4-3e1af7ef63bc/rotate" \
  -H "X-Api-Key: YOUR_MANAGEMENT_KEY"
```

### JavaScript — менеджмент-ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/keys/6dbad0ce-79a9-43f5-8ca4-3e1af7ef63bc/rotate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_MANAGEMENT_KEY',
  },
})

const { success, data, error } = await res.json()
if (success) {
  // Значение нового ключа приходит только в этом ответе
  console.log('Новый ключ:', data.rawKey)
} else if (error.details?.orphanKeyId) {
  // Замена отменена, порядок действий — в «Известных особенностях»
  console.error(error.code, error.details)
}
```

## Поля ответа

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | Всегда `true` при успехе |
| `data.id` | string | Идентификатор записи нового ключа |
| `data.name` | string | Название, перенесённое с прежнего ключа |
| `data.type` | string | Тип записи ключа, всегда `APP` |
| `data.userId` | string | Идентификатор владельца ключа |
| `data.portalId` | string | Идентификатор портала |
| `data.clientId` | string \| null | Идентификатор клиента OAuth, если он записан на ключе. Иначе `null` |
| `data.scopes` | array | [Скоупы](/docs/scopes), перенесённые с прежнего ключа |
| `data.ipWhitelist` | array | Разрешённые IP-адреса. Пустой массив — без ограничения |
| `data.expiresAt` | null | У нового ключа срока действия нет |
| `data.rateLimit` | number \| null | Индивидуальный лимит запросов к AI-эндпоинтам, `null` — общий лимит платформы |
| `data.status` | string | Статус нового ключа, `ACTIVE` |
| `data.lastUsedAt` | null | Новым ключом ещё не пользовались |
| `data.createdAt` | string | Дата создания (ISO 8601) |
| `data.updatedAt` | string | Дата последнего изменения (ISO 8601) |
| `data.accessMode` | string | `READWRITE` или `READONLY` |
| `data.totalDefault` | boolean \| null | Приходит ли `meta.total` в списках, запрошенных этим ключом. `null` — действует настройка платформы |
| `data.issuedVia` | string \| null | Канал, которым выписан вебхук нового ключа: `per-portal` и `cloud-shared` — модуль-коннектор на портале, `dev_key` — ключ разработчика владельца, `legacy` — регистрация через Битрикс24 Network, `none` — вебхук не заводился |
| `data.rawKey` | string | Полное значение нового ключа. Повторно не возвращается |

Полей `prefix`, `suffix` и `b24Ready` в ответе нет — они приходят в [`GET /v1/keys/:id`](/docs/management-keys/get).

## Пример ответа

201 — новый ключ выпущен:

```json
{
  "success": true,
  "data": {
    "id": "9b1f2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
    "name": "Интеграция с CRM",
    "type": "APP",
    "userId": "fafa9780-eed7-4d29-b040-2448d924f452",
    "portalId": "0d9f7744-f853-47c7-b06e-6f61f9dd1b7f",
    "clientId": null,
    "scopes": ["crm"],
    "ipWhitelist": [],
    "expiresAt": null,
    "rateLimit": null,
    "status": "ACTIVE",
    "lastUsedAt": null,
    "createdAt": "2026-10-29T12:22:53.937Z",
    "updatedAt": "2026-10-29T12:22:53.937Z",
    "accessMode": "READONLY",
    "totalDefault": null,
    "issuedVia": "cloud-shared",
    "rawKey": "vibe_api_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  }
}
```

## Пример ответа при ошибке

409 — прежний ключ уже отозван:

```json
{
  "success": false,
  "error": {
    "code": "KEY_NOT_ACTIVE",
    "message": "Key is no longer active"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `PERSONAL_KEY_WEBHOOK_SCOPES_INVALID` | У прежнего ключа остались только права контекста приложения — `placement`, `entity`, `userfieldtype`. Набор прав проверяется до обращения к порталу, поэтому отказ одинаков на любом аккаунте. Сначала добавьте прежнему ключу право на данные через [`PATCH /v1/keys/:id`](/docs/management-keys/update) |
| 400 | `BOX_NO_DEVELOPER_KEY` | Коробочный портал: у владельца ключа нет ключа разработчика, а прежний ключ несёт права Битрикс24 |
| 400 | `BOX_NO_DEVELOPER_KEY` | Коробочный портал: у прежнего ключа есть вебхук, а снять его без ключа разработчика владельца нельзя |
| 402 | `ACCOUNT_FROZEN` | Баланс аккаунта заморожен |
| 403 | `SYSTEM_KEY_ROTATE_FORBIDDEN` | Перевыпускается ключ, который платформа выдаёт на своём эндпоинте: настольного приложения Cowork/Code, агента, проектный ключ для деплоя. В тексте ответа сказано, где этот ключ выдаётся заново |
| 403 | `COWORK_PLATFORM_DISABLED` | Ключ, оплачиваемый подпиской Cowork/Code: Cowork/Code отключён на уровне платформы |
| 403 | `COWORK_ACCESS_REQUIRED` | Ключ подписки Cowork/Code: владельцу ключа доступ к Cowork/Code не открыт |
| 403 | `COWORK_EXTERNAL_CLIENTS_DISABLED` | Ключ подписки Cowork/Code: администратор портала запретил сторонние клиенты |
| 403 | `COWORK_SUBSCRIPTION_INACTIVE` | Ключ подписки Cowork/Code: подписка приостановлена или отменена |
| 403 | `B24_MARKET_SUBSCRIPTION_REQUIRED` | На аккаунте нет действующей подписки маркетплейса, и вебхук не выписывается. Перевыпуск возобновляется сразу после активации подписки |
| 403 | `INT_TARIFF_REQUIRED` | Тот же отказ в регионе, где доступ определяется платным тарифом Битрикс24 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Менеджмент-ключ, которым отправлен запрос, работает в режиме `READONLY` |
| 403 | `MANAGEMENT_SCOPE_REQUIRED` | У менеджмент-ключа нет скоупа `vibe:mgmt:keys` |
| 404 | `KEY_NOT_FOUND` | Ключа с таким `id` нет, он принадлежит другому пользователю, это менеджмент-ключ или ключ без портала |
| 404 | `KEY_NOT_FOUND` | Ключ удалили, пока шла выписка. Новый ключ не создаётся |
| 409 | `KEY_NOT_ACTIVE` | Прежний ключ уже не действует: его отозвали или его статус — `EXPIRED`. Новый ключ не создаётся. Перечитайте ключ через [`GET /v1/keys/:id`](/docs/management-keys/get) |
| 409 | `KEY_NOT_ACTIVE` | Ключ авторизации (`vibe_app_`) не действует, удалён, его приложение удалено или ключ изменили после начала запроса. Новый ключ не создаётся |
| 409 | `REISSUE_IN_PROGRESS` | Только ключ авторизации (`vibe_app_`): с ключом этого приложения уже идёт другая операция — перевыпуск, изменение или удаление. Повторите запрос после её завершения |
| 409 | `KEY_ROTATION_RECOVERY_REQUIRED` | Замена этого ключа не завершена: предыдущий перевыпуск закончился ответом `500` или ещё не закончился другой перевыпуск этого же ключа. Отказ относится и к старому, и к новому ключу такой замены. Новый ключ не создаётся. Если ответа `500` не было, а отказ приходит и через несколько минут, обратитесь в поддержку |
| 409 | `KEY_ROTATION_SOURCE_CHANGED` | Привязка исходного ключа изменилась во время выписки. Новый ключ не создаётся. Перечитайте карточку и состояние ключа перед новой операцией |
| 409 | `PORTAL_ORIGIN_CUTOVER_BUSY` | У портала ключа меняется адрес. Повторите перевыпуск позже |
| 500 | `KEY_ROTATE_REVOKE_FAILED` | Замена отменена: у заблокированного ключа не подтверждено, что его токены доступа погашены. Новый ключ создан, его значения в ответе нет. Порядок действий — в «Известных особенностях» |
| 500 | `KEY_ROTATION_REPOINT_FAILED` | Замена отменена: не подтверждён перенос привязок на новый ключ. Порядок действий — там же |
| 500 | `KEY_ROTATION_FINALIZE_FAILED` | Замена отменена: не подтверждено завершение замены. Порядок действий — там же |
| 503 | `PORTAL_ORIGIN_CUTOVER_UNAVAILABLE` | Не удалось проверить, меняется ли адрес портала ключа. Повторите перевыпуск позже |
| 401 | `WRONG_KEY_TYPE` | Запрос отправлен ключом портала — личным `vibe_api_` или ключом авторизации `vibe_app_`. Эндпоинт принимает только менеджмент-ключ |
| 401 | `KEY_INACTIVE` | Менеджмент-ключ отозван или заблокирован |
| 401 | `KEY_EXPIRED` | Срок действия менеджмент-ключа закончился |
| 401 | `INVALID_API_KEY` | Ключ с переданным значением не найден |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |

Остальные отказы выписки у перевыпуска те же, что у создания: оба метода выписывают ключ одним путём. Это отказы выписки со статусом `409`, `410` и `502`, со статусом `503` — `NETWORK_DEVKEY_REQUIRED` и `CONNECTOR_KEY_ISSUE_TIMEOUT`, а со статусом `403` — `B24_MARKET_TRIAL_USED`, `B24_INSUFFICIENT_SCOPE`, `B24_ACCESS_DENIED` и `CONNECTOR_KEY_ISSUE_FORBIDDEN`. Их описания и поле `error.reason` — в [Создать API-ключ](/docs/management-keys/create#ошибки). Статус `503` приходит и от выписки, и от проверки адреса портала, поэтому решайте по коду, а не по статусу: `PORTAL_ORIGIN_CUTOVER_UNAVAILABLE` из таблицы выше можно повторить позже, а `CONNECTOR_KEY_ISSUE_TIMEOUT` сразу повторять нельзя — вебхук на портале мог уже появиться. Проверка доступа портала к платформе на перевыпуск не распространяется, поэтому `402 MARKETPLACE_REQUIRED`, `402 INT_TARIFF_REQUIRED`, `403 PORTAL_TARIFF_UNREADABLE` и `403 PORTAL_SUBSCRIPTION_UNREADABLE` здесь не приходят. Со статусом `402` до перевыпуска доходит только отказ самого Битрикс24 в выписке по тарифу — `BY_PAID_ONLY`, `KZ_PAID_ONLY`, `UZ_PAID_ONLY`, `B24_PAID_TARIFF_REQUIRED`.

Отказы `OWNER_DELETED`, `OWNER_BLOCKED`, `ACCOUNT_PENDING_ERASURE` и `B24_USER_DELETED` зависят от аккаунта владельца ключа — см. [Состояние аккаунта владельца](/docs/management-keys#состояние-аккаунта-владельца).

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Что переносится на новый ключ.** Название, права, разрешённые IP-адреса, режим доступа, индивидуальный лимит и настройка `totalDefault` переносятся с прежнего ключа как есть. Серверы, приложения, токены доступа, операции деплоя и боты прежнего ключа переезжают на новый. Срок действия не переносится: новый ключ бессрочный.

**Переходный период прежнего ключа — до 24 часов.** Прежний ключ продолжает работать 24 часа после перевыпуска, затем перестаёт действовать. Если его собственный срок истекает раньше, он сохраняется: перевыпуск не продлевает ключ и не возвращает к жизни истёкший.

**Заблокированный ключ тоже перевыпускается.** Перевыпуск — единственный способ заменить ключ в статусе `BLOCKED`, разблокировки нет. Блокировка прежнего ключа остаётся, переходного периода он не получает, а его токены доступа гасятся, а не переезжают на новый ключ.

**Ответ `500` — новый ключ создан, но замена отменена.** Значения нового ключа в ответе нет. Его идентификатор приходит в `error.details.orphanKeyId`. Поле `error.details.strandedSlots` появляется, если при отмене что-то не удалось вернуть прежнему ключу, и перечисляет это: `applications`, `servers`, `accessTokens`, `deployOperations`, `bots`, `previousKeyGrace`. Если поля нет или в нём нет `previousKeyGrace`, прежний ключ сохраняет прежний срок действия. Дальнейшие шаги:

- Поле `strandedSlots` есть — обратитесь в поддержку. Не удаляйте новый ключ, пока на него что-то ссылается.
- Поля `strandedSlots` нет — удалите новый ключ запросом [`DELETE /v1/keys/:id`](/docs/management-keys/delete) с идентификатором из `orphanKeyId`. После ответа `204` ещё раз перевыпустите прежний ключ. Если удаление ответило `409 KEY_ROTATION_RECOVERY_REQUIRED`, обратитесь в поддержку.

Пока замена не завершена, перевыпуск и удаление прежнего и нового ключа отвечают `409 KEY_ROTATION_RECOVERY_REQUIRED`, поэтому повтор перевыпуска без этих шагов не пройдёт. Исключение — удаление нового ключа по второму пункту.

**Отказ по ключу, выданному платформой, прежний ключ не трогает.** При отказе `SYSTEM_KEY_ROTATE_FORBIDDEN` или отказе по подписке Cowork/Code прежний ключ продолжает работать. Обычных ключей кабинета эти проверки не касаются. Что умеет ключ подписки — [Свой агент на подписке](/docs/cowork/harness).

## Смотрите также

- [Список API-ключей портала](/docs/management-keys/list)
- [Создать API-ключ](/docs/management-keys/create)
- [Получить API-ключ](/docs/management-keys/get)
- [Изменить API-ключ](/docs/management-keys/update)
- [Удалить API-ключ](/docs/management-keys/delete)
- [Менеджмент-ключи](/docs/management-keys)
