## Кампании ревью

`GET /v1/performan/review/campaigns`

Возвращает кампании перформанс-ревью, в которых участвует владелец ключа. Навигация по выдаче курсорная, необязательный параметр сужает выдачу до одной кампании.

## Параметры

| Параметр | Тип | Обяз. | По умолч. | Описание |
|----------|-----|:-----:|-----------|----------|
| `campaignId` (query) | number | нет | — | Сузить выдачу до одной кампании. Идентификатор кампании, положительное целое |
| `limit` (query) | number | нет | 50 | Записей на страницу, максимум 200 |
| `afterCursorId` (query) | number | нет | — | Курсор следующей страницы. Значение берётся из `meta.nextCursor.id` предыдущего ответа. В первом запросе не передаётся |

## Навигация

1. Первый запрос идёт без `afterCursorId` — приходит первая страница.
2. Значение `meta.nextCursor.id` из ответа передаётся параметром `afterCursorId` следующего запроса. Курсор копируется целиком, собирать его из полей записи нельзя.
3. Ответ, у которого `meta.nextCursor` равен `null`, означает конец выдачи. Параметра `offset` и общего количества записей у метода нет.

## Примеры

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

```bash
curl "https://vibecode.bitrix24.tech/v1/performan/review/campaigns?limit=20" \
  -H "X-Api-Key: YOUR_API_KEY"
```

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

```bash
curl "https://vibecode.bitrix24.tech/v1/performan/review/campaigns?limit=20" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/performan/review/campaigns?limit=20', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const body = await res.json()

if (!body.success) {
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

for (const campaign of body.data) {
  console.log(campaign.id, campaign.title, campaign.status)
}

// Следующая страница: id курсора кладём в afterCursorId нового запроса
console.log(body.meta.nextCursor)
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/performan/review/campaigns?limit=20', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const body = await res.json()

if (!body.success) {
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

console.log(body.data, body.meta.nextCursor)
```

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

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data` | array | Массив кампаний |
| `data[].id` | number | Идентификатор кампании. Передаётся в параметр `campaignId` остальных методов раздела |
| `data[].title` | string | Название кампании |
| `data[].status` | string | Состояние кампании: `created` — создана, `inProgress` — идёт, `finished` — завершена |
| `data[].startDate` | string | Дата начала, ISO 8601 |
| `data[].endDate` | string | Дата окончания, ISO 8601 |
| `data[].createdAt` | string | Когда кампания создана, ISO 8601 |
| `meta.nextCursor` | object \| null | Курсор следующей страницы. `null` — записей больше нет |
| `meta.nextCursor.id` | number | Значение для параметра `afterCursorId` следующего запроса |

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

```json
{
  "success": true,
  "data": [
    {
      "id": 2,
      "title": "Оценка за четвёртый квартал",
      "status": "created",
      "startDate": "2026-10-01T09:00:00+00:00",
      "endDate": "2026-12-15T09:00:00+00:00",
      "createdAt": "2026-09-20T11:14:02+00:00"
    },
    {
      "id": 1,
      "title": "Оценка за третий квартал",
      "status": "finished",
      "startDate": "2026-06-01T09:00:00+00:00",
      "endDate": "2026-08-31T09:00:00+00:00",
      "createdAt": "2026-05-25T08:40:11+00:00"
    }
  ],
  "meta": { "nextCursor": { "id": 1 } }
}
```

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

400 — параметр не прошёл проверку:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "`limit` must be an integer between 1 and 200; `afterCursorId` a positive integer (pass back meta.nextCursor.id)"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | Значение `campaignId` или `afterCursorId` не является положительным целым числом либо `limit` выходит за диапазон 1–200 |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `TOKEN_MISSING` | У ключа нет токенов портала. Ключ OAuth-приложения требует заголовок `Authorization: Bearer` |
| 403 | `SCOPE_DENIED` | У ключа нет скоупа `performan` |
| 404 | `ROUTE_NOT_FOUND` | Раздел «Перформанс ревью» порталу не включён. Ответ неотличим от ответа на любой несуществующий адрес |
| 404 | `ENTITY_NOT_FOUND` | Раздел включён, но модуля «Перформанс ревью» на портале нет: Битрикс24 отвечает «Метод `performan.review.*` не найден» |
| 403 | `BITRIX_ACCESS_DENIED` | Битрикс24 отказал в доступе. Набор прав, с которым ключ обращается к порталу, не содержит `performan` |
| 409 | `PERFORMAN_SCOPE_JUST_GRANTED` | Ключу Коворка выдан скоуп `performan` этим же запросом. Повторите запрос — он пройдёт |
| 422 | `BITRIX_ERROR` | Битрикс24 отклонил запрос. Причина — в `error.message`, машинный код Битрикс24 — в `error.b24Code` |
| 429 | `RATE_LIMITED` | Превышена частота запросов на стороне Битрикс24 |
| 429 | `QUEUE_OVERFLOW`, `QUEUE_TIMEOUT` | Очередь запросов портала переполнена или запрос не дождался очереди. Заголовок `Retry-After` подсказывает задержку |
| 503 | `BITRIX_TIMEOUT` | Битрикс24 принял запрос, но не ответил за отведённое время. Для чтения повтор безопасен |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 недоступен |

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

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

**Неизвестные параметры строки запроса игнорируются.** Метод читает `campaignId`, `limit` и `afterCursorId`, остальные отбрасывает без ошибки: запрос с опечаткой в имени параметра отвечает `200` и несуженным списком. Так, `revieweeUserId` сужает выдачу только у [карточек менеджерского ревью](/docs/performan/manager-reviews) — на остальных списках он молча отбрасывается.

**Выдача ограничена участием владельца ключа.** Метод отдаёт кампании, в которых сотрудник числится участником, а не все кампании портала. Пустой массив `data` означает, что у этого сотрудника кампаний нет. Администратор портала получает такой же срез.

**Общего количества кампаний метод не возвращает.** Чтобы узнать число записей, нужно пройти все страницы по курсору.

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

- [Карточки самооценки](/docs/performan/self-reviews)
- [Карточки менеджерского ревью](/docs/performan/manager-reviews)
- [Операции перформанс-ревью](/docs/performan/endpoints)
- [Ошибки](/docs/errors)
