For AI agents: markdown of this page — /docs-content-en/timeline-logs/bindings/bind.md documentation index — /llms.txt
Bind an entry
POST /v1/timeline-logs/:id/bind
Binds an existing log entry to an additional CRM entity — the same entry appears in its timeline. Used when one event must be visible across several cards at once: a deal, a contact, a company.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id (path) |
number | yes | Log entry ID |
Request fields (body)
| Field | Type | Required | Description |
|---|---|---|---|
entityId |
number | yes | ID of the entity to bind to |
entityTypeId |
number | yes* | Numeric CRM entity type. See Entity types |
entityType |
string | yes* | String type code: "lead", "deal", "contact", "company", "quote", "order", "smart_invoice", "dynamic_<entityTypeId>" |
*Pass either entityTypeId or entityType — Vibecode substitutes the right one into the B24 call. If both are passed, entityType takes priority.
Supported types
entityTypeId |
entityType |
|---|---|
| 1 | lead |
| 2 | deal |
| 3 | contact |
| 4 | company |
| 7 | quote |
| 14 | order |
| 31 | smart_invoice |
| ≥ 128 | dynamic_<entityTypeId> (arbitrary smart process) |
Any entityTypeId < 128 not present in the table returns 400 INVALID_ENTITY_TYPE_ID. Your Bitrix24 account's smart-process list — GET /v1/smart-processes.
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/timeline-logs/5012/bind \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "entityTypeId": 3, "entityId": 50 }'
curl — OAuth app
curl -X POST https://vibecode.bitrix24.com/v1/timeline-logs/5012/bind \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "entityTypeId": 3, "entityId": 50 }'
JavaScript — personal key
// Bind to a contact
const res = await fetch('https://vibecode.bitrix24.com/v1/timeline-logs/5012/bind', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ entityTypeId: 3, entityId: 50 }),
})
const { success } = await res.json()
// Alternative — specify the type as a string (useful for smart processes)
await fetch('https://vibecode.bitrix24.com/v1/timeline-logs/5012/bind', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ entityType: 'dynamic_174', entityId: 1 }),
})
JavaScript — OAuth app
const res = await fetch('https://vibecode.bitrix24.com/v1/timeline-logs/5012/bind', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({ entityTypeId: 3, entityId: 50 }),
})
const { success } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data.bound |
boolean | Always true — confirmation of the binding |
Response example
{
"success": true,
"data": { "bound": true }
}
Error response example
400 — entityTypeId with no mapping to ENTITY_TYPE:
{
"success": false,
"error": {
"code": "INVALID_ENTITY_TYPE_ID",
"message": "entityTypeId=99 has no ENTITY_TYPE mapping. Use 1=lead, 2=deal, 3=contact, 4=company, 7=quote, 14=order, 31=smart_invoice, or ≥128 for smart-processes."
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS |
entityId was not passed, or neither entityTypeId nor entityType |
| 400 | INVALID_ENTITY_TYPE_ID |
entityTypeId < 128 and not in the mapping table |
| 422 | BITRIX_ERROR |
Bitrix24 rejected the request (e.g. entityType is unknown or the entity does not exist) |
| 403 | SCOPE_DENIED |
The API key lacks the crm scope |
| 401 | TOKEN_MISSING |
The API key has no configured tokens |
Full list of common API errors — Errors.
Known specifics
The parent entity is already bound automatically. When a log entry is created via POST /v1/timeline-logs for entityTypeId+entityId, the entry is already considered bound to that pair. bind is only needed for additional entities.
The case of the string entityType does not matter. Vibecode lowercases it — "DEAL", "Deal", "deal" give the same result. In bindings.list responses the type is always returned in lowercase.
Binding to the same pair is idempotent at the B24 level. A repeated bind to an already-bound entity returns 200 + {bound: true} with no error. The duplicate does not appear in the bindings list.
You cannot bind to an arbitrary type. If you pass something absent from the B24 dictionary in entityType ("random", "foo"), B24 returns ENTITY_TYPE is not defined or invalid. — Vibecode propagates it as 422 BITRIX_ERROR. The type-list check on the Vibecode side runs only against the entityTypeId mapping.
It does not validate the existence of the :id log entry. If you pass the id of a nonexistent log entry in the path, bind still returns 200 + {bound: true} with no error. The binding is not created, because there is no source. Before bind, make sure the log entry exists (GET /v1/timeline-logs/:id) or use an id that was just returned from POST /v1/timeline-logs.
See also
- Unbind — the reverse operation
- List bindings — all entities the entry is bound to
- Create an entry — the parent entity is bound automatically