For AI agents: markdown of this page — /docs-content-en/apps/placements/bind.md documentation index — /llms.txt
Bind a placement
POST /v1/placements/bind
Registers the application at the selected interface point of a Bitrix24 account — a card tab, a menu item, a chat panel. After the call the point appears in the interface with the title passed in the request.
Call preconditions — what is required before binding.
Request fields (body)
| Field | Type | Req. | Description |
|---|---|---|---|
placement |
string | yes | Placement code. The list of codes available to the account — Available placements |
handler |
string | yes | Absolute URL of the application page that opens at this placement |
title |
string | yes | Placement title in the account interface, from 1 to 255 characters |
options |
object | no | Placement settings. Besides the fields listed below, any other fields are accepted — for example context, role, extranet for chat widgets. The value of each field is a string, a number or a boolean. Nested objects and arrays are not accepted |
options.iconName |
string | no | Font Awesome icon name with the fa- prefix — for example fa-comment. Bitrix24 rejects a name longer than 50 characters. The list of names — the Font Awesome 6 gallery. An icon is required for the IM_SIDEBAR, IM_NAVIGATION, IM_TEXTAREA placements, but the platform fills one in when the field is absent and reports it in the optionsDefaulted response field. Your own value always wins over the filled-in one. The IM_CONTEXT_MENU placement needs no icon |
options.errorHandlerUrl |
string | no | Error page URL for the PAGE_BACKGROUND_WORKER placement. If the field is not passed, the platform substitutes the current handler URL |
options.iconSvg |
string | no | Icon in SVG format, up to 10,000 characters |
options.width |
number | no | Width of the IM_TEXTAREA panel, in pixels. A positive integer |
options.height |
number | no | Height of the IM_TEXTAREA panel, in pixels. A positive integer |
options.color |
string | no | Icon color for the IM_TEXTAREA and IM_SIDEBAR placements, from the Bitrix24 chat palette: RED, GREEN, MINT, LIGHT_BLUE, DARK_BLUE, PURPLE, AQUA, PINK, LIME, BROWN, AZURE, KHAKI, SAND, ORANGE, MARENGO, GRAY, GRAPHITE. Not a hexadecimal code |
Examples
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/placements/bind \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"placement": "CRM_DEAL_DETAIL_TAB",
"handler": "https://example.com/deal-tab",
"title": "Deal analytics"
}'
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/placements/bind', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
placement: 'CRM_DEAL_DETAIL_TAB',
handler: 'https://example.com/deal-tab',
title: 'Deal analytics',
}),
})
const { data } = await res.json()
console.log('Registered handler URL:', data.handler)
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on a successful binding |
data.placement |
string | Code of the bound placement |
data.handler |
string | Handler URL registered on the account |
data.title |
string | Placement title in the account interface |
data.options |
object | Effective set of placement settings. Returned when the settings are passed in the request or substituted by the platform |
data.alreadyBound |
boolean | true when the placement was already listed as bound and the registration was performed again |
data.handlerRewritten |
boolean | true when the passed handler URL was replaced with the platform one |
data.requestedHandler |
string | Handler URL from the request. Returned together with handlerRewritten |
Response example
The passed handler URL was replaced with the platform one:
{
"success": true,
"data": {
"placement": "CRM_DEAL_DETAIL_TAB",
"handler": "https://vibecode.bitrix24.com/v1/bitrix-handler",
"title": "Deal analytics",
"requestedHandler": "https://app-a1b2c3d4.vibecode.bitrix24.com/deal-tab",
"handlerRewritten": true
}
}
Repeated binding of the same code:
{
"success": true,
"data": {
"placement": "CRM_DEAL_DETAIL_TAB",
"handler": "https://example.com/deal-tab",
"title": "Deal: summary",
"alreadyBound": true
}
}
Binding the PAGE_BACKGROUND_WORKER placement without options — the platform substituted the error page URL:
{
"success": true,
"data": {
"placement": "PAGE_BACKGROUND_WORKER",
"handler": "https://example.com/worker",
"title": "Background worker",
"options": {
"errorHandlerUrl": "https://example.com/worker"
}
}
}
Error response example
400 — a required field is missing in the request body:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "title: Required"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | OAUTH_APP_REQUIRED |
The call was made with a personal key. Binding works only with an application authorization key |
| 400 | VALIDATION_ERROR |
The request body failed validation — a required field is missing or the placement code is not in the list of allowed ones |
| 400 | PLATFORM_HANDLER_UNRESOLVABLE |
The passed URL points to the technical URL of the application server, and the platform handler could not be resolved. The placement is not registered |
| 400 | APP_NOT_REGISTERED |
The application has no Bitrix24 application identifier |
| 400 | BOX_NO_DEVELOPER_KEY |
The application author has no developer key configured |
| 401 | SESSION_REQUIRED |
The Authorization: Bearer header with a session token is missing |
| 403 | PLACEMENT_SCOPE_MISSING |
The key has no placement scope |
| 403 | WRITE_BLOCKED_READONLY_KEY |
The key works in read-only mode. Switch it to read and write |
| 403 | BOX_WEBHOOK_NOT_DEVELOPER_KEY |
The developer key used for the binding lacks the rest.developer scope. A key's scopes are fixed when it is issued — reconnect the account so the key is issued again. Returned before the account-access checks: a missing scope is not a question of the account's plan |
| 403 | SESSION_REQUIRES_ADMIN |
The developer key belongs to a user without account administrator rights |
| 403 | PLACEMENT_APP_GRANT_MISSING |
The placement is not available to the Bitrix24 application: its grant lacks the required scope. details carries the required scope in requiredScope, the placements available to the application (availablePlacements, availablePlacementsTotal) and the way to widen the grant in remediation. An application's scopes are fixed when it is installed — widening them requires re-issuing the authorization key or creating an application that requests the scope up front. Vibecode key scopes do not affect this |
| 400 | PLACEMENT_OPTIONS_REQUIRED |
The placement has a required option that is absent from the request and that the platform could not fill in. details carries missing — the list of those fields |
| 400 | PLACEMENT_NOT_REST_BINDABLE |
The placement cannot be bound over the API: Bitrix24 does not declare it an embedding point. Pick another code from available placements — placements like this one are marked there with restBindable: false |
| 403 | INT_TARIFF_REQUIRED |
The account gets access through its Bitrix24 plan — a commercial plan is required. error.details.upgradeUrl is not returned. On .com, infrastructure and key issuance additionally require a Vibe+ plan (INT_VIBE_PLUS_REQUIRED) |
| 404 | APP_NOT_FOUND |
No application is linked to the key |
| 404 | B24_EMBEDDING_APP_NOT_FOUND |
Bitrix24 does not know the application ID: the local application was deleted or reinstalled on the account. Create the local application again and call POST /v1/apps/:id/relink-oauth with the new bitrixClientId and bitrixClientSecret. Not to be confused with APP_NOT_FOUND, which is about the key-to-application link on the Vibecode side |
| 413 | PAYLOAD_TOO_LARGE |
The body was not sent as JSON and is longer than one byte. Set the Content-Type: application/json header |
| 415 | FST_ERR_CTP_INVALID_MEDIA_TYPE |
The body was not sent as JSON and is exactly one byte — the same cause, a different validation branch |
| 502 | BITRIX_UNAVAILABLE |
Bitrix24 rejected the placement registration and the reason could not be named. The Bitrix24 response code and status are returned in details, alongside placementInAppList when the placement is available to the application, and diagnostics — "placement_list_skipped" when the reason could not be checked with the account, or "placement_list_empty" when it answered with an empty list, which proves nothing |
| 503 | NETWORK_DEVKEY_REQUIRED |
The developer key for the application author has not been issued yet |
The full list of common API errors — Errors.
Known specifics
- A placement can require a scope on the Bitrix24 application, not on the key. Bitrix24 offers an embedding point only to applications whose grant covers the module that placement belongs to: task card tabs need the tasks scope, profile menu items need the users scope, and so on. The scope each code requires is returned per placement in available placements as
requiredScope, and the summary of the gates in key self-description asplacements.bindPrerequisite. An application's scopes are fixed when it is installed: they cannot be changed on a live application — re-issue the authorization key instead. - The platform fills in the options a placement requires. A chat widget's icon and the background worker's error page URL are filled in when you omit them. The list of filled-in fields is returned as
optionsDefaulted. - Repeated binding re-registers the placement. A call for an already bound code is not rejected: the platform removes the previous registration and binds the placement again, so the new handler URL and title take effect. This is the only way to change the title of an already bound placement.
- The technical URL of the application server is replaced with the platform one. If
handlerpoints to the technical URL of the application server, the platform application handler is registered on the account. External URLs are registered unchanged. - Bitrix24 augments
optionswith its own values. For chat widgets the account stores its own settings alongside the passed ones — display area, role and the extranet flag. They are returned in bound placements even when you did not pass them. - One title for all interface languages. The
titlevalue goes to the account as a single label. A separate translation is not set by this call. In bound placements thelangAllfield returns the same title for every language. - A successful response means the account accepted the write, not that the record stayed in place. The actual account state at any moment after binding is checked with the
portalSyncfield in bound placements:ok— the account returned the code,drift— the code is listed in Vibecode but the account does not have it. - One placement can be occupied by several applications. Bitrix24 distinguishes registrations by application, so binding the same code from a second application of the account is not rejected and does not remove the first registration. Sharing the same platform handler URL across applications does not change that.