## Пакет операций над секциями календаря

`POST /v1/calendar-sections/batch`

Массовое создание, обновление или удаление секций календаря одним запросом — до 500 элементов за вызов. Это отдельный эндпоинт сущности, не путать с [универсальным batch](/docs/batch), который объединяет операции разных сущностей и ограничен 50 вызовами.

## Поля запроса (body)

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|---------|
| `action` | string | да | Тип операции: `create`, `update` или `delete` |
| `items` | array | да при `create` и `update` | Список элементов, до 500. Для `create` — `[{ type, ownerId, name, color?, ... }]`. Для `update` — `[{ id, type, ownerId, name, ... }]`. Набор полей элемента совпадает с телом [`POST /v1/calendar-sections`](./create.md) и [`PATCH /v1/calendar-sections/:id`](./update.md) |
| `ids` | number[] | да при `delete` | Идентификаторы секций для удаления, до 500 |
| `type` | string | да при `delete` | Тип календаря, передаётся рядом с `ids`. Значения — `user`, `group`, `company_calendar`, `location` |
| `ownerId` | number | да при `delete` | Идентификатор владельца календаря, передаётся рядом с `ids`. Для `type=user` — `id` сотрудника из [`GET /v1/users`](/docs/entities/users), для `type=group` — `id` рабочей группы, для `type=location` — `0` |

Для `create` и `update` пара `type` + `ownerId` и поле `name` входят в каждый элемент `items`. Для `delete` `type` и `ownerId` общие для всего пакета и передаются на верхнем уровне рядом с `ids`.

## Примеры

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/calendar-sections/batch" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create",
    "items": [
      { "type": "user", "ownerId": 1, "name": "Командные встречи", "color": "#ff5b49" },
      { "type": "user", "ownerId": 1, "name": "Личное", "color": "#2fc6f6" }
    ]
  }'
```

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/calendar-sections/batch" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create",
    "items": [
      { "type": "user", "ownerId": 1, "name": "Командные встречи", "color": "#ff5b49" },
      { "type": "user", "ownerId": 1, "name": "Личное", "color": "#2fc6f6" }
    ]
  }'
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/calendar-sections/batch', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    action: 'create',
    items: [
      { type: 'user', ownerId: 1, name: 'Командные встречи', color: '#ff5b49' },
      { type: 'user', ownerId: 1, name: 'Личное', color: '#2fc6f6' },
    ],
  }),
})

const { data } = await res.json()
data.results.forEach((item) => {
  if (item.success) console.log(`#${item.index} → id=${item.id}`)
  else console.log(`#${item.index} → ошибка: ${item.error} ${item.message}`)
})
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/calendar-sections/batch', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    action: 'create',
    items: [
      { type: 'user', ownerId: 1, name: 'Командные встречи', color: '#ff5b49' },
      { type: 'user', ownerId: 1, name: 'Личное', color: '#2fc6f6' },
    ],
  }),
})

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

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

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true`, если запрос прошёл верхнеуровневую валидацию. Результат каждого элемента — в `data.results[i].success` |
| `data.results` | array | Массив результатов в том же порядке, что `items` или `ids` запроса |
| `data.results[].index` | number | Индекс элемента, начиная с `0` |
| `data.results[].success` | boolean | Результат этой операции |
| `data.results[].id` | number | Идентификатор секции при `create`, `update` и `delete` |
| `data.results[].error` | string | Код ошибки для упавшего элемента, `UNKNOWN` если код не определён. Может быть пустой строкой, если Битрикс24 прислал только текст без кода |
| `data.results[].message` | string | Текст ошибки для упавшего элемента |
| `data.summary.total` | number | Всего обработано элементов |
| `data.summary.succeeded` | number | Сколько выполнено успешно |
| `data.summary.failed` | number | Сколько завершилось ошибкой |

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

`action: create` — обе секции созданы:

```json
{
  "success": true,
  "data": {
    "results": [
      { "index": 0, "success": true, "id": 181 },
      { "index": 1, "success": true, "id": 183 }
    ],
    "summary": { "total": 2, "succeeded": 2, "failed": 0 }
  }
}
```

`action: update` — элемент без `type` завершился ошибкой, а верхний `success` остался `true`:

```json
{
  "success": true,
  "data": {
    "results": [
      {
        "index": 0,
        "success": false,
        "error": "",
        "message": "Не задан обязательный параметр \"type\" для метода \"calendar.section.update\""
      }
    ],
    "summary": { "total": 1, "succeeded": 0, "failed": 1 }
  }
}
```

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

400 — при `action: delete` не переданы `type` и `ownerId` рядом с `ids`:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_PARAMS",
    "message": "POST /v1/calendar-sections/batch { action: \"delete\" } requires type, ownerId alongside ids. Example: { \"action\": \"delete\", \"ids\": [...], \"type\": ..., \"ownerId\": ... }",
    "missing": ["type", "ownerId"]
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_PARAMS` | `action: delete` без `type` или `ownerId` рядом с `ids` |
| 400 | `INVALID_BATCH_ACTION` | `action` не является поддерживаемой операцией |
| 400 | `BATCH_ITEM_VALIDATION` | `items` или `ids` пустой либо не массив, или элемент `update` без `id` |
| 400 | `BATCH_LIMIT_EXCEEDED` | В запросе передано более 500 элементов |
| 403 | `SCOPE_DENIED` | Ключу не хватает скоупа `calendar` |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Ключ в режиме «только чтение» — запись запрещена |
| 403 | `MANAGEMENT_KEY_NO_ENTITY_ACCESS` | Использован management-ключ вместо ключа приложения |
| 401 | `TOKEN_MISSING` | У ключа нет настроенных токенов |

Ошибки отдельных элементов приходят внутри `data.results[i]` — поле `error` с кодом или пустой строкой и `message` с текстом.

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

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

**Верхний `success` остаётся `true`, если запрос прошёл верхнеуровневую валидацию.** Упавшие элементы не превращают весь ответ в ошибку — это позволяет обработать частичный результат. Перед использованием результата проверяйте `data.results[i].success` для каждого элемента, а сводку смотрите в `data.summary`.

**Пакетный `update` не дополняет `type`, `ownerId` и `name` из существующей секции.** В отличие от одиночного [`PATCH /v1/calendar-sections/:id`](./update.md), который подставляет эти поля сам, в пакете их нужно передать в каждом элементе `items`. Без них элемент завершается ошибкой, а остальные продолжают обрабатываться.

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

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