For AI agents: markdown of this page — /docs-content-en/apps/create.md documentation index — /llms.txt
Create an application
POST /v1/apps
Registers an OAuth application on the Bitrix24 account and creates a paired API key. The body is passed flat, without a wrapper.
Request fields (body)
| Field | Type | Req. | Description |
|---|---|---|---|
title |
string | yes | Application name, from 1 to 255 characters |
scopes |
array | yes | Set of application scopes — access to Bitrix24 account data, at least one. For future publishing the set needs placement. There is no need to list the platform vibe:* scopes, the platform grants them itself. List — Scopes |
description |
string | no | Application description, up to 2000 characters |
appUrl |
string | no | Application URL, only http:// or https://. An empty string is saved as null |
redirectUris |
array | no | OAuth redirect URLs. Defaults to the authorization completion URL and http://localhost |
mode |
string | no | Access mode of the paired key: READONLY or READWRITE. Defaults to the Bitrix24 account policy |
handlerUrl is set by the platform — it is not accepted in the body. OAuth callbacks and opening a placement go through it. The difference between appUrl and handlerUrl — in the Applications section.
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/apps \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Sales dashboard",
"scopes": ["crm", "user", "placement"],
"appUrl": "https://app-abc12345.vibecode.bitrix24.com"
}'
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/apps \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Sales dashboard",
"scopes": ["crm", "user", "placement"],
"appUrl": "https://app-abc12345.vibecode.bitrix24.com"
}'
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/apps', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Sales dashboard',
scopes: ['crm', 'user', 'placement'],
appUrl: 'https://app-abc12345.vibecode.bitrix24.com',
}),
})
const { data } = await res.json()
// Save data.rawKey immediately — it is returned only once
console.log('App ID:', data.id)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/apps', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Sales dashboard',
scopes: ['crm', 'user', 'placement'],
appUrl: 'https://app-abc12345.vibecode.bitrix24.com',
}),
})
const { data } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
data.id |
string | Application identifier |
data.title |
string | Name |
data.description |
string | null | Description |
data.scopes |
array | Set of application scopes — exactly what you passed in the body. The paired key's scopes are wider, see "Known specifics" |
data.handlerUrl |
string | Handler URL, set by the platform |
data.appUrl |
string | null | Application URL |
data.redirectUris |
array | OAuth redirect URLs |
data.bitrixClientId |
string | null | OAuth client identifier in the Bitrix24 account |
data.authorId |
string | Author identifier |
data.portalId |
string | Bitrix24 portal identifier |
data.createdAt |
string | Creation date, ISO 8601 |
data.updatedAt |
string | Modification date, ISO 8601 |
data.placements |
array | Placements, empty before publishing |
data.catalogStatus |
string | Catalog status. For a new application — always PRIVATE |
data.publishedAt |
string | null | Publication date, ISO 8601. For a new application — null |
data.rawKey |
string | Ready-to-use authorization key vibe_app_…. The only vibe_app_… value in this response — use exactly this as X-Api-Key. Returned only in this response and never shown again |
Response example
rawKey is shown with a truncated secret — this is not a working value.
{
"success": true,
"data": {
"id": "33c4d5e6-f7a8-49b0-1234-5c6d7e8f9012",
"title": "Sales dashboard",
"description": null,
"scopes": ["crm", "user", "placement"],
"handlerUrl": "https://vibecode.bitrix24.com/v1/bitrix-handler",
"appUrl": "https://app-abc12345.vibecode.bitrix24.com",
"redirectUris": [
"https://vibecode.bitrix24.com/oauth/complete",
"http://localhost"
],
"bitrixClientId": "local.7c3d4e5f6a7b80.55556666",
"authorId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"portalId": "8b1f0e2a-3c4d-5e6f-7a8b-9c0d1e2f3a4b",
"createdAt": "2026-06-24T09:12:45.781Z",
"updatedAt": "2026-06-24T09:12:45.781Z",
"placements": [],
"catalogStatus": "PRIVATE",
"publishedAt": null,
"rawKey": "vibe_app_local_7c3d4e5f6a7b80_55556666_…_6666"
}
}
Error response example
400 — validation failed:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "title: Required"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR |
Body validation failed: title missing, empty scopes, invalid appUrl |
| 403 | APP_CREATION_RESTRICTED |
Application creation on the portal is restricted to a list, and the author is not on it |
| 403 | KEY_POLICY_READONLY_REQUIRED |
The portal policy allows only READONLY, but READWRITE was requested |
| 403 | WRITE_BLOCKED_READONLY_KEY |
The request comes from a key in read-only mode while the paired key is being created in READWRITE mode. Such a key can only issue an application with mode: "READONLY". More — Access mode |
| 409 | KEY_LIMIT_REACHED |
The per-user key limit for the portal has been reached |
| 409 | CONNECTOR_MODULE_NOT_INSTALLED |
The Vibecode Connector module is not installed on the portal — an authorization key cannot be issued. Retrying without installing the module will not help |
The full list of general API errors — Errors.
Known specifics
- The authorization key is returned only once. The
rawKeyfield is present in the creation response and nowhere else — neither in application data nor in the list. If you did not save it at creation — recreate the application. - A pair is created: an application and an API key. Registration creates an application record and a paired authorization key in one step. This affects deletion: the key frees a slot in the per-user limit only after deleting the application.
- Application scopes and paired-key scopes are different sets. In
scopesyou declare access to Bitrix24 account data —crm,user,placement. The paired key receives that set plus four platform scopes:vibe:infra— servers and agents,vibe:ai— model calls,vibe:search— web search and research,vibe:storage— object storage. That is why a fresh authorization key creates servers throughPOST /v1/infra/serversright away, even thoughvibe:infrawas never in the create body. Thedata.scopesfield of the response shows the application declaration, not the key's effective set — read the effective set fromdata.scopesofGET /v1/mecalled with that key.