For AI agents: markdown of this page — /docs-content-en/timeline-logs/bindings.md documentation index — /llms.txt

Bindings

Linking a single log entry to multiple CRM entities. Besides the parent entity (specified at creation), an entry can be additionally bound to other CRM records — it will appear in their timelines too.

Bitrix24 API: crm.timeline.bindings.* Scope: crm

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

Terminal
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

Terminal
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

javascript
// 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

javascript
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

JSON
{
  "success": true,
  "data": { "bound": true }
}

Error response example

400 — entityTypeId with no mapping to ENTITY_TYPE:

JSON
{
  "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