
## Список комментариев

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

Возвращает комментарии конкретной задачи. На новой карточке задачи список читается из чата, системные сообщения отфильтрованы. На старой — из блока комментариев в самой карточке.

## Параметры

| Параметр | Тип | Обяз. | По умолч. | Описание |
|----------|-----|:-----:|-----------|---------|
| `taskId` (path) | number | да | — | ID родительской задачи |
| `limit` (query) | number | | `50` | Размер страницы (до 200) |
| `offset` (query) | number | | `0` | Сколько подошедших комментариев пропустить перед выдачей. Учитывается на новой карточке при запросе с `filter` или сортировкой не по `ID`, на остальных путях чтения игнорируется |
| `sort` (query) | string | | `id:desc` | Сортировка: поле `ID`, `AUTHOR_ID` или `POST_DATE` и направление `asc` либо `desc` — `?sort=post_date:desc`. Имя поля регистронезависимо; принимаются и camelCase-имена `id`, `authorId`, `authorName`, `createdAt`, `authorEmail`. Сортировка по `AUTHOR_NAME` и `AUTHOR_EMAIL` принимается только на старой карточке, на новой возвращает `400 UNSUPPORTED_SORT_FIELD` |
| `filter` (query) | object | | — | Фильтр по полям `ID`, `AUTHOR_ID`, `POST_DATE`. Принимаются и camelCase-имена `id`, `authorId`, `authorName`, `createdAt`. Передаётся как JSON: `?filter={"AUTHOR_ID":1}`. Перед именем поля допустим префикс `!`, `>`, `>=`, `<` или `<=` — `?filter={">=POST_DATE":"2026-05-01T00:00:00Z"}`. Значение для `POST_DATE` — дата ISO 8601 в UTC, несколько полей объединяются по «и». Фильтр по `AUTHOR_NAME` принимается только на старой карточке, на новой возвращает `400 UNSUPPORTED_FILTER_FIELD` |

## Примеры

### curl — личный ключ

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

### curl — OAuth-приложение

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

### JavaScript — личный ключ

```javascript
const url = 'https://vibecode.bitrix24.tech/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(`Получено ${data.length} комментариев`)
```

### JavaScript — OAuth-приложение

```javascript
const url = 'https://vibecode.bitrix24.tech/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()
```

## Поля ответа

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data` | array | Массив комментариев |
| `data[].id` | number | Идентификатор комментария |
| `data[].taskId` | number | ID родительской задачи |
| `data[].authorId` | number | Автор. Профиль: `GET /v1/users/:authorId` |
| `data[].message` | string | Текст комментария (поддерживает BB-код) |
| `data[].createdAt` | datetime | Дата создания (UTC ISO 8601) |
| `meta.total` | number | Количество комментариев. На новой карточке при запросе с `filter` или сортировкой не по `ID` — точное число подошедших под фильтр в пределах просмотренного окна, на остальных путях чтения — оценка |
| `meta.hasMore` | boolean | Есть ли ещё комментарии за пределами `limit` |
| `meta.truncated` | boolean | Приходит только со значением `true` и только на новой карточке при запросе с `filter` или сортировкой не по `ID`: просмотрено предельное окно, и часть комментариев осталась за его границей |

## Пример ответа

```json
{
  "success": true,
  "data": [
    {
      "id": 36559,
      "taskId": 289,
      "authorId": 1,
      "message": "Добавил черновик отчёта в комментарии — посмотри, пожалуйста.",
      "createdAt": "2026-05-13T12:30:58.000Z"
    },
    {
      "id": 36557,
      "taskId": 289,
      "authorId": 79,
      "message": "[USER=99]Зуля[/USER], готово, спасибо.",
      "createdAt": "2026-05-12T15:11:04.000Z"
    }
  ],
  "meta": {
    "total": 2,
    "hasMore": false
  }
}
```

## Пример ответа при ошибке

400 — `taskId` не положительное целое:

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

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | `taskId` некорректен (не целое положительное число) |
| 400 | `INVALID_SORT_FIELD` | Сортировка по неподдерживаемому полю или направлению. Поддерживаются `ID`, `AUTHOR_ID`, `AUTHOR_NAME`, `AUTHOR_EMAIL`, `POST_DATE` и их camelCase-имена, с направлением `asc` или `desc`. На новой карточке `AUTHOR_NAME` и `AUTHOR_EMAIL` отвечают `UNSUPPORTED_SORT_FIELD` |
| 400 | `UNSUPPORTED_SORT_FIELD` | Только новая карточка: сортировка по `AUTHOR_NAME` или `AUTHOR_EMAIL`. Отсортируйте по `ID`, `AUTHOR_ID` или `POST_DATE` |
| 400 | `INVALID_FILTER` | Параметр `filter` не является корректным JSON либо называет одно поле дважды в разных написаниях имени или знака равенства, например `{"AUTHOR_ID":1,"authorId":2}` или `{"AUTHOR_ID":1,"=authorId":2}`. Только новая карточка: `filter` — скаляр или пустой массив вместо объекта (`0`, `false`, `""`, `[]`), значение поля `ID` или `AUTHOR_ID` не число, значение `POST_DATE` не разбирается как дата, либо значение поля — объект или массив вместо скаляра. Непустой массив или непустая строка в `filter` дают `UNKNOWN_FILTER_FIELD` — их индексы разбираются как имена полей |
| 400 | `UNKNOWN_FILTER_FIELD` | Фильтр по неподдерживаемому полю. Поддерживаются `ID`, `AUTHOR_ID`, `AUTHOR_NAME`, `POST_DATE` и их camelCase-имена. На новой карточке `AUTHOR_NAME` отвечает `UNSUPPORTED_FILTER_FIELD` |
| 400 | `UNSUPPORTED_FILTER_FIELD` | Только новая карточка: фильтр по `AUTHOR_NAME`. Отфильтруйте по `ID`, `AUTHOR_ID` или `POST_DATE`, идентификатор сотрудника по имени — `GET /v1/users` |
| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `task` |
| 401 | `TOKEN_MISSING` | API-ключ не имеет настроенных токенов |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Окно просмотра при фильтрации.** На новой карточке запрос с `filter` или сортировкой не по `ID` просматривает до 2000 самых новых сообщений чата задачи, включая системные уведомления, и отбирает подошедшие комментарии из них. Если история задачи длиннее или ограничена тарифом портала, приходит `meta.truncated: true`: за границей окна остались комментарии, которых нет в ответе, а `meta.total` считает только попавшие в окно. Это не признак следующей страницы — `offset` окно не сдвинет. Сузьте выборку фильтром по `POST_DATE` или `AUTHOR_ID`. По той же причине `?sort=post_date:asc` на такой задаче вернёт самые старые комментарии в пределах окна, а не самые старые в задаче.

**Фильтр и сортировка по автору — через `AUTHOR_ID`.** Поля `AUTHOR_NAME` и `AUTHOR_EMAIL` принимаются на старой карточке и возвращают `400` на новой, поэтому запрос по имени автора работает не на каждом портале. Чтобы выборка не зависела от того, как настроен портал, найдите сотрудника через `GET /v1/users` и фильтруйте или сортируйте по `AUTHOR_ID`.

**Пустая страница при `meta.hasMore: true`.** Системные уведомления о постановке задачи, смене срока и назначении исполнителя отфильтровываются на стороне API. На запросе без `filter` и с сортировкой по `ID`, если весь текущий срез состоит из них, `data` приходит пустым при `meta.hasMore: true`. На этом пути чтения `meta.total` — оценка, и в таком срезе она приходит равной `1` при пустом `data`. Это не ошибка: ведите пагинацию по `meta.hasMore` и содержимому `data`, а не по `meta.total` — запросите следующую страницу или увеличьте `limit`.

## Смотрите также

- [Получить комментарий](./get.md)
- [Создать комментарий](./create.md)
- [Пакет операций](./comments-batch.md)
- [Задачи](/docs/entities/tasks)
- [Лимиты и оптимизация](/docs/optimization)
