## Save a block to "My blocks"

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

Saves a page block as a template in the "My blocks" section of the Bitrix24 account block catalog. Every editor of the account sees the template — it is not a personal bookmark.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|----------|
| `pageId` (path) | number | yes | Page ID. List: [`GET /v1/pages`](/docs/entities/pages/list) |
| `blockId` (path) | number | yes | ID of the block on this page that becomes the template. List: [`GET /v1/pages/:pageId/blocks`](/docs/entities/pages/blocks/list). A block from another page returns `404` |
| `scope` (query) | string | no | Internal landing scope: `KNOWLEDGE` — knowledge base, `GROUP` — group knowledge base, `MAINPAGE` — home page. Omit for a regular site |

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|----------|
| `name` | string | yes | Template name in "My blocks". An empty string or a whitespace-only string is rejected |
| `sections` | array of string | no | Catalog sections the template goes into, for example `["text"]`. Section codes are the `data` keys in the [`GET /v1/block-repository`](/docs/entities/pages/catalog) response. An empty array `[]` is accepted, empty strings in the array are not |

## Examples

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/pages/42/blocks/50/favorite" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Reusable block","sections":["text"]}'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/pages/42/blocks/50/favorite" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Reusable block","sections":["text"]}'
```

### JavaScript — personal key

```javascript
const response = await fetch("https://vibecode.bitrix24.com/v1/pages/42/blocks/50/favorite", {
  method: "POST",
  headers: {"X-Api-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
  body: JSON.stringify({"name": "Reusable block", "sections": ["text"]}),
})
const result = await response.json()
if (!response.ok) throw new Error(result.error.message)
console.log(result.data)
```

### JavaScript — OAuth application

```javascript
const response = await fetch("https://vibecode.bitrix24.com/v1/pages/42/blocks/50/favorite", {
  method: "POST",
  headers: {"X-Api-Key": "YOUR_APP_KEY", "Authorization": "Bearer USER_SESSION_TOKEN", "Content-Type": "application/json"},
  body: JSON.stringify({"name": "Reusable block", "sections": ["text"]}),
})
const result = await response.json()
if (!response.ok) throw new Error(result.error.message)
console.log(result.data)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data.blockId` | number | Template ID in "My blocks". Differs from the source block's `blockId` in the path. Pass this ID to [template deletion](/docs/entities/block-repository/favorites/delete) |
| `data.code` | string | Template code in the form `sourceCode@blockId`. The template appears in the [block catalog](/docs/entities/pages/catalog) under this code |

## Response example

```json
{
  "success": true,
  "data": {
    "blockId": 29441,
    "code": "03.1.three_cols_big_with_text_and_titles@29441"
  }
}
```

## Error response example

400 — template name not provided:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_FIELDS",
    "message": "name is required."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `MISSING_REQUIRED_FIELDS` | `name is required.` — `name` is missing, empty or whitespace-only |
| 400 | `INVALID_PARAMS` | `sections must be an array of non-empty strings.` — `sections` is not an array, or the array contains a non-string, an empty string or a whitespace-only string |
| 400 | `INVALID_PARAMS` | `Body contains an unsupported field.` — the body has a field other than `name` and `sections`, for example `preview` |
| 404 | `ENTITY_NOT_FOUND` | `Page, block or card not found.` — the block does not belong to page `pageId` or does not exist |
| 400 | `INVALID_PARAMS` | `pageId and blockId must be positive safe integers.` — `pageId` or `blockId` is not a positive integer |
| 400 | `INVALID_PARAMS` | `Body must be a JSON object.` — the body is not a JSON object |
| 400 | `INVALID_SCOPE` | `scope` is not `KNOWLEDGE`, `GROUP` or `MAINPAGE` |
| 422 | `BITRIX_NO_EFFECT` | `Bitrix24 did not return a saved block ID.` — Bitrix24 did not return the ID of the saved template |
| 422 | `BITRIX_ERROR` | Bitrix24 rejected the action. The error text comes from Bitrix24 |
| 502 | `BITRIX_ERROR` | `Bitrix24 returned an invalid block code.` — the source block has no catalog block code |
| 403 | `SCOPE_DENIED` | The API key does not have the `landing` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only, the request is rejected before reaching Bitrix24 |
| 403 | `BITRIX_ACCESS_DENIED` | The Bitrix24 user the key was issued for has no permission for this action |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | The key in `X-Api-Key` was not found or has been revoked |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 409 | `LANDING_MODULE_NOT_ENABLED` | The Sites module is not available on the Bitrix24 account |
| 409 | `PORTAL_ADDRESS_CHANGED` | The on-premise Bitrix24 moved to a new address, while the key webhook was issued for the old one. Reissue the key webhook |
| 429 | `RATE_LIMITED` | Bitrix24 request limit exceeded. Retry in 1-2 seconds |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 did not respond or returned a server error |
| 503 | `BITRIX_TIMEOUT` | Bitrix24 did not respond in time |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

- **Every call creates a new template.** Repeating the call with the same block and the same name does not update the previous template — it adds another one with a new `blockId`. Delete unneeded templates with [`DELETE /v1/block-repository/favorites/:blockId`](/docs/entities/block-repository/favorites/delete).
- **The source block does not change.** The template is a copy of the block at the time of the call. Later edits to the block on the page do not reach the template.

## See also

- [Saved blocks](/docs/entities/block-repository)
- [Delete a template from "My blocks"](/docs/entities/block-repository/favorites/delete)
- [Block catalog](/docs/entities/pages/catalog)
- [Page block list](/docs/entities/pages/blocks/list)
