#Creating and using a key
A key is the credential for accessing the Vibe API. This page walks through creating a key in the dashboard step by step and covers every form field: name, scopes, expiration, request limit, and the allowed-IP list.
Which scopes to pick for your task is on a separate page — Scopes.
#Key types
| Type | Prefix | Purpose | Authorization |
|---|---|---|---|
| API key | vibe_api_ |
Access to portal data via the Vibe API | X-Api-Key header |
| Authorization key | vibe_app_ |
Embedding an app in the portal and Bitrix24 OAuth authorization | X-Api-Key + session token |
| Management key | vibe_live_ |
Platform administration | X-Api-Key header |
API key (vibe_api_). Created in the dashboard and bound to a single Bitrix24 portal. All requests run on behalf of the key owner; no session token is required. Suited for personal dashboards, scripts, server-side integrations, and bots on your own portal.
Authorization key (vibe_app_). Bound to a VibeCode app with Bitrix24 OAuth credentials. Each request is sent on behalf of the user who installed the app and completed authorization — so the Authorization: Bearer header is required. Suited for catalog apps that run on different portals under different users. The same key is needed for the app to open inside Bitrix24 — in the left menu, a CRM tab, or a widget (see Embedding an app in the portal).
Management key (vibe_live_). Not bound to a single portal; intended for administration: managing keys, viewing portals, working with feedback. It has no access to Bitrix24 entity data. Full description — Management keys.
Next — creating both portal keys: the API key (vibe_api_) and the authorization key (vibe_app_). The forms differ slightly; the difference is described below. The management key (vibe_live_) is covered separately — Management keys.
#Creating an API key
- Sign in to the dashboard.
- Open the API Keys section.
- Click Create.
- Fill in the form (steps below).
- Copy the key — it is shown once.
#Step 1. Name
An arbitrary name for yourself — the key is listed by it. It does not affect access. Create a separate key with a clear name for each service or integration — this makes revocation on compromise easier.
#Step 2. Scopes
Scopes are permissions for data access. In the form they are grouped into the "Bitrix24" and "VibeCode" tabs; you must select at least one.
The full list of scopes, a description of each, and picking a set for your task are on the Scopes page. Quick reference: crm — CRM data, tasks — tasks, imbot + im — chat bot, disk — files.
The four platform scopes (vibe:infra, vibe:ai, vibe:search, vibe:storage) are added to the key automatically — you do not need to select them.
The set of Bitrix24 scopes is locked to the key at issue time. If you add a Bitrix24 scope in the settings of an already-existing key, GET /v1/me will show it in the list, but requests that need it will return BITRIX_ACCESS_DENIED: the key accesses Bitrix24 data with the scope set it was issued with. To grant a key a new Bitrix24 scope:
- API key (
vibe_api_) — reissue the key or create a new one with the scope selected. - Authorization key (
vibe_app_) — recreate the app with the required scope and complete authorization again (reissuing the key does not grant a scope here).
A scope is granted at issue time only if it is available on the Bitrix24 portal. If, after reissuing or re-authorizing, a call still returns BITRIX_ACCESS_DENIED, then the scope is not provided for this key on the portal.
#Step 3. Expiration
When the key stops working. Options: no limit, 30, 90, 180, or 365 days. After expiration, requests with the key are rejected with code KEY_EXPIRED. For server-side integrations, set a finite expiration and refresh the key in advance.
#Step 4. Request limit
An optional per-key limit for this key. If the field is empty, the general platform and portal limits apply (the "Request limits" section below). The value in effect for the key is returned by GET /v1/me in the rateLimit.requestsPerSecond field.
#Step 5. Allowed-IP list
In the "Advanced settings" block. Restricts the key's calls to a list of IP addresses. Exact IPv4 and IPv6 addresses are supported, one per line; CIDR subnets are not supported.
192.168.1.100
203.0.113.42
2001:db8::1
A request from an address outside the list is rejected with code 403 IP_NOT_ALLOWED. If the list is empty, there is no IP restriction.
#Step 6. Save the key
The full key is shown once, right after creation. Copy it and store it in a safe place — you cannot retrieve it again, only reissue it.
#Creating an authorization key
The authorization key (vibe_app_) is created in the Authorization Keys section of the dashboard. The form is shorter than the API key's: just two fields.
- Open the Authorization Keys section and click Create.
- Name — the app is listed under it.
- Scopes — the same two groups, "Bitrix24" and "VibeCode", at least one; picking a set is described on the Scopes page.
- Copy the key — it is shown once.
Expiration, request limit, and the allowed-IP list are not set in this form — that is how it differs from the API key form. After creation, the authorization key works together with a session token: each request is sent with the X-Api-Key and Authorization: Bearer headers (the "Passing the key" section).
#Embedding an app in the portal
If the app must open inside Bitrix24 — as an item in the left menu, a tab in a CRM card, or a desktop widget — an authorization key (vibe_app_) is required. The API key (vibe_api_) does not support embedding in the portal interface: with it the app accesses data but is not placed inside the Bitrix24 window.
The authorization key provides two capabilities the API key does not:
- Placement in the interface. The app appears at the chosen spot on the portal — the placement binding
POST /v1/placements/bindis responsible for this. Available spots are returned byGET /v1/placements/available. - Transparent authorization. The user opens the app inside Bitrix24 without a separate sign-in: the Gateway determines who opened the app on its own and passes their data to the app server. The browser never sees the session token.
Procedure:
- Create an authorization key in the Authorization Keys section — the form is described above in the "Creating an authorization key" section.
- Pass the authorization key (
vibe_app_) specifically to the AI model and ask for an app with portal embedding. - The model calls
GET /v1/mewith this key and gets theplacementssection with the full embedding procedure.
The full lifecycle of an embedded app, the BFF pattern (Backend-for-Frontend), and handler skeletons in Node, Python, and Go — App authorization on BlackHole.
#Passing the key
The key is passed in the X-Api-Key header:
curl -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.tech/v1/deals
Clients that can only send Authorization: Bearer (for example, OpenAI-compatible ones) can pass the API key itself (vibe_api_…) in this header instead of X-Api-Key — for the key both headers are equivalent. This works on all V1 endpoints, including the bot platform:
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://vibecode.bitrix24.tech/v1/bots
For the authorization key (vibe_app_…) the Authorization: Bearer header is taken by the session token, so the key itself always goes in X-Api-Key (see below).
For the authorization key (vibe_app_) a session token is additionally passed in the Authorization: Bearer header:
curl -H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
https://vibecode.bitrix24.tech/v1/deals
If Authorization: Bearer is not passed for a vibe_app_ key, endpoints that need user context return 401 TOKEN_MISSING: the request has no data on whose behalf to access Bitrix24. The /v1/me and /v1/oauth/* endpoints work without Bearer.
The session token lives 24 hours and is not refreshed. POST /v1/oauth/token (and GET /v1/oauth/poll) issue an access_token with expires_in: 86400 — without a refresh_token and without a refresh grant. There is no "silent" renewal mechanism — this is a deliberate decision. After 24 hours expire, get a new session token by going through the OAuth flow again: GET /v1/oauth/authorize → POST /v1/oauth/token. Before expiration, calls on behalf of the user return 401 TOKEN_EXPIRED — that is the signal to re-authorize.
For background scenarios — cron, server-side integrations, scripts with no user at the screen to re-authorize every 24 hours — use a personal API key (vibe_api_…): it works on behalf of the key owner without a session token, and the only time limit is the key's own "expiration" (see above). The authorization key (vibe_app_…) is intended for apps where a user is present and goes through OAuth.
The /v1/me self-description responds in two modes:
| Headers | currentUser in response |
When applicable |
|---|---|---|
X-Api-Key only |
null |
Server-to-server requests and app bootstrap before OAuth. The portal, tariff, trial, capabilities, scopes, api fields and the list of available endpoints are the same. |
X-Api-Key + Authorization: Bearer vibe_session_* |
{ bitrixUserId, _note } object |
A request on behalf of a specific user — after a Gateway redirect or a manual OAuth flow. All other fields are the same as without Bearer. |
The top level of the response is identical in both modes — only the population of the currentUser field differs. The capabilities.servers.create.available field also depends on the mode: for a vibe_app_ key without a session it returns false with reason SESSION_REQUIRED, because infrastructure POST endpoints require user context.
Infrastructure-creation endpoints (POST /v1/infra/servers, as well as POST /api/agents and POST /api/managed-bots via the dashboard) require the platform to know exactly who is creating the server — this is needed for the tariff check and quota accounting. For vibe_app_ keys this means the presence of Authorization: Bearer <session>; without a session the response is 401 UNAUTHENTICATED with error.hint indicating a working option (go through the OAuth flow or use a personal vibe_api_ key). Reads (GET /v1/infra/servers, GET /v1/me) do not need a session.
#Key lifecycle
Create → Active → Reissue / Revoke / Delete
#Key states
| State | Value in API | Description |
|---|---|---|
| Active | ACTIVE |
Key is ready to use |
| Expired | EXPIRED |
The key's expiration has passed |
| Revoked | REVOKED |
Key is deactivated, requests are rejected |
#Reissue
Reissue creates a new key and leaves the old one a 24-hour transition period — this lets you update the key in apps without downtime:
- Start the reissue in the dashboard.
- Get the new key.
- Update the key in your apps.
- The old key keeps working for another 24 hours.
- When the transition period expires, the old key becomes invalid.
#Revoke and delete
Revoke moves the key to the REVOKED state: subsequent requests are rejected with 401 KEY_INACTIVE. If the key has active servers, deletion returns 409 KEY_HAS_ACTIVE_SERVERS — delete the servers first.
#If a key is compromised
- Revoke the key in the dashboard.
- Create a new key with the same scopes.
- Update the key in all apps.
- Check the request log for requests from unknown addresses.
- Enable the allowed-IP list.
#Security recommendations
- Store keys in environment variables or a secret manager, not in code and not in git.
- Do not pass keys via messengers or email.
- Assign a key only the scopes it needs — picking a set is described on the Scopes page.
- Create a separate key for each service and revoke unused ones.
- For server-side integrations, enable the allowed-IP list and a finite expiration.
- Reissue keys on a schedule (for example, once every 90 days).
#Technical details
Below are details for AI models and advanced integrations.
#Key self-description (`/v1/me`)
GET /v1/me returns the key type, portal, scopes, limits, and a map of available endpoints. This is the main entry point for AI models: it is enough to pass the model the key and the link https://vibecode.bitrix24.tech/v1/me.
curl -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.tech/v1/me
Response for an API key (vibe_api_), characteristic fields shown:
{
"success": true,
"data": {
"type": "personal",
"portal": "mycompany.bitrix24.ru",
"scopes": ["crm", "tasks", "user", "vibe:infra", "vibe:ai", "vibe:search", "vibe:storage"],
"rateLimit": { "requestsPerSecond": 10 },
"auth": {
"personalKey": "X-Api-Key: vibe_api_… (no Bearer)",
"oauthKey": "X-Api-Key: vibe_app_… + Authorization: Bearer <session_token>"
},
"owner": { "name": "Ivan Petrov", "userId": "1" },
"expiresAt": null
}
}
Besides the fields shown, the response contains the api (map of available endpoints and entities), capabilities, tariff, and errorCodes sections — the model uses them to build requests without reading the rest of the documentation.
Response for an authorization key (vibe_app_):
{
"success": true,
"data": {
"type": "oauth_app",
"portal": "mycompany.bitrix24.ru",
"scopes": ["crm", "tasks"],
"app": { "title": "CRM Dashboard", "id": "f2342f7a-…" },
"oauth": {
"authorizeUrl": "https://vibecode.bitrix24.tech/v1/oauth/authorize?app_key=vibe_app_…",
"authorizeUrlNote": "Template URL — append required query params before redirecting the user…",
"requiredParams": { "state": { "required": true, "minLength": 16, "maxLength": 512 }, "redirect_uri": { "required": false }, "scope": { "required": false } },
"tokenUrl": "https://vibecode.bitrix24.tech/v1/oauth/token",
"revokeUrl": "https://vibecode.bitrix24.tech/v1/oauth/revoke"
},
"auth": {
"header": "X-Api-Key: <this-key> + Authorization: Bearer <session-token>",
"steps": [
"1. Redirect user to oauth.authorizeUrl + state (+ redirect_uri)",
"2. Exchange code for session token",
"3. Call API with both headers"
],
"gatewayInjected": {
"description": "For an app embedded in Bitrix24 via a placement and running behind BlackHole, the Gateway authenticates the user itself and injects the header on every request. The browser never sees the token.",
"header": "X-Vibe-Authorization: Bearer vibe_session_*",
"docs": "https://vibecode.bitrix24.tech/docs/infra/app-runtime"
}
}
}
}
⚠
oauth.authorizeUrlis a template, not a ready-made link. The/v1/oauth/authorizeendpoint requires the mandatorystateparameter (16–512 characters) — a CSRF token per RFC 6749 §10.12 that the client generates: create a cryptographically random string, add it to the URL, and verify the value returned in the callback. The server cannot generatestatefor you — otherwise CSRF protection does not work. OpeningauthorizeUrlas is returns400 INVALID_REQUEST "state: Required". Optionally addredirect_uri(your callback; without it the built-in/oauth/completepage is used) andscope. Full-link example:https://vibecode.bitrix24.tech/v1/oauth/authorize?app_key=vibe_app_…&state=aAbBcCdDeEfFgGhH&redirect_uri=https://myapp.com/callback
The response structure for a management key differs — it is described on the Management keys page.
#Full key passing
The key can be passed via Authorization: Bearer <vibe_*> without the X-Api-Key header — this option is supported for OpenAI-compatible clients. When calling through an OAuth app, the session token cannot be passed in this case, so the method applies only to vibe_api_ and vibe_live_ keys.
For an app embedded in Bitrix24 as a placement and running behind BlackHole, the session token arrives neither in the address nor in the body — the Gateway authenticates the user itself and injects the X-Vibe-Authorization: Bearer vibe_session_* header on every request to the app server. The browser neither sees nor stores the token (sessionStorage stays empty). The app reads the user identifier with a single GET /v1/me call, passing Authorization: Bearer from the X-Vibe-Authorization header: the response contains currentUser.bitrixUserId (the numeric Bitrix24 user ID) and portal (the portal domain at the top level). The full request lifecycle, the BFF pattern (Backend-for-Frontend), and handler skeletons in Node/Python/Go — App authorization on BlackHole.
#Request limits
Two independent limit systems apply to each key at the same time: the VibeCode platform limit and the Bitrix24 portal limit.
#VibeCode platform limit
| Parameter | Value |
|---|---|
| Request limit | 300 requests per minute per source |
| Limit window | Sliding 60-second window |
| Limit header | X-RateLimit-Limit |
| Remaining header | X-RateLimit-Remaining |
| Reset header | X-RateLimit-Reset (seconds until the window resets) |
On exceeding the limit, 429 Too Many Requests is returned with code RATE_LIMITED.
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 245
X-RateLimit-Reset: 25
#Bitrix24 portal limit
The portal rate-limits requests (by default about 10 requests per second, the limit is shared among all of the portal's keys). On exceeding it, 502 BITRIX_UNAVAILABLE is returned. The value in effect for the key is returned by GET /v1/me in the rateLimit.requestsPerSecond field.
A single call counts as one unit. One POST /v1/batch with 50 operations spends one unit — this is the most economical way to stay within the limit.
#Recommendations under limits
- Combine requests via
POST /v1/batch(up to 50 operations per call). - Cache data that changes rarely.
- On
429, retry the request with an increasing pause (1 s → 2 s → 4 s). - Rely on the
X-RateLimit-*headers so you do not hit rejection.
#Key error codes
| HTTP | Code | When returned |
|---|---|---|
| 401 | KEY_INACTIVE |
Key is in the REVOKED or EXPIRED state |
| 401 | KEY_EXPIRED |
The key has an expiration set and it has passed |
| 401 | INVALID_API_KEY |
Key not found |
| 401 | TOKEN_MISSING |
Authorization: Bearer not passed for a vibe_app_ key |
| 403 | IP_NOT_ALLOWED |
Request from an address outside the allowed-IP list |
| 403 | WRITE_BLOCKED_READONLY_KEY |
The key has read-only mode set, and the call performs a write — Access mode |
Full code reference — Error codes.
#Access mode
Every key has a separate accessMode field — it controls whether the key allows writes or restricts it to read operations. This is a setting independent of scopes: scopes determine which data sections the key has access to, and the access mode determines whether the key can change that data.
#Two modes
| Mode | Value in API | What is allowed |
|---|---|---|
| Read and write | READWRITE |
All operations — read and write. The default value for new keys. |
| Read-only | READONLY |
Reads are allowed. Any write attempt returns 403 WRITE_BLOCKED_READONLY_KEY. |
Which calls fall under the block in READONLY mode:
- API keys and authorization keys (
vibe_api_,vibe_app_) — any request proxied to Bitrix24 as a write operation is blocked: create, update, delete, actions on entities.GETrequests and aggregation operations (POST /v1/<entity>/aggregate) run without restrictions. - Management keys (
vibe_live_) — blocking is by HTTP method:POST,PATCH,PUT,DELETEare rejected,GETandHEADpass. This means a management key in read-only mode cannot create new keys, change a portal, or submit feedback, but it can read settings and the event log.
The GET /v1/me endpoint returns the key's effective mode in the data.accessMode field:
{
"success": true,
"data": {
"type": "personal",
"portal": "mycompany.bitrix24.ru",
"accessMode": "READONLY",
"scopes": ["crm", "tasks"]
}
}
#Changing the mode
The key owner changes the mode in the dashboard in the API Keys section:
- Open the card of the key you need.
- In the Access mode block, select "Read-only" or "Read and write".
- Save the changes — the mode applies to the next request.
No reissue is needed — the mode changes on a live key without replacing its value. When creating a new key, the mode is set with a separate toggle in the form.
A portal administrator sees other users' keys in the shared list and can change the mode of any key on the portal. After saving, the owner receives a message from the Companion bot informing them that the mode of their key was changed by an administrator.
#Default portal policy
The administrator sets the mode that applies to all new keys on the portal. The setting lives in the API Keys section, in the "Default portal policy" block, and is visible only to administrators.
Possible values:
- Read and write (
READWRITE) — the default value for the portal. Any user creates keys with any mode at their discretion. - Read-only (
READONLY) — ordinary portal members can create only read-only keys. An attempt to issue a key withREADWRITEmode is rejected with code403 KEY_POLICY_READONLY_REQUIRED. The portal administrator is not subject to this restriction and, when needed, creates write keys or changes the mode of another user's key in its card.
The portal policy does not affect existing keys — it applies only at the moment a new key is created. For already-issued keys, the administrator changes the mode manually in the key's card.
#Write-block response example
POST /v1/leads with a key in READONLY mode returns 403:
{
"success": false,
"error": {
"code": "WRITE_BLOCKED_READONLY_KEY",
"message": "Key is in read-only mode. Switch to read+write in /keys to enable writes.",
"details": {
"method": "crm.item.add",
"keyName": "MCP key",
"currentMode": "READONLY",
"switchUrl": "/keys"
}
}
}
The details.method field is present only in the response to a block when proxying to Bitrix24 — it contains the name of the method that would have been called on a successful write. For management keys, details.method is not returned: only the request's HTTP method takes part in the block.
A detailed description of the error code, the reasons it triggers, and the steps to unblock — `WRITE_BLOCKED_READONLY_KEY`.