## Список секций

`GET /v1/calendar-sections`

Возвращает все секции календаря для пары `type` + `ownerId`. У одного сотрудника может быть несколько секций — например, «Работа», «Личное», «Командные встречи».

## Параметры

| Параметр | Тип | Обяз. | По умолч. | Описание |
|----------|-----|:-----:|-----------|---------|
| `type` (query) | string | да | — | Тип календаря: `user` — личный, `group` — групповой, `company_calendar` — календарь компании, `location` — переговорная |
| `ownerId` (query) | number | да | — | Идентификатор владельца календаря. Для сотрудника — `GET /v1/users`, для рабочей группы — её id, для `type=location` — `0` |
| `limit` (query) | number | нет | `50` | Количество записей, до 5000. При `limit > 50` включается автопагинация |
| `offset` (query) | number | нет | `0` | Принимается, но не влияет на выборку — список возвращает все секции пары `type` + `ownerId` |

Фильтрация через `filter[...]` не поддерживается. Любой ключ `filter[name]=...` возвращает `400 UNSUPPORTED_FILTER` ещё до обращения к Битрикс24.

## Примеры

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

```bash
curl "https://vibecode.bitrix24.tech/v1/calendar-sections?type=user&ownerId=1" \
  -H "X-Api-Key: YOUR_API_KEY"
```

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

```bash
curl "https://vibecode.bitrix24.tech/v1/calendar-sections?type=user&ownerId=1" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

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

```javascript
const params = new URLSearchParams({ type: 'user', ownerId: '1' })
const res = await fetch(`https://vibecode.bitrix24.tech/v1/calendar-sections?${params}`, {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data, meta } = await res.json()
console.log(`Найдено ${meta.total} секций`)
```

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

```javascript
const params = new URLSearchParams({ type: 'user', ownerId: '1' })
const res = await fetch(`https://vibecode.bitrix24.tech/v1/calendar-sections?${params}`, {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

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

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data` | array | Массив секций |
| `meta.total` | number | Общее количество секций в выборке |
| `meta.hasMore` | boolean | Есть ли ещё записи за пределами `limit` |

Поля одной секции в массиве `data`:

| Поле | Тип | RO | Описание |
|------|-----|:--:|---------|
| `id` | number | да | Идентификатор секции |
| `name` | string | нет | Название |
| `description` | string | нет | Описание |
| `type` | string | нет | Тип календаря: `user`, `group`, `company_calendar`, `location` |
| `ownerId` | number | нет | Идентификатор владельца календаря |
| `color` | string | нет | Цвет секции в формате `#RRGGBB` |
| `textColor` | string | нет | Цвет текста в формате `#RRGGBB` |
| `export` | object | нет | Параметры экспорта в формате iCal: `{ "ALLOW": boolean, "SET": "all" \| "3_9" \| "6_12" }`. Ключи внутри объекта — в верхнем регистре, формат сохраняется на запись и чтение без преобразований |
| `access` | object | да | Карта прав доступа: ключ — идентификатор права доступа, значение — числовой идентификатор разрешения |
| `perm` | object | да | Карта разрешений текущего сотрудника: `view_time`, `view_title`, `view_full`, `add`, `edit`, `edit_section`, `access` |
| `isCollab` | boolean | да | Принадлежность к коллабе |
| `createdBy` | number | да | Идентификатор создателя секции |
| `dateCreate` | datetime | да | Дата создания |
| `updatedAt` | datetime | да | Дата последнего изменения |

«RO» — поле доступно только на чтение, передавать в `POST` / `PATCH` нельзя, иначе Вайбкод вернёт `400 READONLY_FIELD`.

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

```json
{
  "success": true,
  "data": [
    {
      "id": 42,
      "name": "Работа",
      "description": "Основной рабочий календарь",
      "type": "user",
      "ownerId": 1,
      "color": "#9cbeee",
      "textColor": "#283000",
      "export": {
        "ALLOW": true,
        "SET": "3_9"
      },
      "access": {
        "U1": "calendar_owner",
        "G2": 13
      },
      "perm": {
        "view_time": true,
        "view_title": true,
        "view_full": true,
        "add": true,
        "edit": true,
        "edit_section": true,
        "access": true
      },
      "isCollab": false,
      "createdBy": 1,
      "dateCreate": "2026-05-15T09:34:33+03:00",
      "updatedAt": "2026-05-15T09:34:33+03:00"
    }
  ],
  "meta": {
    "total": 1,
    "hasMore": false
  }
}
```

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

400 — не переданы обязательные `type` или `ownerId`:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_PARAMS",
    "message": "GET /v1/calendar-sections requires query parameters: type, ownerId. Example: GET /v1/calendar-sections?type=...&ownerId=..."
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_PARAMS` | Не переданы `type` или `ownerId` |
| 400 | `UNSUPPORTED_FILTER` | Передан ключ `filter[...]` — фильтрация не поддерживается. Допустимы только `type`, `ownerId`, `limit`, `offset` |
| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `calendar` |
| 401 | `TOKEN_MISSING` | У API-ключа нет настроенных токенов |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 временно недоступен — повторите запрос позже |

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

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

**`limit` обрезает выдачу на стороне API Вайбкод, `offset` не действует.** Список всегда возвращает все секции указанной пары `type` + `ownerId`. `limit` обрезает полученный массив до N записей, а `offset` принимается, но игнорируется — пропустить записи через него нельзя.

**Поле `export` сохраняет регистр Битрикс24.** Ключи внутри `export` остаются `ALLOW` и `SET` в верхнем регистре — не преобразуются к camelCase. То же при отправке через [`POST /v1/calendar-sections`](./create.md): передавайте именно `{ "ALLOW": true, "SET": "3_9" }`.

**Получить секцию по одному `id` через API нельзя.** Эндпоинт `GET /v1/calendar-sections/:id` не поддерживается. Чтобы найти одну секцию по `id` — получите список и отфильтруйте на стороне клиента: `data.find(s => s.id === 42)`.

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

- [Создать секцию](./create.md)
- [Обновить секцию](./update.md)
- [Удалить секцию](./delete.md)
- [Пакет операций](./batch.md)
- [События календаря](/docs/entities/calendar-events)
