
## List comments

`GET /v1/timelines`

Returns timeline comments attached to a specific CRM record. The `entityType` and `entityId` filters are required — without them the request returns `400 MISSING_REQUIRED_FILTER`.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|---------|
| `filter` (query) | object | yes | — | The parent CRM record: the `entityType` and `entityId` keys are required, their values are described below the table. The same keys are also accepted without the wrapper: `?entityType=deal&entityId=741`.<br>[Filtering syntax](/docs/filtering). Example: `?filter[entityType]=deal&filter[entityId]=741` |
| `limit` (query) | number | no | `50` | Number of records (up to 5000). When `limit > 50`, Vibecode automatically requests several pages from Bitrix24 |
| `offset` (query) | number | no | `0` | Skip N records. When `offset > 0`, `limit ≤ 500` is recommended |
| `sort` (query) | string | no | — | Sorting by creation date: `sort=-createdAt` puts the newest first, `sort=createdAt` the oldest first. Sorting by any other field, `id` included, is accepted without an error but does not change the order |
| `order` (query) | object | no | — | The same sorting in map form: `order[createdAt]=desc`. If `sort` is also sent, `sort` applies. A direction other than `asc` or `desc` returns `400 INVALID_SORT_DIRECTION` |
| `select` (query) | string | no | — | Field selection: `?select=id,comment,authorId` |

`filter[entityType]` is the type of the parent CRM record: `deal`, `lead`, `contact`, `company` or `DYNAMIC_<entityTypeId>` for smart processes, for example `DYNAMIC_174`. The `entityTypeId` value comes from [`GET /v1/smart-processes`](/docs/entities/smart-processes/list). `filter[entityId]` is the parent record ID, and its source depends on the type: [`GET /v1/deals`](/docs/entities/deals/list), [`GET /v1/leads`](/docs/entities/leads/list), [`GET /v1/contacts`](/docs/entities/contacts/list), [`GET /v1/companies`](/docs/entities/companies/list), and for smart process items — [`GET /v1/items/:entityTypeId`](/docs/entities/items/list).

## Examples

### curl — personal key

```bash
curl -g "https://vibecode.bitrix24.com/v1/timelines?filter[entityType]=deal&filter[entityId]=741" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl -g "https://vibecode.bitrix24.com/v1/timelines?filter[entityType]=deal&filter[entityId]=741" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/timelines?filter[entityType]=deal&filter[entityId]=741', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data, meta } = await res.json()
console.log(`Found ${meta.total} comments`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/timelines?filter[entityType]=deal&filter[entityId]=741', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { success, data, meta } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of comments (all fields — see [Comment fields](/docs/entities/timelines/fields)) |
| `meta.total` | number | Total number of records matching the filter |
| `meta.hasMore` | boolean | Whether there are more records beyond `limit` |

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": 66309,
      "entityId": 741,
      "entityType": "deal",
      "comment": "First contact: the client showed interest in the offer",
      "authorId": 1,
      "createdAt": "2026-04-24T12:39:28.000Z"
    },
    {
      "id": 66311,
      "entityId": 741,
      "entityType": "deal",
      "comment": "Follow-up: the client is ready to sign the contract next week",
      "authorId": 1,
      "createdAt": "2026-04-24T12:39:30.000Z"
    }
  ],
  "meta": {
    "total": 2,
    "hasMore": false
  }
}
```

## Error response example

400 — a required filter was not provided:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_FILTER",
    "message": "GET /v1/timelines requires filter fields: entityType, entityId. Example: GET /v1/timelines?filter[entityType]=...&filter[entityId]=..."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_FILTER` | The required `filter[entityType]` and `filter[entityId]` were not provided |
| 400 | `UNKNOWN_FILTER_FIELD` | The filter contains a field that comments do not have. The message lists the allowed fields after the word `Available` |
| 400 | `INVALID_SORT_DIRECTION` | A direction in `order` other than `asc` or `desc` |
| 422 | `BITRIX_ERROR` | Invalid `entityType` value (e.g. a numeric CRM code instead of a string) |
| 403 | `SCOPE_DENIED` | The API key lacks the `crm` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 429 | `RATE_LIMITED` | Rate limit exceeded: 300 requests per minute per portal. All API keys of the portal share one limit. The current limit is returned in the `x-ratelimit-limit` header. Retry after the delay in the `Retry-After` header |

For the full list of common API errors, see [Errors](/docs/errors).

## Known specifics

**`entityType` is a string.** Use string CRM type identifiers: `deal`, `lead`, `contact`, `company`. For smart processes — `DYNAMIC_<entityTypeId>` (e.g. `DYNAMIC_174`). In the response the value comes back in lowercase (`dynamic_174`). Numeric CRM codes do not work in `entityType` — the request returns `422 BITRIX_ERROR Access denied.`

**Filtering only by `entityType` + `entityId`.** Other comment fields in the filter (`authorId`, `comment`, ranges like `>=createdAt`, etc.) are accepted without an error but do not narrow the selection — the response is the same as without them. If you need to narrow results by author or text, fetch all comments for the record and filter them on the client side.

**Default order — ascending by `id`.** Without `sort`, the list is returned in creation order: the earliest comments first. For the newest first, use `sort=-createdAt`.

**Auto-pagination.** When `limit > 50`, Vibecode automatically requests several pages from Bitrix24 and returns all records in a single response.

## See also

- [Get comment](/docs/entities/timelines/get)
- [Add comment](/docs/entities/timelines/create)
- [Comment fields](/docs/entities/timelines/fields)
- [Filtering syntax](/docs/filtering)
- [Entity API](/docs/entity-api)
- [Batch](/docs/batch)
- [Limits and optimization](/docs/optimization)
