For AI agents: markdown of this page — /docs-content-en/infra/access-tokens.md documentation index — /llms.txt
Access tokens
Short-lived tokens for external access to a deployed application on a BLACKHOLE server. Two modes: api-bearer — JWT for the Authorization HTTP header, share-url — a distributable link with cookie authentication.
Scope: vibe:infra
Mint an access token
POST /v1/infra/servers/:id/access-tokens
Mints a short-lived token for external access to a deployed application. Two modes: api-bearer — JWT for the Authorization HTTP header; share-url — a link that sets a cookie when visited.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string (UUID) | yes | BLACKHOLE server ID |
Request body fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
mode |
string | yes | — | "api-bearer" or "share-url" |
ttlSeconds |
number | no | 86400 |
Token lifetime in seconds. Range: 300–315 360 000 (from 5 minutes to 10 years). The value 315 360 000 is shown in the interface as "Never expires" |
identityBound |
boolean | no | true |
For share-url only. When true — login via Bitrix24 is required, and the real user identifier ends up in the log. When false — anonymous visit, a synthetic identifier |
name |
string | no | — | Token label for display in the list (up to 100 characters) |
Examples
curl — personal key
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/access-tokens" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "api-bearer",
"ttlSeconds": 600,
"name": "ci-smoke"
}'
curl — OAuth application
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/access-tokens" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "share-url",
"ttlSeconds": 2592000,
"identityBound": false,
"name": "preview"
}'
JavaScript — personal key
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/access-tokens`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ mode: 'api-bearer', ttlSeconds: 600 }),
}
)
const { data } = await res.json()
// E2E check via the public path
const check = await fetch(`${data.appUrl}/api/health`, {
headers: { Authorization: `Bearer ${data.token}` },
})
console.log(check.status) // 200 — the application responds through the Gateway
JavaScript — OAuth application
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/access-tokens`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
mode: 'share-url',
ttlSeconds: 2592000,
name: 'preview',
}),
}
)
const { data } = await res.json()
console.log(data.url) // https://app-xxxx.vibecode.bitrix24.com/?s=R8k3Zm2P
Response fields
The set of fields depends on the mode.
Mode api-bearer:
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data.id |
string | Token ID for later revocation |
data.mode |
string | "api-bearer" |
data.token |
string | JWT for the Authorization: Bearer header. Returned once — at mint time |
data.expiresAt |
string (ISO 8601) | Retention period of the token record — for listing and revocation |
data.jwtExpiresAt |
string (ISO 8601) | The real validity period of the Bearer token. Capped at 10 minutes regardless of ttlSeconds. After it expires, mint a new token |
data.note |
string | Note about the difference between expiresAt and jwtExpiresAt |
data.subdomain |
string | Server subdomain |
data.appUrl |
string | Full HTTPS address of the application |
data.curlExample |
string | Ready-to-use curl example with the token for a quick check |
Mode share-url:
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data.id |
string | Token ID for later revocation |
data.mode |
string | "share-url" |
data.shortcode |
string | Code inserted into the URL as ?s=<shortcode> |
data.url |
string | Full distributable link |
data.identityBound |
boolean | Whether a visit requires login via Bitrix24 |
data.expiresAt |
string (ISO 8601) | Token expiration moment |
data.name |
string | null | The label passed at mint time |
Response example
Mode api-bearer:
{
"success": true,
"data": {
"id": "tk_7d3fa2b1",
"mode": "api-bearer",
"token": "eyJhbGciOiJFUzI1NiJ9...",
"expiresAt": "2026-05-18T10:50:00.000Z",
"jwtExpiresAt": "2026-05-18T10:40:10.000Z",
"subdomain": "app-91306a4c",
"appUrl": "https://app-91306a4c.vibecode.bitrix24.com",
"curlExample": "curl -H \"Authorization: Bearer eyJhbGciOiJFUzI1NiJ9...\" https://app-91306a4c.vibecode.bitrix24.com/api/health",
"note": "JWT is a 10-minute Gateway session token. Bearer stops working at jwtExpiresAt. POST .../:tokenId/refresh to renew the same token, or POST /access-tokens for a new one."
}
}
Mode share-url:
{
"success": true,
"data": {
"id": "tk_8e4gb3c2",
"mode": "share-url",
"shortcode": "R8k3Zm2P",
"url": "https://app-91306a4c.vibecode.bitrix24.com/?s=R8k3Zm2P",
"identityBound": false,
"expiresAt": "2026-06-17T08:44:00.000Z",
"name": "preview"
}
}
Error response example
429 — token mint rate limit exceeded:
{
"success": false,
"error": {
"code": "TOKEN_MINT_RATE_LIMIT",
"message": "Rate limit: 50 mints/hour per API key"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_MODE |
An invalid mode was passed |
| 400 | INVALID_TTL |
ttlSeconds is outside the allowed range [300, 315 360 000] |
| 400 | NAME_TOO_LONG |
name exceeds 100 characters |
| 401 | MISSING_API_KEY |
The X-Api-Key header was not provided |
| 401 | INVALID_API_KEY |
Invalid or expired API key |
| 403 | TOKEN_OWNER_MISMATCH |
The server belongs to a different API key |
| 404 | SERVER_NOT_FOUND |
Server not found or deleted |
| 409 | ACTIVE_TOKEN_LIMIT |
The limit of 100 active tokens per server has been reached |
| 429 | TOKEN_MINT_RATE_LIMIT |
The limit of 50 mints per hour per API key has been exceeded. Header Retry-After: 3600 |
| 503 | FEATURE_DISABLED |
Access tokens are disabled on the platform |
Full list of common API errors — Errors.
Known specifics
tokenis valid for 10 minutes regardless ofttlSeconds. SavetokenandjwtExpiresAtimmediately: the JWT stops working atjwtExpiresAt, notexpiresAt.expiresAtis the retention period of the record (for listing and revocation). To extend access, call token refresh (same token, fresh JWT, no new record) or mint a new one viaPOST /access-tokens.identityBoundis ignored forapi-bearer. The identifier in the log is always the UUID of the API key owner.- Limits: 100 active tokens per server; 50 mints per hour per API key;
ttlSecondsfrom 300 to 315 360 000.