لوكلاء AI: ملف markdown لهذه الصفحة — /docs-content-en/keys-auth/oauth.md فهرس التوثيق — /llms.txt

مقالات التوثيق متاحة حاليًا باللغة الإنجليزية فقط.

Application user authorization

OAuth authorization flow for applications that act on behalf of different users of a Bitrix24 account. The user signs in through Bitrix24, the application receives a session token, and then calls the API on their behalf. An AI agent that is given the authorization key completes this whole flow on its own — following the steps below.

Scope: not required | Base URL: https://vibecode.bitrix24.com/v1 | Authorization: the authorization key in the app_key parameter

When user authorization is needed

The vibe_app_ authorization key acts on behalf of the specific user who installed the application. To tell the platform which user to call Bitrix24 as, the request carries a session token in the Authorization: Bearer header. The token is issued at the end of this flow.

The personal vibe_api_ key acts on behalf of its own owner and does not use a session token. For background scenarios without a user at the screen, use it instead of the authorization key — Passing the key.

The /v1/oauth/* endpoints do not read the X-Api-Key header. They take the authorization key as the app_key parameter: in the query string of GET /v1/oauth/authorize and GET /v1/oauth/poll, in the body of POST /v1/oauth/token and POST /v1/oauth/placement-session. The exception is POST /v1/oauth/revoke: it needs no authorization key and accepts only the session token in the Authorization: Bearer header.

Step 1. Send the user to authorization

Generate a state — a cryptographically random string of 16–512 characters. This protects against cross-site request forgery per RFC 6749 §10.12: the client generates the value, and on return checks that the same value came back. The server cannot generate state for you.

Build a link to GET /v1/oauth/authorize and redirect the user's browser to it. This is a top-level navigation, not a background request — the Bitrix24 consent page sends an X-Frame-Options header and does not open inside an iframe.

javascript
const state = crypto.randomUUID()
// Save state in the user's session to check it on return
const url = new URL('https://vibecode.bitrix24.com/v1/oauth/authorize')
url.searchParams.set('app_key', 'YOUR_APP_KEY')
url.searchParams.set('state', state)
url.searchParams.set('redirect_uri', 'https://myapp.example.com/callback')
window.location.href = url.toString()

The platform checks app_key and redirect_uri and redirects the user to the Bitrix24 authorization page. After authorization, Bitrix24 returns the user to the application's registered handler, and the platform then returns them to your redirect_uri.

Step 2. Handle the return to `redirect_uri`

After authorization, the platform redirects the browser to your redirect_uri with a one-time code and your state:

https://myapp.example.com/callback?code=VIBE_AUTH_CODE&state=YOUR_STATE

Compare state with the value you saved in step 1. If the values do not match, abort authorization. For the errors this address can carry, see What arrives at redirect_uri.

Step 3. Exchange the code for a session token

From the application server, exchange code for a session token. The redirect_uri in the body must exactly match the one from step 1.

cURL

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "app_key": "YOUR_APP_KEY",
    "code": "VIBE_AUTH_CODE",
    "redirect_uri": "https://myapp.example.com/callback"
  }'

JavaScript

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    app_key: 'YOUR_APP_KEY',
    code: 'VIBE_AUTH_CODE',
    redirect_uri: 'https://myapp.example.com/callback',
  }),
})
const { access_token, user, expires_in } = await res.json()
// Save access_token — it is valid for 24 hours
JSON
{
  "success": true,
  "access_token": "vibe_session_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "user": { "id": "42", "name": "John Smith", "email": "user@example.com" },
  "expires_in": 86400
}

The code is one-time and valid for 5 minutes.

Step 4. Call the API with the session token

Every API request carries two headers — the authorization key in X-Api-Key and the session token in Authorization: Bearer:

cURL

Terminal
curl https://vibecode.bitrix24.com/v1/deals \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/deals', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})
const { data } = await res.json()

The session inherits the application's rights in the Bitrix24 account. Without the Authorization: Bearer header, endpoints that require a user context return 401 TOKEN_MISSING.

What arrives at `redirect_uri`

The platform returns the user to redirect_uri with the result in query parameters. Your state always comes back — check it first.

Parameter When it arrives Value
Parametercode When it arrivesAuthorization succeeded ValueOne-time code to exchange for a token. Valid for 5 minutes
Parameterstate When it arrivesAlways ValueThe state value passed in step 1
Parametererror When it arrivesAuthorization failed ValueReason for the denial — one of the values below

error values:

error What happened
errortoken_exchange_failed What happenedBitrix24 did not issue tokens for the authorization code
errorinvalid_domain What happenedThe Bitrix24 account domain failed validation
errorprofile_fetch_failed What happenedFailed to read the user profile in the Bitrix24 account
errorapp_unavailable What happenedThe application is no longer available: its author erased their data

Some failures at the return step arrive as a JSON response with status 400 or 500 instead of in the address: until the platform knows redirect_uri, it cannot redirect to it. These are MISSING_PARAMS, INVALID_STATE, and APP_CONFIG_ERROR from the Errors table.

`redirect_uri` rule

redirect_uri must exactly match one of the addresses registered for the application — scheme, host, port, and path all match. You can add a return address in the application card in the Authorization Keys section — the "Redirect URI (OAuth)" field.

A new application has the address http://localhost registered by default — without a port and with the path /. The match is exact, so http://localhost:3000/callback does not match it. For the return to go to your address — http://localhost:3000/callback or https://myapp.example.com/callback — first add it in the application card. Otherwise GET /v1/oauth/authorize returns 400 INVALID_REDIRECT_URI.

If redirect_uri is omitted, the platform uses the built-in return page — Authorization without your own redirect_uri.

Authorization without your own `redirect_uri`

When redirect_uri is omitted, the platform returns the user to the built-in /oauth/complete page and creates the session token on its side. The application retrieves the result by polling GET /v1/oauth/poll with the same state.

cURL

Terminal
curl "https://vibecode.bitrix24.com/v1/oauth/poll?app_key=YOUR_APP_KEY&state=YOUR_STATE"

JavaScript

javascript
const url = `https://vibecode.bitrix24.com/v1/oauth/poll?app_key=YOUR_APP_KEY&state=${state}`
const res = await fetch(url)
const result = await res.json()
if (result.status === 'complete') {
  // result.access_token, result.user, result.expires_in
}

Until the user completes sign-in, the response carries status pending:

JSON
{ "success": true, "status": "pending" }

After sign-in, the same request returns the session token. The result is one-time — the next poll with this same state returns pending again:

JSON
{
  "success": true,
  "status": "complete",
  "access_token": "vibe_session_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "user": { "id": "42", "name": "John Smith", "email": "user@example.com" },
  "expires_in": 86400
}

The result is kept for 10 minutes. Retrieve it right after the user returns to the sign-in page.

Session token: lifetime and revocation

The session token is valid for 24 hours and is not refreshed — the expires_in field in the response equals 86400. There is no renewal mechanism. After expiry, calls on behalf of the user return 401 INVALID_SESSION — this is the signal to go through authorization again: GET /v1/oauth/authorize → POST /v1/oauth/token.

To revoke a token early, call POST /v1/oauth/revoke with the session token in the Authorization: Bearer header. Revocation deletes the user's session, and further calls with this token are rejected.

cURL

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/oauth/revoke \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/oauth/revoke', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer USER_SESSION_TOKEN' },
})
const { revoked } = await res.json()
JSON
{ "success": true, "revoked": true }

The revoked field equals false if there was no longer an active session with that token. The response arrives with status 200 in both cases.

Application on your own server

A separate tab for sign-in is not always available — for example, the application opens as a placement inside Bitrix24, and the consent page does not open inside an iframe. If the application is hosted on your own server rather than behind Black Hole, the current user's session token is obtained in one of two ways — depending on whose handler receives the placement.

Vibecode application, appUrl — your server. The placement arrives at the Vibecode handler, and the platform redirects the browser to <appUrl>/?code=<one-time code>&placement=...&member_id=.... Your server exchanges the code for a session token using the same POST /v1/oauth/token request with the body { app_key, code, redirect_uri }, where redirect_uri exactly equals the configured appUrl. The session token does not reach the browser — the address holds only a one-time code, useless without app_key. Edit the appUrl field in the application card in the Authorization Keys section.

Your own Bitrix24 application with its own handler. The placement arrives directly at your server with a Bitrix24 user token. Exchange it for a session token with a server request — POST /v1/oauth/placement-session.

cURL

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/oauth/placement-session \
  -H "Content-Type: application/json" \
  -d '{
    "app_key": "YOUR_APP_KEY",
    "access_token": "BITRIX24_USER_TOKEN",
    "member_id": "MEMBER_ID",
    "domain": "mycompany.bitrix24.com"
  }'

JavaScript

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/oauth/placement-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    app_key: 'YOUR_APP_KEY',
    access_token: 'BITRIX24_USER_TOKEN',
    member_id: 'MEMBER_ID',
    domain: 'mycompany.bitrix24.com',
  }),
})
const { access_token, user, expires_in } = await res.json()
JSON
{
  "success": true,
  "access_token": "vibe_session_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "user": { "id": "42", "name": "John Smith", "email": "user@example.com" },
  "expires_in": 86400
}

domain must match the application's Bitrix24 account. The refresh_token and expires_in fields in the body are optional and describe the Bitrix24 user token: expires_in — how long it is valid, 3600 seconds by default. Without an active refresh_token, the Bitrix24 token is not refreshed automatically — after it expires, reopen the placement. The session token itself, as in the main flow, is valid for 24 hours.

For the full lifecycle of an embedded application and handler examples in Node, Python, and Go, see Authorization in a Black Hole app.

Endpoint reference

Method Path Description
MethodGET Path/v1/oauth/authorize DescriptionStart authorization — redirect to the Bitrix24 sign-in page
MethodGET Path/v1/oauth/callback DescriptionReceive the Bitrix24 response. Called by Bitrix24, not the application
MethodPOST Path/v1/oauth/token DescriptionExchange the code for a session token
MethodGET Path/v1/oauth/poll DescriptionRetrieve the authorization result without your own redirect_uri
MethodPOST Path/v1/oauth/placement-session DescriptionSession token for an application on your own server
MethodPOST Path/v1/oauth/revoke DescriptionRevoke the session token

Errors

The authorization key is checked on entry to GET /v1/oauth/authorize, POST /v1/oauth/token, and POST /v1/oauth/placement-session:

HTTP Code Description
HTTP401 CodeINVALID_APP_KEY Descriptionapp_key not found or it is not an authorization key
HTTP401 CodeKEY_INACTIVE DescriptionAuthorization key revoked
HTTP401 CodeKEY_EXPIRED DescriptionAuthorization key has expired
HTTP403 CodeOWNER_BLOCKED DescriptionThe key owner is blocked or no longer active on the portal

GET /v1/oauth/authorize:

HTTP Code Description
HTTP400 CodeINVALID_REQUEST DescriptionMissing required state or it is outside the 16–512 character range
HTTP400 CodeINVALID_REDIRECT_URI Descriptionredirect_uri is not registered for the application
HTTP500 CodeNO_PORTAL DescriptionThe application is not linked to a portal

GET /v1/oauth/callback (called by Bitrix24):

HTTP Code Description
HTTP400 CodeMISSING_PARAMS DescriptionBitrix24 returned without code or state
HTTP400 CodeINVALID_STATE Descriptionstate not found or expired after 20 minutes. error.details.reason holds NOT_FOUND or EXPIRED
HTTP500 CodeAPP_CONFIG_ERROR DescriptionThe application has no OAuth credentials set

POST /v1/oauth/token:

HTTP Code Description
HTTP400 CodeINVALID_REQUEST DescriptionThe body has no code or redirect_uri
HTTP400 CodeINVALID_CODE DescriptionCode not found or belongs to another application
HTTP400 CodeCODE_EXPIRED DescriptionThe code has expired — 5 minutes
HTTP400 CodeCODE_ALREADY_USED DescriptionThe code has already been exchanged for a token
HTTP400 CodeREDIRECT_URI_MISMATCH Descriptionredirect_uri does not match the one passed to GET /v1/oauth/authorize
HTTP500 CodeTOKEN_NOT_FOUND DescriptionUser token not found

GET /v1/oauth/poll:

HTTP Code Description
HTTP400 CodeINVALID_REQUEST Descriptionstate shorter than 16 characters or no app_key
HTTP401 CodeINVALID_APP_KEY Descriptionapp_key not found or it is not an authorization key

POST /v1/oauth/placement-session:

HTTP Code Description
HTTP400 CodeINVALID_REQUEST DescriptionThe body has no access_token, member_id, or domain
HTTP400 CodeDOMAIN_MISMATCH Descriptiondomain does not match the application's portal
HTTP401 CodeUSER_AUTH_REQUIRED DescriptionThe Bitrix24 user token did not confirm authorization on the portal
HTTP403 CodeAPP_UNAVAILABLE DescriptionThe application is no longer available: its author erased their data
HTTP500 CodeNO_PORTAL DescriptionThe application is not linked to a portal

POST /v1/oauth/revoke:

HTTP Code Description
HTTP400 CodeMISSING_TOKEN DescriptionNo Authorization: Bearer with a session token was passed

API calls with a session token:

HTTP Code Description
HTTP401 CodeTOKEN_MISSING DescriptionThe authorization key was sent without Authorization: Bearer to an endpoint that needs a user context
HTTP401 CodeINVALID_SESSION DescriptionThe session token has expired, been revoked or is unknown. Authorize again: GET /v1/oauth/authorize → POST /v1/oauth/token

Full list of common API errors — Errors.

Error response example

400 — required state not passed:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "state: Required"
  }
}

See also