For AI agents: markdown of this page — /docs-content-en/apps/placements/unbind.md documentation index — /llms.txt
Unbind a placement
POST /v1/placements/unbind
Removes the application from the Bitrix24 interface point where it was registered and detaches that placement code from the application. The call is safe to repeat: a code that is not listed as bound to the application is treated as already detached.
Call preconditions — what is required before binding.
Request fields (body)
| Field | Type | Req. | Description |
|---|---|---|---|
placement |
string | yes | Placement code. Codes bound to the application — Bound placements, the full list — Available placements |
handler |
string | no | Handler URL whose registration must be removed. Without this field, all registrations of the application on the specified placement are removed |
Examples
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/placements/unbind \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"placement": "CRM_DEAL_DETAIL_TAB"}'
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/placements/unbind', {
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' }),
})
const { data } = await res.json()
if (data.alreadyUnbound) {
console.log('The placement is already unbound from the application')
}
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on successful execution |
data.placement |
string | Placement code that was unbound |
data.alreadyUnbound |
boolean | Present with the value true when the specified code was not listed as bound to the application |
Response example
Unbinding a bound placement:
{
"success": true,
"data": {
"placement": "CRM_DEAL_DETAIL_TAB"
}
}
The placement code is not bound to the application:
{
"success": true,
"data": {
"placement": "CRM_QUOTE_DETAIL_TAB",
"alreadyUnbound": true
}
}
Error response example
400 — the placement code is not recognized:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "placement: Placement must be in VALID_PLACEMENTS or match the dynamic CRM pattern CRM_(DYNAMIC|SMART)_<entityTypeId>_(DETAIL_TAB|DETAIL_ACTIVITY|LIST_MENU|LIST_TOOLBAR|DETAIL_TOOLBAR|ACTIVITY_TIMELINE_MENU)"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | OAUTH_APP_REQUIRED |
The request was made with a personal vibe_api_… key. Unbinding is available only to an application authorization key |
| 400 | VALIDATION_ERROR |
The body failed validation: the placement code is not recognized or handler is not a URL |
| 400 | APP_NOT_REGISTERED |
The application has no Bitrix24 client identifier, so there is no registration to remove |
| 400 | BOX_NO_DEVELOPER_KEY |
The account is self-hosted and the application author has no developer key configured |
| 401 | SESSION_REQUIRED |
The Authorization: Bearer header with a session token was not passed where it is required |
| 403 | PLACEMENT_SCOPE_MISSING |
The key has no placement scope |
| 403 | WRITE_BLOCKED_READONLY_KEY |
The key works in read-only mode. Switch the mode in the API Keys section |
| 404 | APP_NOT_FOUND |
No application is linked to the key |
| 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 registration removal. The placement stays in the application's list. Once the check is enabled, an unconfirmed removal on any transport answers with the same code — see the note below |
The full list of common API errors — Errors.
Unbinding runs over ONE transport, not two. The platform selects it based on the account and the application: on a self-hosted account, and on a cloud account switched to the developer key, it is the developer-key transport, otherwise it is the application's OAuth transport. A call never uses both at once, so "removed over one, confirmed over the other" does not happen here.
Waiting for confirmation is being rolled out account by account, so there are two cases:
- While the capability is not enabled on the account — an unconfirmed response does not stop the unbind: the placement is dropped from the application's list and the request returns success. The registration may still remain on the account.
- Once enabled — an unconfirmed response returns
502 BITRIX_UNAVAILABLEand keeps the code in the application's list so that the list does not drift from the account. Retry the request.
The check applies to all three unbind transports alike — the self-hosted one, the cloud developer-key one and the application's OAuth transport. Confirmation means the number of removed registrations that Bitrix24 names; an answer without it is not a confirmation. So once the check is enabled, success on this request means "Bitrix24 confirmed the removal", not "Bitrix24 accepted the call".
Known specifics
- Pass the same
handlervalue as when binding. The URL is normalized to the registered handler by the same rules as when binding, so unbinding finds the registration and removes the placement from the account.