
# CRM Timeline

12 REST endpoints for logging actions in the timeline of CRM entities: creating log entries, notes on them, pinning, binding to multiple entities at once. Handy for AI agents, background integrations, and automation that need to leave a structured trail in a deal or contact card.

**Scope:** `crm` | **Base URL:** `https://vibecode.bitrix24.com/v1` | **Authorization:** `X-Api-Key`

[Quick start](#quick-start) | [An AI agent logs its actions (full example)](#full-example-an-ai-agent-logs-its-actions) | [Error codes](#error-codes) | [Endpoint reference](#endpoint-reference)

## Documentation sections

- [Log entries](/docs/timeline-logs/logs) — create, view, delete log entries
- [Notes](/docs/timeline-logs/notes) — a note-comment on a log entry
- [Pins](/docs/timeline-logs/pins) — pin or unpin an entry at the top of the timeline
- [Bindings](/docs/timeline-logs/bindings) — link one entry to multiple CRM entities

## When to use

- Record an AI agent's action: analyzed the client, prepared a quote, sent a notification.
- Capture an event from an external system: payment succeeded, order assembled, document signed.
- Build an audit trail of an integration: what data it processed, what it based its decision on.
- Pin a key deal event at the top of the timeline so the manager sees the context right away.

For user text comments (not system events) use [`/v1/timelines`](/docs/entities/timelines) — a separate API over `crm.timeline.comment.*`.

## Quick start

### 1. Create an entry in a deal's timeline

```bash
curl -X POST https://vibecode.bitrix24.com/v1/timeline-logs \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entityTypeId": 2,
    "entityId": 100,
    "title": "AI agent processed the request",
    "text": "Client data analyzed. Recommendation: offer the Enterprise plan."
  }'
```

Response:

```json
{
  "success": true,
  "data": {
    "id": 5012,
    "created": "2026-04-27T10:00:00+00:00",
    "authorId": 1,
    "title": "AI agent processed the request",
    "text": "Client data analyzed. Recommendation: offer the Enterprise plan.",
    "iconCode": ""
  }
}
```

### 2. Pin the entry at the top of the timeline

```bash
curl -X POST https://vibecode.bitrix24.com/v1/timeline-logs/5012/pin \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "entityTypeId": 2, "entityId": 100 }'
```

### 3. Attach an internal note

```bash
curl -X POST https://vibecode.bitrix24.com/v1/timeline-logs/5012/note \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "entityTypeId": 2, "entityId": 100, "text": "The client usually responds within 2 days." }'
```

## Full example: an AI agent logs its actions

Scenario: an AI agent analyzes a deal, leaves a log entry with the result, binds it to a contact and a company, attaches a note for the manager, pins it in the timeline.

```javascript
const VIBE_KEY = process.env.VIBE_KEY
const BASE = 'https://vibecode.bitrix24.com/v1'

async function api(method, path, body = null) {
  const opts = { method, headers: { 'X-Api-Key': VIBE_KEY } }
  if (body) {
    opts.headers['Content-Type'] = 'application/json'
    opts.body = JSON.stringify(body)
  }
  const res = await fetch(`${BASE}${path}`, opts)
  return res.json()
}

const dealId = 100
const contactId = 50
const companyId = 10

// 1. Record that work has started
const start = await api('POST', '/timeline-logs', {
  entityTypeId: 2,
  entityId: dealId,
  title: 'AI agent started processing',
  text: 'Client data analysis, credit-limit check, quote preparation.',
})
const startId = start.data.id

// 2. Bind the entry to the contact and the company — managers of both will see
//    the same event in their timelines
await api('POST', `/timeline-logs/${startId}/bind`, { entityTypeId: 3, entityId: contactId })
await api('POST', `/timeline-logs/${startId}/bind`, { entityTypeId: 4, entityId: companyId })

// ... the AI agent does its work ...

// 3. Record the result as a separate log entry
const result = await api('POST', '/timeline-logs', {
  entityTypeId: 2,
  entityId: dealId,
  title: 'AI agent finished processing',
  text: [
    '[b]Analysis results:[/b]',
    '- Credit limit: OK (500,000 USD)',
    '- Recommended plan: Enterprise',
    '- Discount: 10% (returning client)',
    '- Quote generated and sent by email',
  ].join('\n'),
})
const resultId = result.data.id

// 4. Pin the final entry at the top of the timeline
await api('POST', `/timeline-logs/${resultId}/pin`, { entityTypeId: 2, entityId: dealId })

// 5. Leave an internal note for the manager
await api('POST', `/timeline-logs/${resultId}/note`, {
  entityTypeId: 2,
  entityId: dealId,
  text: 'The client usually responds within 2 days. Remind the manager if there is no reply.',
})

console.log('AI agent finished, all actions logged')
```

## Which key to use

CRUD operations work with any key type — personal (`vibe_api_*`) or an OAuth app (`vibe_app_*`). However, **`DELETE /v1/timeline-logs/:id` imposes a restriction**: Bitrix24 allows a log entry to be deleted only by the same app that created it.

- **OAuth app** (`vibe_app_*` + `Authorization: Bearer ...`) — stable `client_id`, you can delete your own entries. If you plan to delete created entries via the API, use this key type.
- **Personal key** (`vibe_api_*`) — Vibecode rotates tokens between calls, so to Bitrix24 each call looks like a separate app. `DELETE` always returns `403 CROSS_APP_DELETE_FORBIDDEN`, including for freshly created entries.

If the app that created the entry is unavailable, deleting it is impossible by design. Bitrix24 does not provide a UI delete button for a log entry in the entity card. Keep this in mind when designing audit scenarios.

More details — [Delete an entry](/docs/timeline-logs/logs/delete).

## Parent entity types

The `entityTypeId` parameter (the CRM entity's numeric code) specifies whose timeline the entry is created in:

| `entityTypeId` | Entity | Where to find the ID |
|:---:|----------|--------------|
| 1 | Lead | [`GET /v1/leads`](/docs/entities/leads/list) |
| 2 | Deal | [`GET /v1/deals`](/docs/entities/deals/list) |
| 3 | Contact | [`GET /v1/contacts`](/docs/entities/contacts) |
| 4 | Company | [`GET /v1/companies`](/docs/entities/companies) |
| 7 | Quote | [`GET /v1/quotes`](/docs/entities/quotes) |
| 14 | Order | [`GET /v1/orders`](/docs/entities/orders) |
| 31 | Invoice | [`GET /v1/invoices`](/docs/entities/invoices) |
| ≥ 128 | Smart process | [`GET /v1/items/:entityTypeId`](/docs/entities/items/list); list of processes — [`GET /v1/smart-processes`](/docs/entities/smart-processes/list) |

In bindings (`bind`/`unbind`) you can use either the numeric `entityTypeId` or the string `entityType` directly (`"deal"`, `"contact"`, `"dynamic_174"`, etc.) — see [Bind an entry](/docs/timeline-logs/bindings/bind).

## Error codes

### Timeline errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | Required parameters are missing or invalid (`entityTypeId`, `entityId`, `title`, `text`, `itemType`, etc. — the specific field is in `message`) |
| 400 | `INVALID_ENTITY_TYPE_ID` | In `bindings.bind`/`unbind` an `entityTypeId` was passed with no mapping to `ENTITY_TYPE` (`< 128` and not in the table above) |
| 403 | `CROSS_APP_DELETE_FORBIDDEN` | Attempt to delete a log entry via a key other than the one it was created with |
| 404 | `ENTITY_NOT_FOUND` | A log entry with the given `id` does not exist — Bitrix24 returned a `NOT_FOUND` error |
| 404 | `NOT_FOUND` | Only `GET /v1/timeline-logs/:id`: Bitrix24 returned a successful response but the entry object is empty |
| 404 | `NOTE_NOT_FOUND` | The specified timeline item has no attached note |

### System errors

| HTTP | Code | Description |
|------|-----|---------|
| 401 | `AUTH_REQUIRED` | Missing `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Invalid API key |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens (a `vibe_app_*` key requires `Authorization: Bearer ...`) |
| 403 | `SCOPE_DENIED` | The API key lacks the `crm` scope |
| 422 | `BITRIX_ERROR` | Bitrix24 returned an error (text in `message`) |
| 429 | `RATE_LIMITED` | Request rate limit exceeded. Wait 1–2 seconds and retry. Several calls can be combined into [`POST /v1/batch`](/docs/batch) |
| 429 | `QUEUE_TIMEOUT` | The request to B24 did not complete within the portal's queue. The request was NOT sent to Bitrix24 — safe to retry (`Retry-After`). Narrow the filter or retry later |
| 502 | `ERROR_LOOP_DETECTED` | The circuit breaker triggered: many identical errors from B24 in a row. Wait ~60 seconds |
| 502 | `BITRIX_UNAVAILABLE` | The Bitrix24 portal is unavailable |
| 503 | `BITRIX_TIMEOUT` | Bitrix24 accepted the request but did not respond within 15 seconds. For write operations — re-read the entity first, the change may have applied |
| 500 | `INTERNAL_ERROR` | Internal server error |

Full list of common API codes — [Errors](/docs/errors).

## Endpoint reference

All 12 endpoints:

| Method | Path | Bitrix24 method | Description |
|-------|------|---------------|---------|
| POST | [/v1/timeline-logs](/docs/timeline-logs/logs/create) | `crm.timeline.logmessage.add` | Create a log entry |
| GET | [/v1/timeline-logs](/docs/timeline-logs/logs/list) | `crm.timeline.logmessage.list` | List log entries |
| GET | [/v1/timeline-logs/:id](/docs/timeline-logs/logs/get) | `crm.timeline.logmessage.get` | Get a single entry |
| DELETE | [/v1/timeline-logs/:id](/docs/timeline-logs/logs/delete) | `crm.timeline.logmessage.delete` | Delete an entry |
| POST | [/v1/timeline-logs/:id/note](/docs/timeline-logs/notes/save) | `crm.timeline.note.save` | Save or update a note |
| GET | [/v1/timeline-logs/:id/note](/docs/timeline-logs/notes/get) | `crm.timeline.note.get` | Get a note |
| DELETE | [/v1/timeline-logs/:id/note](/docs/timeline-logs/notes/delete) | `crm.timeline.note.delete` | Delete a note |
| POST | [/v1/timeline-logs/:id/pin](/docs/timeline-logs/pins/pin) | `crm.timeline.item.pin` | Pin an entry |
| POST | [/v1/timeline-logs/:id/unpin](/docs/timeline-logs/pins/unpin) | `crm.timeline.item.unpin` | Unpin an entry |
| POST | [/v1/timeline-logs/:id/bind](/docs/timeline-logs/bindings/bind) | `crm.timeline.bindings.bind` | Bind to another entity |
| POST | [/v1/timeline-logs/:id/unbind](/docs/timeline-logs/bindings/unbind) | `crm.timeline.bindings.unbind` | Unbind from an entity |
| GET | [/v1/timeline-logs/:id/bindings](/docs/timeline-logs/bindings/list) | `crm.timeline.bindings.list` | List all bindings of an entry |

## See also

- [Timeline comments](/docs/entities/timelines) — user text comments (a separate API over `crm.timeline.comment.*`)
- [Deals](/docs/entities/deals), [Leads](/docs/entities/leads), [Contacts](/docs/entities/contacts), [Companies](/docs/entities/companies) — typical parent entities
- [Smart processes](/docs/entities/smart-processes) — for timeline entries on custom CRM types
- [Batch](/docs/batch) — bulk operations
- [Limits and optimization](/docs/optimization) — rate limits
