Для AI-агентов: markdown этой страницы — /docs-content/cowork/applications-key.md индекс документации — /llms.txt
Выдать или заменить ключ приложения
POST /v1/cowork/applications/:id/key
Выдаёт ключ приложению с пустым слотом или заменяет уже выданный и возвращает новый ключ ровно один раз. Так публикуют приложение, добавленное из каталога: сырой ключ не восстанавливается, а перевыпуск через управляющий ключ настольному клиенту недоступен.
Скоуп: vibe:cowork (ключ Cowork/Code) | Базовый URL: https://vibecode.bitrix24.tech/v1 | Авторизация: X-Api-Key
Какая ветка сработала, называет поле issued: minted — слот был пуст и ключ выдан, rotated — ключ в слоте заменён. Заранее ветку не угадать, поэтому решает платформа. Вызывают эндпоинт двое. Владелец приложения получает ключ в слоте приложения. Участник команды разработки сервера приложения получает собственный ключ этого сервера — ключ владельца при этом не меняется и не показывается.
Параметры
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
Параметрid (path) |
Типstring | Обяз.да | ОписаниеИдентификатор приложения. Список: GET /v1/applications |
ПараметрIdempotency-Key (header) |
Типstring | Обяз.да | ОписаниеСтрока от 1 до 255 символов из набора [A-Za-z0-9_.:-]. Область действия — вызывающий ключ. Как отвечает повтор — в «Известных особенностях» |
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
ПолеsyncServerEnv |
Типboolean | Обяз.нет | ОписаниеЗаменить ключ в окружении сервера приложения и перезапустить приложение. По умолчанию false. Действует только на ветке rotated: при minted прежнего ключа в окружении нет. Итог приходит в поле envSync ответа |
Тело необязательно: запрос без тела и запрос с пустым объектом {} равнозначны. Схема строгая: лишнее поле отвечает 400 VALIDATION_ERROR. Размер тела ограничен 8 КиБ.
Примеры
Эндпоинт принимает только ключ Cowork/Code, поэтому примеров два. У личного ключа и ключа OAuth-приложения нет скоупа vibe:cowork, отказ по скоупу — 403 INSUFFICIENT_SCOPE.
curl — ключ Cowork/Code
curl -X POST https://vibecode.bitrix24.tech/v1/cowork/applications/APPLICATION_ID/key \
-H "X-Api-Key: YOUR_COWORK_KEY" \
-H "Idempotency-Key: app-key-2026-09-22-01" \
-H "Content-Type: application/json" \
-d '{}'
JavaScript — ключ Cowork/Code
const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/applications/APPLICATION_ID/key', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_COWORK_KEY',
'Idempotency-Key': 'app-key-2026-09-22-01',
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
})
if (!res.ok) {
const { error } = await res.json()
throw new Error(`${res.status} ${error.code}`)
}
const { data } = await res.json()
// Сырой ключ приходит один раз — сохраните его сразу
if (data.rawApiKey === null) {
// Это повтор запроса: ключ уже выдан, заново он не показывается
} else {
saveKey(data.applicationId, data.rawApiKey)
}
// Прежний ключ работает до previousKey.graceUntil — доставьте новый ключ серверу раньше
if (data.previousKey?.graceUntil) {
console.log('Прежний ключ перестанет работать:', data.previousKey.graceUntil)
}
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
Полеsuccess |
Типboolean | ОписаниеВсегда true при успехе |
Полеdata.application |
Типobject | null | ОписаниеКарточка приложения — та же форма, что отдаёт GET /v1/applications/:id. Её блок key уже показывает новый ключ. null только в одном случае: ключ выдан, а карточку после этого прочитать не удалось — тогда в warningCodes приходит APPLICATION_CARD_UNAVAILABLE |
Полеdata.applicationId |
Типstring | ОписаниеПовторяет application.id, чтобы связать локальную запись с карточкой, не разбирая её |
Полеdata.issued |
Типstring | null | Описаниеminted — слот был пуст и ключ выдан, rotated — ключ в слоте заменён. При повторе запроса — то, что сделал исходный запрос. null у замены, сделанной до того, как платформа начала записывать ветку |
Полеdata.rawApiKey |
Типstring | null | ОписаниеСырой ключ. Возвращается ОДИН раз, восстановить нельзя. Формат — vibe_api_, затем 32 символа латиницы и цифр, затем _ и 6 шестнадцатеричных символов. null при повторе запроса |
Полеdata.key |
Типobject | null | ОписаниеНовый ключ без секрета — id, prefix, suffix, scopes, status, expiresAt, createdAt. null при повторе запроса |
Полеdata.key.scopes |
Типarray | ОписаниеПрава нового ключа. Ключ владельца, выданный в пустой слот, несёт только vibe:infra и vibe:storage. Замена переносит права прежнего ключа |
Полеdata.key.expiresAt |
Типstring | null | ОписаниеСрок действия нового ключа, ISO 8601. null — ключ бессрочный. При замене срок наследуется от прежнего ключа, см. «Известные особенности» |
Полеdata.previousKey |
Типobject | null | ОписаниеЗаменённый ключ — id, graceUntil, status. Приходит только владельцу на ветке rotated, в остальных случаях null |
Полеdata.previousKey.graceUntil |
Типstring | null | ОписаниеМомент, когда прежний ключ перестанет работать: через 24 часа после замены или раньше, если раньше наступает его собственный срок. null, когда прежний ключ был заблокирован, — отсрочки у него нет |
Полеdata.envSync |
Типobject | null | ОписаниеИтог замены ключа в окружении сервера: статус в поле status, значения — в таблице ниже. null, когда syncServerEnv не передан, на ветке minted и в ответе участнику команды разработки |
Полеdata.warnings |
Типarray | ОписаниеПредупреждения текстом. Пустой, когда предупреждений нет |
Полеdata.warningCodes |
Типarray | ОписаниеКоды предупреждений. APPLICATION_HAS_AUTH_KEY — у приложения есть и ключ авторизации: карточка продолжает показывать его, а вызов затронул личный ключ. ENV_SYNC_NOT_APPLICABLE_FOR_COLLABORATOR — ответ участнику команды разработки. KEY_NOT_REPLAYABLE — повтор запроса. APPLICATION_CARD_UNAVAILABLE — карточку прочитать не удалось |
Значения envSync.status. Поле variable называет затронутую переменную окружения, поле reason уточняет skipped и recreate_failed.
| Статус | Что произошло |
|---|---|
Статусupdated |
Что произошлоКлюч заменён в окружении приложения, приложение перезапущено |
Статусrestart_failed |
Что произошлоКлюч в окружении заменён, перезапуск не удался — перезапустите приложение сами |
Статусowner_restore_failed |
Что произошлоКлюч в окружении заменён, но файл окружения остался недоступен приложению. Перезапуск не поможет, пока приложению не вернут доступ к файлу |
Статусnot_found |
Что произошлоПрежний ключ в окружении не найден, окружение не тронуто. Впишите новый ключ сами |
Статусskipped |
Что произошлоЗамена не выполнялась: reason: "no_server" — у приложения нет сервера, reason: "galaxy" — доставка ключа в контейнеры для аккаунта выключена |
Статусunreachable |
Что произошлоСервер или контейнер спит либо недоступен, окружение не тронуто |
Статусfailed |
Что произошлоПлатформа не смогла определить, куда доставить ключ, или доставка оборвалась |
Статусrecreated |
Что произошлоКонтейнер пересоздан с новым ключом в окружении. На время перезапуска приложение обрывает открытые соединения — это плановый простой |
Статусnot_required |
Что произошлоВ окружении контейнера нет ключа платформы, менять нечего |
Статусbaked_in_image |
Что произошлоКлюч зашит в образ контейнера, пересоздание его не обновит. Переопределите переменную при запуске или пересоберите образ из исходников |
Статусrecreate_failed |
Что произошлоЗамена началась и не завершилась. Причина — в reason: rolled_back, app_down, busy, read_failed или timeout |
Статусsuperseded |
Что произошлоБолее поздняя замена ключа уже применилась к этому контейнеру |
Пример ответа
Замена ключа в занятом слоте, issued: "rotated":
{
"success": true,
"data": {
"application": {
"id": "cmud90k3b0009cicg8yxl2rf8",
"name": "Отчёт по сделкам",
"description": null,
"type": "PERSONAL",
"iconUrl": null,
"createdAt": "2026-09-22T22:31:23.063Z",
"updatedAt": "2026-09-22T22:31:23.092Z",
"viewerState": "owner",
"pinned": false,
"author": { "name": "Автор приложений" },
"isEmbedded": false,
"openUrl": null,
"openTarget": null,
"server": null,
"sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
"activeOperation": null,
"key": {
"slot": "api",
"present": true,
"prefix": "vibe_api_…",
"suffix": "9529",
"status": "ACTIVE",
"expiresAt": null,
"lastUsedAt": null,
"rotatable": true,
"rotateBlockedReason": null,
"affectsShownKey": true
}
},
"applicationId": "cmud90k3b0009cicg8yxl2rf8",
"issued": "rotated",
"rawApiKey": "vibe_api_…",
"key": {
"id": "b3d37d59-5b50-4e72-aa12-8a2b40a012f8",
"prefix": "vibe_api_…",
"suffix": "9529",
"scopes": ["crm", "vibe:infra", "vibe:storage"],
"status": "ACTIVE",
"expiresAt": null,
"createdAt": "2026-09-22T22:31:23.086Z"
},
"previousKey": {
"id": "5d192322-3ced-438e-bc4f-0cbba01b9937",
"graceUntil": "2026-09-23T22:31:23.087Z",
"status": "ACTIVE"
},
"envSync": null,
"warnings": [],
"warningCodes": []
}
}
Выдача ключа в пустой слот, issued: "minted":
{
"success": true,
"data": {
"application": {
"id": "cmud90jwg0001cicg4qgipzws",
"name": "Дашборд продаж",
"description": null,
"type": "PERSONAL",
"iconUrl": null,
"createdAt": "2026-09-22T22:31:22.816Z",
"updatedAt": "2026-09-22T22:31:22.889Z",
"viewerState": "owner",
"pinned": false,
"author": { "name": "Автор приложений" },
"isEmbedded": false,
"openUrl": null,
"openTarget": null,
"server": null,
"sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
"activeOperation": null,
"key": {
"slot": "api",
"present": true,
"prefix": "vibe_api_…",
"suffix": "f08a",
"status": "ACTIVE",
"expiresAt": null,
"lastUsedAt": null,
"rotatable": true,
"rotateBlockedReason": null,
"affectsShownKey": true
}
},
"applicationId": "cmud90jwg0001cicg4qgipzws",
"issued": "minted",
"rawApiKey": "vibe_api_…",
"key": {
"id": "61a91657-2e88-4aeb-848f-1951327efd71",
"prefix": "vibe_api_…",
"suffix": "f08a",
"scopes": ["vibe:infra", "vibe:storage"],
"status": "ACTIVE",
"expiresAt": null,
"createdAt": "2026-09-22T22:31:22.879Z"
},
"previousKey": null,
"envSync": null,
"warnings": [],
"warningCodes": []
}
}
Пример ответа при ошибке
403 — ключ в слоте приложения шире вызывающего ключа:
{
"success": false,
"error": {
"code": "KEY_ROTATE_WIDER_THAN_CALLER",
"message": "The key in this application slot is wider than your key. Re-issue it from the web cabinet, where the owner sees what the new key will be allowed to do."
}
}
Ошибки
Выписка ключа идёт тем же каналом Битрикс24, что у создания приложения, и его отказы переподнимаются дословно. У коробочного аккаунта выписка идёт своим каналом и приносит собственные коды, разобранные в Ключах и авторизации. Форма ответа та же, ветвитесь по error.code.
| HTTP | Код | Описание |
|---|---|---|
| HTTP400 | КодIDEMPOTENCY_KEY_REQUIRED |
ОписаниеЗаголовок Idempotency-Key не передан |
| HTTP400 | КодINVALID_IDEMPOTENCY_KEY |
ОписаниеЗаголовок передан, но не подходит по длине или набору символов |
| HTTP400 | КодVALIDATION_ERROR |
ОписаниеЛишнее поле в теле или syncServerEnv не булево значение |
| HTTP400 | КодPORTAL_NOT_LINKED |
ОписаниеАккаунт Битрикс24 не связан с Битрикс24 Нетворк, и выписать ключ нечем |
| HTTP400 | КодBOX_NO_DEVELOPER_KEY |
ОписаниеКоробочный аккаунт: у владельца приложения нет ключа разработчика, и выписать ключ нечем |
| HTTP401 | КодMISSING_API_KEY |
ОписаниеНе передан заголовок X-Api-Key |
| HTTP401 | КодINVALID_API_KEY |
ОписаниеКлюч не опознан: такой строки на платформе нет |
| HTTP401 | КодKEY_INACTIVE |
ОписаниеКлюч выключен |
| HTTP401 | КодKEY_EXPIRED |
ОписаниеСрок действия вызывающего ключа истёк |
| HTTP402 | КодACCOUNT_FROZEN |
ОписаниеБаланс аккаунта исчерпан — пополните счёт |
| HTTP402 | КодMARKETPLACE_REQUIRED |
ОписаниеТолько выдача, а не замена: у аккаунта нет действующей подписки BitrixGPT + Маркетплейс. В странах, где доступ даёт тариф Битрикс24, приходит код своей страны — KZ_PAID_ONLY, UZ_PAID_ONLY или BY_PAID_ONLY. Замена эту проверку не проходит: она переносит права прежнего ключа и новых не выдаёт |
| HTTP402 | КодINT_TARIFF_REQUIRED |
ОписаниеТолько выдача, а не замена: аккаунт получает доступ по тарифу Битрикс24, а тариф бесплатный |
| HTTP403 | КодINSUFFICIENT_SCOPE |
ОписаниеУ ключа нет скоупа vibe:cowork |
| HTTP403 | КодCOWORK_HARNESS_KEY_FORBIDDEN |
ОписаниеВызов сделан ключом стороннего агента, выписанным на подписку. Такому ключу эндпоинт недоступен — см. Свой агент на подписке |
| HTTP403 | КодCOWORK_NOT_ACTIVATED |
ОписаниеНет активной подписки Cowork/Code для пары сотрудник и аккаунт |
| HTTP403 | КодWRITE_BLOCKED_READONLY_KEY |
ОписаниеВызывающий ключ в режиме «только чтение», а выдача и замена ключа — запись. error.details называет ключ и его режим |
| HTTP403 | КодNOT_APPLICATION_OWNER |
ОписаниеВызывающий не владеет приложением и не входит в команду разработки его сервера |
| HTTP403 | КодKEY_ROTATE_WIDER_THAN_CALLER |
ОписаниеКлюч в слоте приложения шире вызывающего ключа. Замена здесь молча сузила бы приложение, которым могут пользоваться другие, поэтому такой ключ перевыпускают в кабинете |
| HTTP403 | КодKEY_POLICY_READONLY_REQUIRED |
ОписаниеТолько ключ участника команды разработки: выдаваемый ключ шире режима, который аккаунт назначает новым ключам. Владельцу ключ в пустой слот выдаётся в режиме политики, и этот отказ ему не приходит |
| HTTP403 | КодINFRA_DISABLED_FOR_PORTAL |
ОписаниеТолько выдача, а не замена: администратор портала выключил работу с серверами, а новый ключ несёт vibe:infra |
| HTTP403 | КодPORTAL_TARIFF_UNREADABLE |
ОписаниеТолько выдача, а не замена: тариф аккаунта прочитать не удалось, поэтому какой тариф нужен, ответ не называет. Покупка тарифа отказ не снимает |
| HTTP403 | КодPORTAL_SUBSCRIPTION_UNREADABLE |
ОписаниеТолько выдача, а не замена: состояние подписки аккаунта прочитать не удалось. Покупка отказ не снимает — приложение нужно переподключить под главным администратором аккаунта |
| HTTP404 | КодAPPLICATION_NOT_FOUND |
ОписаниеПриложения с таким id на аккаунте нет или оно удалено |
| HTTP409 | КодKEY_ROTATE_OAUTH_APP_KEY |
ОписаниеВ личном слоте лежит ключ авторизации. Его перевыпуск пересоздаёт OAuth-приложение на аккаунте и меняет client_id, поэтому делается в кабинете |
| HTTP409 | КодKEY_ROTATE_SYSTEM_KEY |
ОписаниеВ слоте лежит ключ, который платформа выдаёт своим эндпоинтом. Кнопки перевыпуска в кабинете у такого ключа нет — обратитесь в поддержку |
| HTTP409 | КодKEY_ROTATE_LIVE_OAUTH_GRANT |
ОписаниеУ ключа есть живое разрешение авторизации, и замена оставила бы его на отзываемом ключе. Сначала отзовите разрешение в кабинете |
| HTTP409 | КодKEY_ROTATE_NOT_ACTIVE |
ОписаниеКлюч в слоте отозван или его срок истёк. Верните ключ в работу или продлите срок в кабинете и повторите |
| HTTP409 | КодKEY_ROTATE_KEY_VANISHED |
ОписаниеКлюч удалили, пока шёл запрос. Повторите |
| HTTP409 | КодAPPLICATION_KEY_RECOVERY_REQUIRED |
ОписаниеКлюч в слоте — незавершённая замена. Новый ключ идемпотентности запрет не снимает: нужно восстановление через поддержку |
| HTTP409 | КодAPPLICATION_KEY_REPLACE_IN_PROGRESS |
ОписаниеНа приложении уже идёт другая замена ключа либо она завершилась, пока этот запрос ждал очереди. Одна замена на приложение за раз, с любым ключом идемпотентности. Дождитесь её, перечитайте карточку и только потом просите снова. Замена, брошенная упавшим запросом, перестаёт мешать через две минуты |
| HTTP409 | КодKEY_LIMIT_REACHED |
ОписаниеТолько выдача, а не замена: квота ключей исчерпана. error.details содержит used, limit и requested, а scope: "portal" означает портальный потолок платформы |
| HTTP409 | КодCOLLABORATOR_KEY_REQUIRES_SERVER |
ОписаниеУчастник команды разработки: у приложения нет живого сервера, а ключ участника привязан к серверу |
| HTTP409 | КодCOLLABORATOR_MEMBERSHIP_BIND_CONFLICT |
ОписаниеУчастник команды разработки: членство не удалось надёжно привязать к аккаунту, и ключ не выдан. Попросите владельца сервера добавить вас заново |
| HTTP409 | КодIDEMPOTENCY_KEY_BODY_MISMATCH |
ОписаниеТот же Idempotency-Key пришёл с другим телом |
| HTTP409 | КодIDEMPOTENCY_KEY_ALREADY_USED |
ОписаниеКлюч идемпотентности израсходован, и повторить нечего: он отправлен для другого приложения, карточку удалили либо ключ под ним уже выдан, а запрос потом упал. Прочитайте карточку и повторите с НОВЫМ ключом идемпотентности |
| HTTP409 | КодIDEMPOTENCY_CONCURRENT_RETRY |
ОписаниеПараллельный запрос с тем же ключом идемпотентности ещё выполняется. Единственный из трёх отказов идемпотентности, где повтор осмыслен |
| HTTP413 | КодPAYLOAD_TOO_LARGE |
ОписаниеТело больше 8 КиБ. Проверяется до разбора тела, поэтому ничего не резервируется и ключ не выписывается |
| HTTP415 | КодFST_ERR_CTP_INVALID_MEDIA_TYPE |
ОписаниеТело прислано с типом содержимого, который маршрут не разбирает. Отправляйте Content-Type: application/json или запрос без тела |
| HTTP429 | КодRATE_LIMITED |
ОписаниеПревышен предел частоты на связку аккаунт и владелец ключа. Суммарный лимит платформы — 6 запросов в минуту. Действующее для вашего ключа значение приходит в заголовке x-ratelimit-limit — оно ниже суммарного, поскольку лимит делится между репликами |
| HTTP429 | КодQUOTA_EXCEEDED |
ОписаниеИсчерпана суточная бесплатная квота вызовов при нулевом балансе на предоплате |
| HTTP500 | КодAPPLICATION_KEY_ATTACH_FAILED |
ОписаниеКлюч выдан в пустой слот, но привязать его к приложению не удалось. error.details.orphanKeyId называет этот ключ: отзовите его и повторите с НОВЫМ ключом идемпотентности |
| HTTP500 | КодAPPLICATION_KEY_REPOINT_FAILED |
ОписаниеНовый ключ выписан, но карточка не дошла до проверенного конечного состояния. Ключ error.details.orphanKeyId остаётся под защитой восстановления, и повтор с другим ключом идемпотентности запрещён. Если на этот ключ ничего не указывает, удалите его штатным удалением ключа. Непустой error.details.strandedSlots перечисляет то, что ещё указывает на ключ, — тогда обратитесь в поддержку |
| HTTP500 | КодKEY_ROTATE_REVOKE_FAILED |
ОписаниеЗамена заблокированного ключа: отзыв его живых токенов доступа не подтвердился. Сырого ключа в ответе нет, выписанный ключ остаётся под защитой восстановления, и повтор не разрешён, пока восстановление не завершено |
| HTTP502 | КодBITRIX_UNAVAILABLE |
ОписаниеБитрикс24 отказал или был недоступен во время выписки ключа. Прежний ключ остаётся как был: действующий продолжает работать, заблокированный — нет |
| HTTP503 | КодCOWORK_FEATURE_DISABLED |
ОписаниеCowork/Code отключён на уровне платформы |
Полный список общих ошибок API — Ошибки.
Известные особенности
Режим выданного ключа не шире вашего ключа. На ключ, который получает владелец приложения, режим места Cowork/Code не влияет. В пустой слот ключ выдаётся в самом узком из режима, который аккаунт назначает новым ключам, и режима вызывающего ключа: политика «только чтение» выдачу не отбивает, а сужает. Замена даёт ключ не шире текущего режима заменяемого ключа и не шире вызывающего.
Карточка заранее говорит, пройдёт ли вызов. Блок key карточки приложения несёт rotatable — пройдёт ли этот вызов для вас — и rotateBlockedReason с причиной отказа. WIDER_THAN_CALLER значит, что ключ в слоте шире вашего, WRITE_BLOCKED_READONLY_KEY — что ваш ключ не меняет данные. Незнакомую причину читайте как «заменить нельзя, причина неизвестна». Флаг отражает то, что платформа уже знает, поэтому false не тупик, а true не гарантия: отказ самого эндпоинта всё равно обрабатывайте.
Без syncServerEnv новый ключ до сервера не доходит. Приложение держит прежний ключ в своём окружении и начинает получать отказы в момент previousKey.graceUntil — это не всегда через 24 часа. Присылайте true, если у вас нет своего способа доставить ключ серверу.
Срок нового ключа при замене наследуется. Бессрочный ключ остаётся бессрочным, действующий срок переносится как есть. Срок, который уже прошёл, заменяется сроком по умолчанию аккаунта — тем же keyExpiresInDays, что отдают параметры создания.
Заблокированный ключ в слоте замене не мешает. Его живые токены доступа гасятся и на новый ключ не переезжают.
Участник команды разработки получает свой ключ. Ключ привязан к серверу приложения и открывает только маршруты разработки этого сервера. Окружение сервера владельца такой вызов не меняет. Режим ключа участника — самый узкий из режима вызывающего ключа и режима места Cowork/Code, если вызывающий ключ принадлежит месту: у места в режиме «только чтение» ключ участника выдаётся в том же режиме, даже когда сам вызывающий ключ может изменять данные.
Повтор с тем же ключом идемпотентности ключа не возвращает. Повтор с тем же телом отвечает 201 с заголовком Idempotent-Replayed: true. Секрет хранится только в виде хеша, поэтому сохраняйте rawApiKey сразу, в том же обработчике ответа.