## Пересобрать набор карточек

`PUT /v1/pages/:pageId/blocks/:blockId/cards`

Заменяет ВСЁ содержимое родителя первой карточки: соседние элементы, которые не являются карточками, и другие наборы карточек внутри этого родителя будут удалены. Это поведение Б24. source перечисляет образцы из текущего набора: type card и value — индекс; type preset и value — ключ пресета из манифеста. values — объект групп правок, каждая группа содержит узлы с @N, где N — индекс среди всех узлов с этим селектором после пересборки. Пример создаёт две карточки с разными заголовками. Пустой source, неизвестный селектор или индекс дают 400 до записи. Для простых правок используйте clone/remove и PATCH nodes.

Требуется скоуп `landing`; READONLY-ключ получает 403 до записи. Блок проверяется на принадлежность странице.

Query `scope` необязателен: `KNOWLEDGE`, `GROUP` или `MAINPAGE` для соответствующей страницы; для обычного сайта пропустите. ID должны быть положительными целыми безопасными числами.

Развёрнутый HTML ограничен 8 МиБ; превышение даёт 413 до записи. null и неподдерживаемое содержимое текстового узла дают 400; неприменённый простой текст — 422. HTML санитайзит Б24.

## Примеры

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

```bash
curl -X PUT "https://vibecode.bitrix24.tech/v1/pages/42/blocks/50/cards" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"selector":".landing-block-card","source":[{"type":"card","value":0},{"type":"card","value":1}],"values":{"first":{".landing-block-node-title@0":"First"},"second":{".landing-block-node-title@1":"Second"}}}'
```

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

```javascript
const response = await fetch("https://vibecode.bitrix24.tech/v1/pages/42/blocks/50/cards", {
  method: "PUT",
  headers: {"X-Api-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
  body: JSON.stringify({"selector": ".landing-block-card", "source": [{"type": "card", "value": 0}, {"type": "card", "value": 1}], "values": {"first": {".landing-block-node-title@0": "First"}, "second": {".landing-block-node-title@1": "Second"}}}),
})
const result = await response.json()
if (!response.ok) throw new Error(result.error.message)
console.log(result.data)
```

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

```bash
curl -X PUT "https://vibecode.bitrix24.tech/v1/pages/42/blocks/50/cards" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"selector":".landing-block-card","source":[{"type":"card","value":0},{"type":"card","value":1}],"values":{"first":{".landing-block-node-title@0":"First"},"second":{".landing-block-node-title@1":"Second"}}}'
```

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

```javascript
const response = await fetch("https://vibecode.bitrix24.tech/v1/pages/42/blocks/50/cards", {
  method: "PUT",
  headers: {"X-Api-Key": "YOUR_APP_KEY", "Authorization": "Bearer USER_SESSION_TOKEN", "Content-Type": "application/json"},
  body: JSON.stringify({"selector": ".landing-block-card", "source": [{"type": "card", "value": 0}, {"type": "card", "value": 1}], "values": {"first": {".landing-block-node-title@0": "First"}, "second": {".landing-block-node-title@1": "Second"}}}),
})
const result = await response.json()
if (!response.ok) throw new Error(result.error.message)
console.log(result.data)
```

## Ответ

```json
{
  "success": true,
  "data": {
    "cards": {
      ".landing-block-card": [
        {
          "index": 0,
          "content": "<div class=\"landing-block-card\"><h3 class=\"landing-block-node-title\">First</h3></div>"
        },
        {
          "index": 1,
          "content": "<div class=\"landing-block-card\"><h3 class=\"landing-block-node-title\">Second</h3></div>"
        }
      ]
    }
  }
}
```

Отказ после записи не отменяет действие Б24. При 422/502 после вызова сначала перечитайте блок; повтор clone/add может создать ещё одну карточку.

## Ошибки

| HTTP | Code |
|---|---|
| 400 | INVALID_PARAMS / MISSING_REQUIRED_FIELDS / INVALID_SCOPE |
| 401 | MISSING_API_KEY / INVALID_API_KEY / TOKEN_MISSING |
| 403 | SCOPE_DENIED / WRITE_BLOCKED_READONLY_KEY / BITRIX_ACCESS_DENIED |
| 404 | ENTITY_NOT_FOUND |
| 409 | PORTAL_ADDRESS_CHANGED / LANDING_MODULE_NOT_ENABLED |
| 413 | PAYLOAD_TOO_LARGE |
| 422 | BITRIX_ERROR / BITRIX_NO_EFFECT |
| 429 | RATE_LIMITED |
| 502 | BITRIX_ERROR |
| 503 | SERVICE_UNAVAILABLE |
