## Добавить блок на страницу

`POST /v1/pages/:pageId/blocks`

Добавляет на страницу лендинга блок из каталога блоков портала — с разметкой из каталога или со своей.

Поля передаются плоско в корне JSON, без обёртки `fields`. Работа со страницами и их блоками — в разделе [Страницы](/docs/entities/pages).

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|---------|
| `pageId` (path) | number | да | ID страницы. Список: [`GET /v1/pages`](/docs/entities/pages/list) |
| `scope` (query) | string | нет | Раздел Битрикс24, к которому относится страница: `KNOWLEDGE` — база знаний, `GROUP` — база знаний группы, `MAINPAGE` — главная страница. Для страницы обычного сайта не передаётся |

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

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|---------|
| `code` | string | да | Код блока из каталога. Каталог: [`GET /v1/block-repository`](/docs/entities/pages/catalog), код — ключ элемента в `items` раздела |
| `afterId` | number | нет | ID блока этой страницы, после которого встанет новый блок. Список: [`GET /v1/pages/:pageId/blocks`](/docs/entities/pages/blocks/list). Без поля новый блок встаёт первым на странице |
| `active` | boolean | нет | Видимость блока. `false` — блок создаётся скрытым. По умолчанию блок видим. Принимаются также строки `"true"`, `"false"`, `"1"`, `"0"` и числа `1`, `0` |
| `content` | string | нет | HTML-разметка блока вместо разметки из каталога. Без поля блок получает разметку из каталога |

## Примеры

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/pages/20/blocks" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "03.1.three_cols_big_with_text_and_titles",
    "afterId": 30,
    "content": "<section class=\"landing-block\"><div class=\"container\"><h2>Hello</h2></div></section>"
  }'
```

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

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/pages/20/blocks" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "03.1.three_cols_big_with_text_and_titles",
    "afterId": 30,
    "content": "<section class=\"landing-block\"><div class=\"container\"><h2>Hello</h2></div></section>"
  }'
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/pages/20/blocks', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    code: '03.1.three_cols_big_with_text_and_titles',
    afterId: 30,
    content: '<section class="landing-block"><div class="container"><h2>Hello</h2></div></section>',
  }),
})

const { success, data } = await res.json()
console.log('Block ID:', data.id)
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/pages/20/blocks', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    code: '03.1.three_cols_big_with_text_and_titles',
    afterId: 30,
    content: '<section class="landing-block"><div class="container"><h2>Hello</h2></div></section>',
  }),
})

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

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

| Поле | Тип | Описание |
|------|-----|---------|
| `id` | number | ID созданного блока в черновике страницы. Подходит для [`PATCH /v1/pages/:pageId/blocks/:blockId`](/docs/entities/pages/blocks/update) и [`DELETE /v1/pages/:pageId/blocks/:blockId`](/docs/entities/pages/blocks/delete) |
| `version` | string | Версия страницы, в которую добавлен блок. Всегда `draft` — черновик |
| `published` | boolean | Опубликовано ли изменение. Всегда `false` |
| `publishWith` | string | Вызов, который публикует страницу вместе с новым блоком, с подставленным ID страницы |

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

```json
{
  "success": true,
  "data": {
    "id": 32,
    "version": "draft",
    "published": false,
    "publishWith": "POST /v1/pages/20/publication"
  }
}
```

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

422 — кода блока нет в каталоге:

```json
{
  "success": false,
  "error": {
    "code": "BLOCK_CANT_BE_ADDED",
    "message": "Bitrix24 refused to add this block. Check that `code` is a code from GET /v1/block-repository."
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `MISSING_BLOCK_CODE` | Не передан `code` или передана пустая строка |
| 400 | `INVALID_AFTER_ID` | `afterId` не является положительным целым числом |
| 400 | `INVALID_ACTIVE` | `active` не является логическим значением |
| 400 | `INVALID_CONTENT` | `content` передан не строкой |
| 400 | `INVALID_PAGE_ID` | `pageId` в пути не является положительным целым числом |
| 400 | `INVALID_SCOPE` | `scope` не равен `KNOWLEDGE`, `GROUP` или `MAINPAGE` |
| 400 | `INVALID_PARAMS` | Битрикс24 отклонил запрос: не хватает обязательного параметра |
| 404 | `ENTITY_NOT_FOUND` | Страницы нет или она не видна ключу. Для страницы базы знаний, группы или главной страницы нужен `scope` |
| 422 | `BLOCK_CANT_BE_ADDED` | Битрикс24 отказался добавить блок: кода `code` нет в каталоге |
| 422 | `BLOCK_WRONG_VERSION` | Блок каталога требует более новой версии модуля сайтов, чем установлена на портале |
| 502 | `BLOCK_ADD_UNCONFIRMED` | Битрикс24 не вернул ID нового блока — создание не подтверждено |
| 403 | `BITRIX_ACCESS_DENIED` | У сотрудника, под которым выпущен ключ, нет прав на страницу в Битрикс24 |
| 422 | `BITRIX_ERROR` | Битрикс24 отклонил запрос, текст ошибки — в `message` |
| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `landing` |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Ключ в режиме «только чтение» |
| 401 | `TOKEN_MISSING` | API-ключ не имеет настроенных токенов |

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

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

**Разметка возвращается в обёртке.** Чтение [`GET /v1/pages/:pageId/blocks?content=true`](/docs/entities/pages/blocks/list) отдаёт разметку из `content` внутри элемента `<div id="b<id>" class="block-wrapper block-<код>">`. В классе обёртки точки и подчёркивания кода блока заменены дефисами: для `03.1.three_cols_big_with_text_and_titles` это `block-03-1-three-cols-big-with-text-and-titles`.

**Несуществующий `afterId` не отклоняется.** Если блока с таким ID на странице нет, блок всё равно создаётся с ответом `201`, но встаёт не первым и не в конец, а в другое место страницы. Перед вызовом берите `afterId` из [списка блоков](/docs/entities/pages/blocks/list), а после вызова проверьте позицию нового блока тем же списком.

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

- [Список блоков страницы](/docs/entities/pages/blocks/list)
- [Заменить разметку блока](/docs/entities/pages/blocks/update)
- [Удалить блок](/docs/entities/pages/blocks/delete)
- [Восстановить блок](/docs/entities/pages/blocks/restore)
- [Каталог блоков](/docs/entities/pages/catalog)
- [Опубликовать блок](/docs/entities/pages/block-publication)
- [Страницы](/docs/entities/pages)
