## Список обращений

`GET /v1/feedback`

Возвращает список обращений с фильтрами и пагинацией. Обычный ключ видит только свои обращения (отправленные этим же ключом), ключ со скоупом `vibe:feedback` — все обращения своего портала.

## Параметры

| Параметр | Тип | Обяз. | По умолч. | Описание |
|----------|-----|:-----:|-----------|----------|
| `status` (query) | string | нет | — | `NEW`, `REVIEWING`, `AWAITING_USER`, `NEEDS_REVIEW`, `RESOLVED`, `ARCHIVED`, `WITHDRAWN`. Регистр не важен |
| `category` (query) | string | нет | — | `BUG`, `SUGGESTION`, `DOCS`, `CHAT`, `BOTS`, `OTHER`. Регистр не важен |
| `offset` (query) | number | нет | `0` | Сколько записей пропустить |
| `page` (query) | number | нет | `1` | Постраничная пагинация. Используется, когда `offset` не задан |
| `limit` (query) | number | нет | `20` | Размер страницы, от 1 до 100 |
| `filter[status]`, `filter[category]` (query) | string | нет | — | Те же два фильтра в скобочной форме |

Для листания используйте `offset` — например `offset=100&limit=50`. Поле `offset` в ответе повторяет применённое смещение. Если `offset` не передан, работает `page`.

Фильтры `status` и `category` регистронезависимы (`status=new` равнозначно `status=NEW`). Неизвестное значение возвращает `400 INVALID_FILTER_VALUE` — опечатка в фильтре отклоняется явно, а не приводит к выдаче всего списка.

Те же два фильтра принимаются в скобочной форме: `filter[status]=NEW&filter[category]=BUG`. Проверка та же — регистр не важен, неизвестное значение возвращает `400 INVALID_FILTER_VALUE`. Если в запросе есть обе формы, применяется плоская. Значение, которое не является одиночным (`filter[status][]=NEW`), тоже отклоняется с `400 INVALID_FILTER_VALUE`.

## Примеры

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

```bash
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://vibecode.bitrix24.tech/v1/feedback?status=NEW&category=BUG&limit=20"
```

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

```bash
curl -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  "https://vibecode.bitrix24.tech/v1/feedback?status=NEW&category=BUG&limit=20"
```

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

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.tech/v1/feedback?status=NEW&category=BUG&limit=20',
  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
)
const { data, total } = await res.json()
```

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

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.tech/v1/feedback?status=NEW&category=BUG&limit=20',
  { headers: { 'X-Api-Key': 'YOUR_APP_KEY', 'Authorization': 'Bearer USER_SESSION_TOKEN' } },
)
const { data, total } = await res.json()
```

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

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | Всегда `true` при успехе |
| `data` | array | Массив обращений |
| `data[].id` | string | UUID обращения |
| `data[].category` | string | Категория |
| `data[].title` | string | Заголовок |
| `data[].body` | string | Описание |
| `data[].status` | string | Текущий статус |
| `data[].source` | string | `api` или `ui` |
| `data[].resolution` | string · null | Вердикт, записанный при последнем закрытии обращения. Пусто, если обращение ни разу не закрывали. Переоткрытие вердикт сохраняет, поэтому поле бывает заполнено и на активном обращении — за последним ответом команды идите в ленту комментариев |
| `data[].attachmentCount` | number | Количество вложений |
| `data[].createdAt` | string | Дата создания (ISO 8601) |
| `data[].resolvedAt` | string · null | Дата закрытия, если есть |
| `total` | number | Общее количество записей под фильтром |
| `page` | number | Текущая страница |
| `limit` | number | Размер страницы |
| `offset` | number | Применённое смещение |

Ключ со скоупом `vibe:feedback` дополнительно получает в каждой записи поля `portalDomain`, `userName`, `userId`, `apiKeyId` — кто и с какого ключа отправил обращение.

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

```json
{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-1111-2222-3333-444455556666",
      "category": "BUG",
      "title": "POST /v1/deals/search возвращает 500 при пустом filter",
      "body": "При вызове POST /v1/deals/search с телом {\"filter\":{}} приходит 500.",
      "status": "NEW",
      "source": "api",
      "resolution": null,
      "attachmentCount": 0,
      "createdAt": "2026-04-19T10:30:00.000Z",
      "resolvedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20,
  "offset": 0
}
```

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

400 — неизвестное значение фильтра:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_FILTER_VALUE",
    "message": "Invalid status 'BOGUS'. Allowed values: NEW, REVIEWING, AWAITING_USER, NEEDS_REVIEW, RESOLVED, ARCHIVED, WITHDRAWN."
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `INVALID_FILTER_VALUE` | Передано неизвестное значение `status` или `category` |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |

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

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

- [Получить обращение](/docs/feedback/get)
- [Отправить обращение](/docs/feedback/submit)
- [Обратная связь](/docs/feedback)
- [Ошибки](/docs/errors)
