
## List comments

`GET /v1/tasks/:taskId/comments`

Returns the comments of a specific task. On the new task card the list is read from the chat, system messages are filtered out. On the old one — from the comments block inside the card.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|---------|
| `taskId` (path) | number | yes | — | Parent task ID |
| `limit` (query) | number | | `50` | Page size (up to 200) |
| `offset` (query) | number | | `0` | How many matching comments to skip before returning results. Honoured on the new card for a request with `filter` or a sort other than `ID`, ignored on the other read paths |
| `sort` (query) | string | | `id:desc` | Sorting: field `ID`, `AUTHOR_ID` or `POST_DATE` and direction `asc` or `desc` — `?sort=post_date:desc`. The field name is case-insensitive. Sorting by `AUTHOR_NAME` and `AUTHOR_EMAIL` is accepted on the old card only, on the new one it returns `400 UNSUPPORTED_SORT_FIELD` |
| `filter` (query) | object | | — | Filter by the fields `ID`, `AUTHOR_ID`, `POST_DATE`. Passed as JSON: `?filter={"AUTHOR_ID":1}`. The field name may carry a `!`, `>`, `>=`, `<` or `<=` prefix — `?filter={">=POST_DATE":"2026-05-01T00:00:00Z"}`. The value for `POST_DATE` is an ISO 8601 date in UTC, several fields are combined with "and". Filtering by `AUTHOR_NAME` is accepted on the old card only, on the new one it returns `400 UNSUPPORTED_FILTER_FIELD` |

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/tasks/289/comments?limit=20&sort=id:desc" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth app

```bash
curl "https://vibecode.bitrix24.com/v1/tasks/289/comments?limit=20&sort=id:desc" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const url = 'https://vibecode.bitrix24.com/v1/tasks/289/comments?limit=20&sort=id:desc'
const res = await fetch(url, {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

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

### JavaScript — OAuth app

```javascript
const url = 'https://vibecode.bitrix24.com/v1/tasks/289/comments?limit=20&sort=id:desc'
const res = await fetch(url, {
  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 |
| `data[].id` | number | Comment identifier |
| `data[].taskId` | number | Parent task ID |
| `data[].authorId` | number | Author. Profile: `GET /v1/users/:authorId` |
| `data[].message` | string | Comment text (supports BB-code) |
| `data[].createdAt` | datetime | Creation date (UTC ISO 8601) |
| `meta.total` | number | Number of comments. On the new card for a request with `filter` or a sort other than `ID` — the exact count of the matches within the scanned window, on the other read paths — an estimate |
| `meta.hasMore` | boolean | Whether there are more comments beyond `limit` |
| `meta.truncated` | boolean | Comes with the value `true` only, and only on the new card for a request with `filter` or a sort other than `ID`: the scan window was exhausted, and some comments stayed beyond its edge |

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": 36559,
      "taskId": 289,
      "authorId": 1,
      "message": "Added a draft of the report to the comments — please take a look.",
      "createdAt": "2026-05-13T12:30:58.000Z"
    },
    {
      "id": 36557,
      "taskId": 289,
      "authorId": 79,
      "message": "[USER=99]Alex[/USER], done, thanks.",
      "createdAt": "2026-05-12T15:11:04.000Z"
    }
  ],
  "meta": {
    "total": 2,
    "hasMore": false
  }
}
```

## Error response example

400 — `taskId` is not a positive integer:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "taskId must be a positive integer"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | `taskId` is invalid (not a positive integer) |
| 400 | `INVALID_SORT_FIELD` | Sort by an unsupported field or direction. Supported: `ID`, `AUTHOR_ID`, `AUTHOR_NAME`, `AUTHOR_EMAIL`, `POST_DATE` with direction `asc` or `desc`. On the new card `AUTHOR_NAME` and `AUTHOR_EMAIL` answer with `UNSUPPORTED_SORT_FIELD` |
| 400 | `UNSUPPORTED_SORT_FIELD` | New card only: sort by `AUTHOR_NAME` or `AUTHOR_EMAIL`. Sort by `ID`, `AUTHOR_ID` or `POST_DATE` instead |
| 400 | `INVALID_FILTER` | The `filter` parameter is not valid JSON. New card only: `filter` is a scalar or an empty array instead of an object (`0`, `false`, `""`, `[]`); the value of `ID` or `AUTHOR_ID` is not a number; the value of `POST_DATE` does not parse as a date; or a field value is an object or an array instead of a scalar. A non-empty array or a non-empty string in `filter` yields `UNKNOWN_FILTER_FIELD` — its indexes are read as field names |
| 400 | `UNKNOWN_FILTER_FIELD` | Filter by an unsupported field. Supported: `ID`, `AUTHOR_ID`, `AUTHOR_NAME`, `POST_DATE`. On the new card `AUTHOR_NAME` answers with `UNSUPPORTED_FILTER_FIELD` |
| 400 | `UNSUPPORTED_FILTER_FIELD` | New card only: filter by `AUTHOR_NAME`. Filter by `ID`, `AUTHOR_ID` or `POST_DATE` instead, an employee identifier by name — `GET /v1/users` |
| 403 | `SCOPE_DENIED` | The API key does not have the `task` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

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

## Known specifics

**Scan window on filtering.** On the new card a request with `filter` or a sort other than `ID` scans up to 2000 of the newest task chat messages, system notifications included, and picks the matching comments out of them. If the task history is longer, or is limited by the Bitrix24 account plan, `meta.truncated: true` arrives: comments that are not in the response stayed beyond the window edge, and `meta.total` counts only the ones inside it. This is not a sign of a next page — `offset` does not move the window. Narrow the selection with a `POST_DATE` or `AUTHOR_ID` filter. For the same reason `?sort=post_date:asc` on such a task returns the oldest comments within the window, not the oldest comments of the task.

**Filter and sort by author — via `AUTHOR_ID`.** The fields `AUTHOR_NAME` and `AUTHOR_EMAIL` are accepted on the old card and return `400` on the new one, so a request by author name does not work on every Bitrix24 account. To make the selection independent of how the Bitrix24 account is configured, find the employee via `GET /v1/users` and filter or sort by `AUTHOR_ID`.

**Empty page with `meta.hasMore: true`.** System notifications about task creation, deadline change and assignee change are filtered out on the API side. For a request without `filter` and with a sort by `ID`, if the entire current slice consists of them, `data` comes back empty with `meta.hasMore: true`. On this read path `meta.total` is an estimate, and in such a slice it comes back equal to `1` while `data` is empty. This is not an error: paginate by `meta.hasMore` and the contents of `data`, not by `meta.total` — request the next page or increase `limit`.

## See also

- [Get comment](./get.md) — a single record by `id`
- [Create comment](./create.md) — add a new one
- [Batch operations](./comments-batch.md) — add several in one call
- [Tasks](/docs/entities/tasks) — parent entity
- [Limits and optimization](/docs/optimization) — rate limits
