For AI agents: markdown of this page — /docs-content-en/cowork/applications-create.md documentation index — /llms.txt

Create an application from Cowork/Code

POST /v1/cowork/applications

Creates a personal application and issues its key, which is returned exactly once. The endpoint does not create a server: a personal application has none by definition. Your deployment creates the server, which is then linked to the card automatically. The Idempotency-Key header is required.

Scope: vibe:cowork (Cowork/Code key) | Base URL: https://vibecode.bitrix24.com/v1 | Authorization: X-Api-Key

Take the request field values from the application creation parameters. The creation parameters also include the scope presets and the access mode the issued key will get.

Parameters

Parameter Type Required Description
ParameterIdempotency-Key (header) Typestring Requiredyes DescriptionA string of 1 to 255 characters from the set [A-Za-z0-9_.:-]. It is scoped to the calling key, so two different clients may send the same string. A key from a SUCCESSFUL attempt does not expire — it remains valid for as long as the application exists. A key from a FAILED attempt (the failure happened while the key was being issued, usually after Bitrix24 was already contacted) is replayed for 20 minutes and then forgotten. See Idempotency for details

Request fields (body)

Field Type Required Description
Fieldname Typestring Requiredyes DescriptionApplication name, 2 to 100 characters. Control characters are not allowed. Leading and trailing whitespace is removed before the length is measured, so a request with a one-character name returns 400 even if the name is surrounded by spaces
Fieldtype Typestring Requiredyes DescriptionApplication type. The only supported value is personal. The schema accepts external, but the endpoint returns 400 APP_TYPE_NOT_AVAILABLE
Fieldb24Scopes Typearray Requiredno DescriptionBitrix24 scopes for the key being issued. Omit it and the key gets every scope this account can grant, with B24_SCOPES_DEFAULTED_TO_ALL in warningCodes. A minted key cannot be narrowed afterwards, so send an explicit list when you do not need the full set. An empty array is refused: it would mean a key with no account scopes. Take the values from the scopePresets set in the creation parameters
Fieldmode Typestring Requiredno DescriptionKey access mode: READONLY or READWRITE. If omitted, the key is issued in the narrowest of the account's default mode, the calling key's mode and, if the key belongs to a subscription, the Cowork/Code subscription mode; that value is returned in the mode field of the creation parameters. An explicit value wider than the subscription mode is issued in the subscription mode, and the actual mode is returned in data.mode of the response. If the account assigns read-only access to new keys, a request with READWRITE returns 403 — the account policy overrides the request. While the write block for read-only keys is in force (it is by default), a read-only calling key gets no new key, with or without this field: creation returns 403 WRITE_BLOCKED_READONLY_KEY before the remaining checks. Without the block it gets a read-only key, and an explicit READWRITE returns the same 403
FieldexpiresInDays Typenumber | null Requiredno DescriptionKey lifetime in days, as an integer of 1 or greater. If omitted or set to null, the key is issued with no expiry. The expiry policy from the creation parameters does not apply automatically; see "Known specifics"

The schema is strict: an extra field in the body returns 400 VALIDATION_ERROR, and the response names the field. The body size is limited to 64 KB.

Examples

The endpoint accepts only a Cowork/Code key, so only two examples are provided. Personal keys and OAuth application keys lack the vibe:cowork scope, so requests using them return 403 INSUFFICIENT_SCOPE.

curl — Cowork/Code key

Terminal
curl -X POST https://vibecode.bitrix24.com/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": "Deal report",
    "type": "personal",
    "b24Scopes": ["crm"]
  }'

JavaScript — Cowork/Code key

javascript
const res = await fetch('https://vibecode.bitrix24.com/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: 'Deal report',
    type: 'personal',
    b24Scopes: ['crm'],
  }),
})

if (!res.ok) {
  const { error } = await res.json()
  throw new Error(`${res.status} ${error.code}`)
}

const { data } = await res.json()

// The raw key is returned only once — save it immediately
if (data.rawApiKey === null) {
  // This is a retry: the application already exists, so the key is not issued again
} else {
  saveKey(data.rawApiKey, data.keyExpiresAt)
}

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata.application Typeobject | null DescriptionApplication card in the same shape returned by GET /v1/applications/:id. The fields populated immediately after creation are listed below. See the card page for the full list. null means the key has already been issued and attached to the application, but the card could not be read: the response is still 201 and contains the raw key (it is returned only once), and warningCodes includes APPLICATION_CARD_UNAVAILABLE. Read the card via GET /v1/applications/:id
Fielddata.application.id Typestring DescriptionApplication identifier
Fielddata.application.name Typestring DescriptionThe name you passed
Fielddata.application.type Typestring DescriptionPERSONAL for an application created by this endpoint
Fielddata.application.server Typeobject | null Descriptionnull in the initial response because a personal application has no server yet. On a retry, the field reflects the state AT THE MOMENT OF THE RETRY, so it contains a server object if the application has since been deployed
Fielddata.application.openUrl Typestring | null Descriptionnull in the initial response because there is nothing to open yet. On a retry, it contains the current application URL if one has already been issued
Fielddata.applicationId Typestring DescriptionRepeats application.id. Returned separately so you can link your local record to the card without parsing the card itself
Fielddata.rawApiKey Typestring | null DescriptionRaw application key. It is returned ONCE and cannot be recovered. The format is vibe_api_, followed by 32 Latin letters and digits, _, and 6 lowercase hexadecimal characters, for a total of 48 characters. null on a retry
Fielddata.keyExpiresAt Typestring | null DescriptionKey expiry, ISO 8601. null means the key has no expiry. On a retry, the field is ABSENT rather than empty
Fielddata.mode Typestring DescriptionAccess mode of the issued key — READONLY or READWRITE. On a retry the field is ABSENT
Fielddata.warnings Typearray DescriptionHuman-readable warning messages. Empty when there are none
Fielddata.warningCodes Typearray DescriptionWarning codes. Contains KEY_NOT_REPLAYABLE on a retry, B24_SCOPES_DEFAULTED_TO_ALL when b24Scopes was omitted and the key got every scope the account can grant, and APPLICATION_CARD_UNAVAILABLE when the key was issued and attached but the card could not be read (data.application is then null). Both warnings and warningCodes are always present, even when empty, so the response shape is the same in every case

Response example

JSON
{
  "success": true,
  "data": {
    "application": {
      "id": "cmt8ht5u40005ensk4fp45ebx",
      "name": "Deal report",
      "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": "Application author" },
      "isEmbedded": false,
      "openUrl": null,
      "openTarget": null,
      "server": null,
      "sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
      "activeOperation": null
    },
    "applicationId": "cmt8ht5u40005ensk4fp45ebx",
    "rawApiKey": "vibe_api_…",
    "keyExpiresAt": null,
    "mode": "READWRITE",
    "warnings": [],
    "warningCodes": []
  }
}

Error response example

409 — the key quota is exhausted:

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

Deleting the issued key in your Vibecode account does NOT cancel idempotency: the application remains, and a retry with the same idempotency key still returns 201 with the Idempotent-Replayed: true header and warningCodes: ["KEY_NOT_REPLAYABLE"]. That retry does not issue a new key — the raw key is returned exactly once, during initial creation. To get a working key for an existing application, use POST /v1/keys/:id/rotate.

A failure that happened after Bitrix24 was contacted is replayed the same way — see Retry after a failure.

Errors

The endpoint-specific error list is exhaustive: the endpoint does not return codes that are not listed here. Key issuance goes through Bitrix24 Network, whose errors are propagated verbatim and are also included in the table. For a self-hosted Bitrix24 portal, key issuance uses a separate channel and can return its own codes, covered in Keys and authorization. The response shape is the same; branch on error.code.

HTTP Code Description
HTTP400 CodeIDEMPOTENCY_KEY_REQUIRED DescriptionThe Idempotency-Key header is missing
HTTP400 CodeINVALID_IDEMPOTENCY_KEY DescriptionThe header is present but does not meet the length or character-set requirements
HTTP400 CodeVALIDATION_ERROR DescriptionThe request body fails validation because of the length of name, control characters in name, an unknown mode value, expiresInDays below one, an empty b24Scopes, or an extra field. The message names the field
HTTP400 CodeAPP_TYPE_NOT_AVAILABLE DescriptionThe request contains type: "external", which is unavailable in this version
HTTP400 CodeINVALID_SCOPES Descriptionb24Scopes contains a scope that is not in the Bitrix24 catalog. The message lists the rejected values
HTTP400 CodePORTAL_NOT_LINKED DescriptionThe Bitrix24 account is not connected to Bitrix24 Network, so no channel is available for issuing the key
HTTP400 CodePERSONAL_KEY_WEBHOOK_SCOPES_INVALID DescriptionNone of the scopes left in b24Scopes can be bound to the account. Returned when ONLY the placement, entity, or userfieldtype scopes are provided, because a personal key does not support them. Add at least one data-access scope, such as crm
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeINVALID_API_KEY DescriptionThe key is not recognized — no such key exists on the platform
HTTP401 CodeKEY_INACTIVE DescriptionThe key is disabled
HTTP401 CodeKEY_EXPIRED DescriptionThe calling key has expired
HTTP402 CodeACCOUNT_FROZEN DescriptionThe account balance is exhausted — top it up
HTTP402 CodeINT_TARIFF_REQUIRED DescriptionThe portal is on a free Bitrix24 plan — creating an application requires a commercial plan, and a trial plan grants limited access. For accounts where access is restricted to Vibe+ plans, key issuance requires a Vibe+ plan, and an account on an ordinary commercial plan receives INT_VIBE_PLUS_REQUIRED. The response body includes the upgrade URL. Retrying without changing the account state returns the same response
HTTP403 CodeINSUFFICIENT_SCOPE DescriptionThe key lacks the vibe:cowork scope
HTTP403 CodeSCOPE_NOT_AVAILABLE_ON_PORTAL Descriptionb24Scopes contains a scope for a module the account does not have. The message lists those scopes. The neighbouring key-issuing endpoints return the same error
HTTP403 CodeCOWORK_HARNESS_KEY_FORBIDDEN DescriptionThe call was made with a third-party agent key issued for the subscription. Such a key cannot create applications — see Your own agent on the subscription
HTTP403 CodeCOWORK_NOT_ACTIVATED DescriptionNo active Cowork/Code subscription for the user and portal
HTTP403 CodeWRITE_BLOCKED_READONLY_KEY DescriptionThe calling Cowork/Code key was issued in read-only mode, but creating an application is a write operation. This error is returned before the remaining checks
HTTP403 CodeAPP_CREATION_RESTRICTED DescriptionThe account policy restricts who can create applications, and the key owner is not allowed to do so. See Rights to create keys and apps
HTTP403 CodeKEY_POLICY_READONLY_REQUIRED DescriptionThe account assigns read-only access to new keys, but the request body contains mode: "READWRITE". The refusal is unconditional because this key has no administrative override
HTTP409 CodeKEY_LIMIT_REACHED DescriptionThe key quota is exhausted. error.details contains used, limit, and requested; without scope, this is the per-user account limit, while scope: "portal" means the platform's per-account key cap
HTTP409 CodeIDEMPOTENCY_KEY_BODY_MISMATCH DescriptionThe same Idempotency-Key was used with a different request body
HTTP409 CodeIDEMPOTENCY_KEY_ALREADY_USED DescriptionThe idempotency key has been consumed PERMANENTLY: it belongs to an application that has since been deleted. A failed attempt that reached Bitrix24 no longer returns this code — see Retry after a failure
HTTP409 CodeIDEMPOTENCY_CONCURRENT_RETRY DescriptionA concurrent request with the same idempotency key is still running. This is the only idempotency error for which a retry makes sense. The idempotency key is claimed BEFORE the application key is issued, so this error is returned before any key exists: no second application or key is created, no matter how many requests are sent concurrently
HTTP415 CodeFST_ERR_CTP_INVALID_MEDIA_TYPE DescriptionThe request uses a content type that this route does not parse. Send Content-Type: application/json
HTTP429 CodeRATE_LIMITED DescriptionThe rate limit for the combination of Bitrix24 account and key owner has been exceeded. The platform-wide limit is 6 requests per minute. The limit currently in force for your key is returned in the x-ratelimit-limit header.
HTTP429 CodeQUOTA_EXCEEDED DescriptionThe daily free-call quota is exhausted while the prepaid balance is zero
HTTP413 CodePAYLOAD_TOO_LARGE DescriptionThe request body is larger than 64 KiB. For example, an unusually long b24Scopes can reach this size. The limit is checked before the body is parsed, so neither the claim nor the key is created
HTTP500 CodeAPPLICATION_CREATE_FAILED DescriptionAn internal write or the key-issuing step failed, and the response cannot tell which. Three outcomes are possible: (a) the key was issued but the application card could not be written (an extra key appears in the API Keys section of your Vibecode account — revoke it); (b) the key-issuing step itself threw, for example on a database timeout — usually no key exists; (c) the reservation insert itself failed and nothing was created at all. In (a) and (b) the outcome is recorded: a retry with the SAME idempotency key within 20 minutes gets this same response (Idempotent-Replayed: true), so a replayed 500 does not prove an extra key exists. In (c) the reservation was never claimed, and a retry runs as a brand-new attempt right away, with no such header. See Retry after a failure
HTTP502 CodeBITRIX_UNAVAILABLE DescriptionBitrix24 Network rejected the call or was unavailable while the key was being issued — this is a failure AFTER Bitrix24 was already contacted, so the creation may have gone through on Bitrix24's side. A retry with the SAME idempotency key within 20 minutes gets this same response (Idempotent-Replayed: true) — see Retry after a failure. For a retry made PAST the 20-minute window, note that changing the idempotency key value does not protect against a duplicate — a retry with the old key and a retry with a new one both start a brand-new attempt. There is usually nothing on the platform to check either: the failed reservation is removed together with its outcome, and no key is minted for a failure at this stage — if the first attempt did reach Bitrix24, look for a duplicate on the Bitrix24 account itself. Treat the risk as inherent to retrying past the window and limit the number of retries. This code also covers a terminal case: the key owner's authorization in Bitrix24 Network has expired, and only the owner can resolve it by signing in to Bitrix24 Network again. The response does not distinguish the two cases and provides no separate field — instead of retrying to diagnose it, tell the user right away that the key owner must sign in to Bitrix24 Network again
HTTP503 CodeCOWORK_FEATURE_DISABLED DescriptionCowork/Code is disabled at the platform level
HTTP503 CodeAPP_CREATE_DISABLED DescriptionCreating applications from Cowork/Code is disabled. The available field of the creation parameters reports this in advance

See Errors for the full list of common API errors.

Idempotency

Unlike creating a server, this endpoint requires the Idempotency-Key header. It issues a key and consumes a quota slot, so without idempotency, retrying after a network interruption could create a second application and a second key.

A retry with the same key and request body returns 201, adds the Idempotent-Replayed: true response header, and returns the same card. The raw key is then null, and KEY_NOT_REPLAYABLE appears in warningCodes: the platform stores only the key hash, so the raw key cannot be recovered.

A lost key is not returned on a retry, and this Cowork/Code key cannot reissue it — the response contains no identifier for the issued key, and the /v1/keys section accepts only a management key. The only practical option is to create the application again with a NEW Idempotency-Key value, obtain a fresh key, and then remove the extra card and its key from your Vibecode account. Save rawApiKey immediately in the same response handler.

The fingerprint is calculated from a canonicalized request body. The order of fields and the order of values in b24Scopes do not affect the comparison, so reordering either still counts as the same request. Leading and trailing whitespace in name also has no effect, and expiresInDays: null is equivalent to omitting the field. Using the same key with a different body returns 409 IDEMPOTENCY_KEY_BODY_MISMATCH instead of a result for a different request.

Repeat the same request body without modifying it. Omitting an optional field and explicitly providing the value that the account would supply produce DIFFERENT fingerprints. For example, if the first request omitted mode and the retry includes it, the response is 409 IDEMPOTENCY_KEY_BODY_MISMATCH. For the same reason, ["crm"] and ["crm", "crm"] differ: the scopes are sorted before comparison, but duplicates are not removed.

Retry after a failure

If the first attempt failed AFTER Bitrix24 was already contacted (the connector was unreachable, the Bitrix24 account refused, an internal write failed), the platform stores that outcome and, for 20 minutes, returns it verbatim on a retry with the same Idempotency-Key: the same HTTP status, the same error.code, the same body, plus the Idempotent-Replayed: true header. Aside from that header, the platform's response is indistinguishable from the first failure — use the header to tell a replay from the first attempt.

After 20 minutes the outcome is forgotten: the platform physically frees the idempotency key, and a retry with it runs as a brand-new attempt — every check runs again, including a chance to succeed. The retry body must still match the first attempt's body, or, as always, 409 IDEMPOTENCY_KEY_BODY_MISMATCH is returned; the exception is when the outcome is already forgotten (20 minutes have passed) — then the body is not compared against the forgotten failure at all, and a retry with ANY body starts a new attempt.

If the first failure happened AFTER Bitrix24 was already contacted (for example 502 BITRIX_UNAVAILABLE), the account may already have received a webhook from the first attempt — a retry past the 20-minute window does not check for that and can mint a SECOND key on top of the first. Changing the Idempotency-Key value does not protect against that here — the same key and a new one both run as a new attempt past the window. Usually there is nothing on the platform to check either: a failed reservation is removed together with its outcome, and at most failure stages no key is minted at all — so look for a possible duplicate on the Bitrix24 account itself, if you can, and treat the risk as part of the cost of retrying past the window. The exception is 500 APPLICATION_CREATE_FAILED: there the key is sometimes ALREADY issued (see the error table above), and then you can find and revoke the extra key in the API Keys section of your Vibecode account.

A refusal by one of the checks that run BEFORE the idempotency key is claimed (body validation failed, the key quota is exhausted, the account is not linked to Bitrix24 Network, the platform's Bitrix24 plan check did not pass) is not covered by this guarantee: the key is not kept in that case, and a retry with it is indistinguishable from the first request as far as the platform is concerned. Most plan-related refusals arrive before the key is claimed and are not replayed, but a refusal that the Bitrix24 account returned while the key was being issued is stored and replayed for 20 minutes. The response body does not tell them apart, so rely on the Idempotent-Replayed header: absent means the answer is fresh.

Known specifics

The default key lifetime does not apply — the keyExpiresInDays field in the creation parameters is a hint, not a default. If expiresInDays is omitted, the key is issued with no expiry, and the response contains keyExpiresAt: null. To limit the lifetime, pass the number of days explicitly. You can present the value from the creation parameters as a suggestion to the user.

The placement, entity, and userfieldtype scopes are not included in the issued key. In a mixed set, they are dropped without an error because a personal key does not support them. An error is returned only when b24Scopes contains no other scopes. Check the scopes on the issued key rather than relying on the request you sent.

The issued key cannot call AI or web search. It carries vibe:infra, vibe:storage, and the requested Bitrix24 scopes, while vibe:ai and vibe:search are absent from both the scope string and the runtime scopes. An application created this way cannot spend the account wallet on AI models or web search.

The order of errors matters: first the calling key's permissions, then the product state, then the cost. The checks run in this order: the key's existence, expiry, read-only mode, and account balance freeze; the vibe:cowork scope and key class, whether Cowork/Code is enabled, whether the subscription is active, and whether the application creation wizard is enabled; idempotency and the request body schema; and finally the account's platform access, application creation policy, and key quota. When multiple conditions fail at once, the first error in this sequence is returned.

A 500 APPLICATION_CREATE_FAILED refusal does not show whether the key was issued. If the key was already issued but the card could not be created, the quota slot is taken — find and revoke the extra key. If the key-issuing step itself threw, there is usually no key, but the outcome is still stored. In both cases a retry with the same idempotency key within 20 minutes returns the stored failure, and the Idempotent-Replayed: true header alone does not prove an extra key exists — check your key list. If the reservation insert itself failed, neither the key nor the card exists — the reservation was never claimed, there is no stored outcome, and a retry runs as a brand-new attempt right away.

Some card fields are not populated by this endpoint — retrieve them from the application catalog. The field set matches GET /v1/applications/:id, but pinned is always false here, and sources and activeOperation are always empty, even if the application has been deployed and the user has pinned it in their Vibecode account. Read those fields from the application catalog; use the creation response for the identifier, name, and key.

The server is linked to the card automatically. After creating the application, create the server by calling POST /v1/infra/servers with the parameters from the server block of the creation parameters. No separate call is needed to link the server to the card.

See also