
## Создать приложение из Cowork/Code

`POST /v1/cowork/applications`

Создаёт личное приложение и выписывает его ключ, который возвращается ровно один раз. Сервер при этом не создаётся: у личного приложения его нет по определению — сервер появляется от вашего деплоя и сам привязывается к карточке. Заголовок `Idempotency-Key` обязателен.

**Скоуп:** `vibe:cowork` (ключ Cowork/Code) | **Базовый URL:** `https://vibecode.bitrix24.tech/v1` | **Авторизация:** `X-Api-Key`

Значения для полей запроса берите из [параметров создания приложения](./applications-defaults.md) — там же лежат наборы прав и режим доступа, который аккаунт назначает новым ключам.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|-------|----------|
| `Idempotency-Key` (header) | string | да | Строка от 1 до 255 символов из набора `[A-Za-z0-9_.:-]`. Область действия — вызывающий ключ, поэтому два разных клиента могут прислать одну и ту же строку. Срока жизни у неё нет: она живёт столько же, сколько созданное ею приложение. Подробнее — [Идемпотентность](#идемпотентность) |

## Поля запроса (body)

| Поле | Тип | Обяз. | Описание |
|------|-----|-------|----------|
| `name` | string | да | Название приложения. От 2 до 100 символов, управляющие символы запрещены. Пробелы по краям обрезаются, и длина считается уже после обрезки, поэтому название из одного символа отвечает `400` и с пробелами вокруг |
| `type` | string | да | Тип приложения. Работает значение `personal`. Значение `external` схема принимает, но эндпоинт отвечает `400 APP_TYPE_NOT_AVAILABLE` |
| `b24Scopes` | array | нет | Права Битрикс24 для выписываемого ключа. Поле пропущено — ключ получает все права, которые может выдать этот аккаунт, а в `warningCodes` приходит `B24_SCOPES_DEFAULTED_TO_ALL`. Сузить права выданного ключа нечем, поэтому присылайте явный список, если полный набор вам не нужен. Пустой массив отбивается: он значил бы ключ без прав аккаунта. Значения берите из набора `scopePresets` в [параметрах создания](./applications-defaults.md) |
| `mode` | string | нет | Режим доступа ключа — `READONLY` или `READWRITE`. Без поля берётся режим аккаунта, он же приходит в `mode` параметров создания. Если аккаунт назначает новым ключам только чтение, значение `READWRITE` отвечает `403` — политика аккаунта сильнее запроса |
| `expiresInDays` | number \| null | нет | Срок жизни ключа в днях, целое от 1. Без поля и при `null` ключ выписывается бессрочным — политика срока из параметров создания сама не применяется, см. «Известные особенности» |

Схема строгая: лишнее поле в теле отвечает `400 VALIDATION_ERROR` и называет его. Размер тела ограничен 64 КБ.

## Примеры

Эндпоинт принимает только ключ Cowork/Code, поэтому примеров два: ключ без скоупа `vibe:cowork` получает `403 INSUFFICIENT_SCOPE`.

### curl — ключ Cowork/Code

```bash
curl -X POST https://vibecode.bitrix24.tech/v1/cowork/applications \
  -H "X-Api-Key: YOUR_COWORK_KEY" \
  -H "Idempotency-Key: create-app-2026-08-25-01" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Отчёт по сделкам",
    "type": "personal",
    "b24Scopes": ["crm"]
  }'
```

### JavaScript — ключ Cowork/Code

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/applications', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_COWORK_KEY',
    'Idempotency-Key': 'create-app-2026-08-25-01',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Отчёт по сделкам',
    type: 'personal',
    b24Scopes: ['crm'],
  }),
})

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.rawApiKey, data.keyExpiresAt)
}
```

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

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | Всегда `true` при успехе |
| `data.application` | object | Карточка приложения — та же форма, что отдаёт [`GET /v1/applications/:id`](/docs/applications/get). Ниже перечислены поля, которые наполнены сразу после создания. Полный список — на странице карточки |
| `data.application.id` | string | Идентификатор приложения |
| `data.application.name` | string | Название, которое вы передали |
| `data.application.type` | string | `PERSONAL` для приложения, созданного этим эндпоинтом |
| `data.application.server` | object \| null | `null` на создающем ответе: сервера у личного приложения ещё нет. При повторе запроса поле отражает состояние НА МОМЕНТ ПОВТОРА, поэтому у приложения, которое успели задеплоить, здесь придёт объект сервера |
| `data.application.openUrl` | string \| null | `null` на создающем ответе: открывать пока нечем. При повторе — текущий адрес приложения, если он уже выдан |
| `data.applicationId` | string | Повторяет `application.id`. Отдаётся отдельно, чтобы связать вашу локальную запись с карточкой, не разбирая её внутренности |
| `data.rawApiKey` | string \| null | Сырой ключ приложения. Возвращается ОДИН раз, восстановить нельзя. Формат — `vibe_api_`, затем 32 символа латиницы и цифр, затем `_` и 6 шестнадцатеричных символов в нижнем регистре, всего 48 символов. `null` при повторе запроса |
| `data.keyExpiresAt` | string \| null | Срок действия ключа, ISO 8601. `null` — ключ бессрочный. При повторе запроса поле ОТСУТСТВУЕТ, а не приходит пустым |
| `data.mode` | string | Режим доступа выписанного ключа — `READONLY` или `READWRITE`. При повторе запроса поле ОТСУТСТВУЕТ |
| `data.warnings` | array | Предупреждения текстом. Пустой, когда предупреждений нет |
| `data.warningCodes` | array | Коды предупреждений. `KEY_NOT_REPLAYABLE` при повторе запроса. `B24_SCOPES_DEFAULTED_TO_ALL`, когда `b24Scopes` не прислан и ключ получил все права аккаунта. Оба поля приходят всегда, даже пустыми — форма ответа одна для всех случаев |

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

```json
{
  "success": true,
  "data": {
    "application": {
      "id": "cmt8ht5u40005ensk4fp45ebx",
      "name": "Отчёт по сделкам",
      "description": null,
      "type": "PERSONAL",
      "iconUrl": null,
      "createdAt": "2026-08-25T09:59:01.324Z",
      "updatedAt": "2026-08-25T09:59:01.324Z",
      "viewerState": "owner",
      "pinned": false,
      "author": { "name": "Роман Глушаков" },
      "isEmbedded": false,
      "openUrl": null,
      "openTarget": null,
      "server": null,
      "sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
      "activeOperation": null
    },
    "applicationId": "cmt8ht5u40005ensk4fp45ebx",
    "rawApiKey": "vibe_api_ge5crx6rXOgoFikYi7G2inWA6dx7VO1V_9bcf92",
    "keyExpiresAt": null,
    "mode": "READWRITE",
    "warnings": [],
    "warningCodes": []
  }
}
```

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

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

```json
{
  "success": false,
  "error": {
    "code": "KEY_LIMIT_REACHED",
    "message": "Maximum number of API keys reached",
    "details": { "used": 40, "limit": 40, "requested": 1, "scope": "portal" }
  }
}
```

Удаление выданного ключа в кабинете НЕ отменяет идемпотентность: карточка остаётся, а повтор с тем же ключом идемпотентности по-прежнему отвечает `201` с заголовком `Idempotent-Replayed: true` и `warningCodes: ["KEY_NOT_REPLAYABLE"]`. Нового ключа этот повтор не выпишет — сырой ключ отдаётся ровно один раз, при первом создании; получить рабочий ключ для существующего приложения можно через `POST /v1/keys/:id/rotate`.

## Ошибки

Перечень отказов самого эндпоинта исчерпывающий: кода, которого здесь нет, эндпоинт не отдаёт. Выписка ключа идёт через Битрикс24 Нетворк, и его отказы переподнимаются дословно — они в таблице тоже. У коробочного аккаунта выписка идёт своим каналом и приносит собственные коды, разобранные в [Ключах и авторизации](/docs/keys-auth). Форма ответа та же, ветвитесь по `error.code`.

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `IDEMPOTENCY_KEY_REQUIRED` | Заголовок `Idempotency-Key` не передан |
| 400 | `INVALID_IDEMPOTENCY_KEY` | Заголовок передан, но не подходит по длине или набору символов |
| 400 | `VALIDATION_ERROR` | Нарушена схема тела: длина `name`, управляющие символы в нём, неизвестное значение `mode`, `expiresInDays` меньше единицы, пустой `b24Scopes` или лишнее поле. Сообщение называет поле |
| 400 | `APP_TYPE_NOT_AVAILABLE` | Передан `type: "external"` — в этой версии он недоступен |
| 400 | `INVALID_SCOPES` | В `b24Scopes` есть право, которого нет в каталоге Битрикс24. Сообщение перечисляет непринятые значения |
| 400 | `PORTAL_NOT_LINKED` | Аккаунт Битрикс24 не связан с Битрикс24 Нетворк, и выписать ключ нечем |
| 400 | `PERSONAL_KEY_WEBHOOK_SCOPES_INVALID` | В `b24Scopes` не осталось ни одного права, которое можно привязать к аккаунту. Приходит, когда переданы ТОЛЬКО права `placement`, `entity` или `userfieldtype` — личный ключ их не исполняет. Добавьте хотя бы одно право доступа к данным, например `crm` |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Ключ не опознан: такой строки на платформе нет |
| 401 | `KEY_INACTIVE` | Ключ выключен |
| 401 | `KEY_EXPIRED` | Срок действия вызывающего ключа истёк |
| 402 | `ACCOUNT_FROZEN` | Баланс аккаунта исчерпан — пополните счёт |
| 402 | `MARKETPLACE_REQUIRED` | У аккаунта подписочной модели нет активной подписки. Тело ответа содержит путь подключения. Повтор без изменения состояния аккаунта даёт тот же ответ |
| 402 | `KZ_PAID_ONLY` · `UZ_PAID_ONLY` | Тот же отказ у аккаунтов ТАРИФНОЙ модели: подписки как продукта в этих странах нет, нужен платный или демо-тариф Битрикс24. Тариф выбирается на стороне Битрикс24, тело ответа содержит адрес |
| 402 | `BY_PAID_ONLY` | Белорусский аккаунт без оплаченного доступа. Доступ открывает платный или демо-тариф Битрикс24, и открывает его также платная подписка — в Беларуси она продаётся. Тариф выбирается на стороне Битрикс24, тело ответа содержит адрес. Код приходит, когда для аккаунта включена тарифная модель |
| 403 | `INSUFFICIENT_SCOPE` | У ключа нет скоупа `vibe:cowork` |
| 403 | `SCOPE_NOT_AVAILABLE_ON_PORTAL` | В `b24Scopes` есть право модуля, которого у аккаунта нет. Сообщение перечисляет такие права. Тот же отказ дают соседние эндпоинты выдачи ключей |
| 403 | `COWORK_HARNESS_KEY_FORBIDDEN` | Вызов сделан ключом стороннего агента, выписанным на подписку. Создавать приложения такому ключу нельзя — см. [Свой агент на подписке](/docs/cowork/harness) |
| 403 | `COWORK_NOT_ACTIVATED` | Нет активной подписки Cowork/Code для пары сотрудник и аккаунт |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Вызывающий ключ Cowork/Code выписан в режиме «только чтение», а создание приложения — запись. Отказ приходит раньше остальных проверок |
| 403 | `APP_CREATION_RESTRICTED` | Политика аккаунта ограничивает круг тех, кто создаёт приложения, и владелец ключа в него не входит. Подробнее — [Права на создание](/docs/access-rights) |
| 403 | `KEY_POLICY_READONLY_REQUIRED` | Аккаунт назначает новым ключам только чтение, а в теле передан `mode: "READWRITE"`. Отказ безусловный: административного канала у этого ключа нет |
| 409 | `KEY_LIMIT_REACHED` | Квота ключей исчерпана. `error.details` содержит `used`, `limit` и `requested`; без `scope` это лимит пользователя на портале, а `scope: "portal"` означает портальный потолок платформы |
| 409 | `IDEMPOTENCY_KEY_BODY_MISMATCH` | Тот же `Idempotency-Key` пришёл с другим телом |
| 409 | `IDEMPOTENCY_KEY_ALREADY_USED` | Ключ идемпотентности израсходован: он принадлежит приложению, которое с тех пор удалили, ЛИБО попытка дошла до обращения к Битрикс24 и там не удалась. Во втором случае ключ остаётся занятым намеренно — повтор с ним мог бы выписать второй ключ поверх первого. Состояние постоянное: возьмите новый ключ идемпотентности |
| 409 | `IDEMPOTENCY_CONCURRENT_RETRY` | Параллельный запрос с тем же ключом идемпотентности ещё выполняется. Единственный из трёх отказов идемпотентности, где повтор осмыслен. Заявка на ключ занимается ДО выписки, поэтому такой отказ приходит раньше, чем создаётся ключ: второе приложение и второй ключ не появятся, сколько бы запросов ни ушло одновременно |
| 415 | `FST_ERR_CTP_INVALID_MEDIA_TYPE` | Тело прислано с типом содержимого, который этот маршрут не разбирает. Отправляйте `Content-Type: application/json` |
| 429 | `RATE_LIMITED` | Превышен предел частоты на связку аккаунт и владелец ключа. Суммарный лимит платформы — 6 запросов в минуту. Действующее для вашего ключа значение приходит в заголовке `x-ratelimit-limit` — оно ниже суммарного, поскольку лимит делится между репликами |
| 429 | `QUOTA_EXCEEDED` | Исчерпана суточная бесплатная квота вызовов при нулевом балансе на предоплате |
| 413 | `PAYLOAD_TOO_LARGE` | Тело запроса больше 64 КиБ. Достигается, например, очень длинным `b24Scopes`. Проверяется до разбора тела, поэтому ни заявка, ни ключ не создаются |
| 500 | `APPLICATION_CREATE_FAILED` | Запись не удалась. Возможны ДВА состояния, и различить их по ответу нельзя: либо ключ уже выписан, а карточку записать не удалось, либо не удалась ещё сама заявка и не создано ничего. В первом случае в кабинете появится лишний ключ — отзовите его. В обоих случаях повторяйте с НОВЫМ ключом идемпотентности: повтор со старым может ответить `409 IDEMPOTENCY_KEY_ALREADY_USED` |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 Нетворк отказал или был недоступен во время выписки ключа. Приложение и ключ не созданы, но ключ идемпотентности ИЗРАСХОДОВАН: отказ приходит уже после обращения к Битрикс24, поэтому заявка остаётся занятой намеренно — иначе повтор мог бы выписать второй ключ поверх первого. Повторяйте с НОВЫМ ключом идемпотентности: повтор со старым детерминированно ответит `409 IDEMPOTENCY_KEY_ALREADY_USED`. Под этот же код попадает терминальный случай — истекла авторизация владельца ключа в Битрикс24 Нетворк, и лечит её только сам владелец, войдя в Битрикс24 Нетворк заново. Отличить одно от другого по ответу нельзя, отдельного поля нет, поэтому сделайте ОДИН повтор с новым ключом, а на втором таком ответе остановитесь и покажите человеку, что владельцу ключа нужно войти заново |
| 503 | `COWORK_FEATURE_DISABLED` | Cowork/Code отключён на уровне платформы |
| 503 | `APP_CREATE_DISABLED` | Создание приложений из Cowork/Code отключено. Заранее это видно по полю `available` в [параметрах создания](./applications-defaults.md) |

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

## Идемпотентность

Заголовок `Idempotency-Key` обязателен, и это отличие от [создания сервера](/docs/infra/servers/create), где он необязателен. Причина в том, что эндпоинт выписывает ключ и занимает место в квоте: без защиты обрыв сети оставлял бы второе приложение и второй ключ.

Повтор запроса с тем же ключом и тем же телом отвечает `201`, добавляет заголовок ответа `Idempotent-Replayed: true` и возвращает ту же карточку. Сырой ключ при этом приходит `null`, а в `warningCodes` появляется `KEY_NOT_REPLAYABLE`: у платформы лежит только хеш ключа, восстановить сам ключ нечем.

**Потерянный ключ повтором не возвращается, и перевыпустить его этим ключом Cowork/Code нельзя** — идентификатора выданного ключа в ответе нет, а раздел `/v1/keys` принимает только управляющий ключ. Практический путь один: создайте приложение заново с НОВЫМ значением `Idempotency-Key` и получите свежий ключ, а лишнюю карточку и её ключ уберите в кабинете платформы. Поэтому сохраняйте `rawApiKey` сразу, в том же обработчике ответа.

Отпечаток снимается с приведённого к общему виду тела: порядок полей и порядок значений внутри `b24Scopes` на сравнение не влияют, поэтому переставленные местами поля по-прежнему считаются тем же запросом. Пробелы по краям `name` тоже не влияют, а `expiresInDays: null` и отсутствие этого поля считаются одним и тем же. Другое тело с тем же ключом отвечает `409 IDEMPOTENCY_KEY_BODY_MISMATCH`, а не отдаёт чужой результат.

Повторяйте то же тело, а не уточнённое. Опущенное необязательное поле и то же поле со значением, которое аккаунт подставил бы сам, дают РАЗНЫЕ отпечатки: если первый запрос шёл без `mode`, а повтор дописал `mode`, придёт `409 IDEMPOTENCY_KEY_BODY_MISMATCH`. По той же причине различаются `["crm"]` и `["crm", "crm"]` — набор прав перед сравнением сортируется, но дубликаты из него не убираются.

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

**Срок жизни ключа по умолчанию не применяется — поле `keyExpiresInDays` из параметров создания это подсказка, а не значение по умолчанию.** Если не передать `expiresInDays`, ключ выписывается бессрочным, и в ответе `keyExpiresAt` приходит `null`. Хотите ограничить срок — передайте число дней явно, а показать человеку можно значение из параметров создания.

**Права `placement`, `entity` и `userfieldtype` на выписанном ключе не окажутся.** В смешанном наборе они отбрасываются без отказа: личный ключ их не исполняет. Отказ приходит только тогда, когда кроме них в `b24Scopes` не передано ничего. Состав прав проверяйте по выданному ключу, а не по отправленному запросу.

**Выписанный ключ не умеет обращаться к искусственному интеллекту и веб-поиску.** Он несёт `vibe:infra`, `vibe:storage` и запрошенные права Битрикс24, а `vibe:ai` и `vibe:search` в него не попадают ни в строке прав, ни в правах во время работы. Приложение, созданное так, не сможет расходовать кошелёк аккаунта на модели и поиск.

**Порядок отказов несущий: сначала права вызывающего ключа, потом состояние продукта, потом стоимость.** Проверки идут так: сначала сам ключ — существование, срок, режим «только чтение», заморозка баланса. Затем скоуп `vibe:cowork`, класс ключа, отключение всего Cowork/Code, активность подписки, отключение самого мастера. Затем идемпотентность и схема тела. И только потом доступ аккаунта к платформе, политика создания приложений и квота ключей. Если нарушено несколько условий сразу, придёт первый отказ из этой цепочки.

**Отказ `500 APPLICATION_CREATE_FAILED` означает, что ключ уже выписан.** Место в квоте занято, а карточки нет. Повторяйте с новым ключом идемпотентности, а лишний ключ отзовите — отзыв освобождает место в квоте, удалять ключ не обязательно.

**Часть полей карточки эта ручка не наполняет — читайте их из витрины.** Набор полей совпадает с [`GET /v1/applications/:id`](/docs/applications/get), но `pinned` здесь всегда `false`, а `sources` и `activeOperation` всегда пустые, даже если приложение уже задеплоено и человек закрепил его в кабинете. За этими признаками обращайтесь к витрине приложений, а из ответа создания берите идентификатор, имя и ключ.

**Сервер к карточке привязывается сам.** После создания приложения поднимайте сервер своим [`POST /v1/infra/servers`](/docs/infra/servers/create) с параметрами из блока `server` [параметров создания](./applications-defaults.md). Отдельного вызова, связывающего сервер с карточкой, нет и не нужно.

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

- [Параметры создания приложения](./applications-defaults.md)
- [Создать сервер](/docs/infra/servers/create)
- [Карточка приложения](/docs/applications/get)
- [Ключи и авторизация](/docs/keys-auth)
- [Cowork/Code](/docs/cowork)
- [Ошибки](/docs/errors)
