---
id: collections-post-id-group
title: "POST /api/collections/:id/group"
domain: collections
kind: api-method
http: "POST /api/collections/:id/group"
---

# POST /api/collections/:id/group {#collections-post-id-group}

## Сводка

| Поле | Значение |
|---|---|
| **HTTP** | `POST /api/collections/:id/group` |
| **Auth** | `—` |
| **Scope токена** | `read_write` |
| **PG-функции** | `api.group_collection_blocks` |
| **Таблицы** | `collection_block`, `collection_edge`, `generation_job` |
| **SRM** | SRM-365 |
| **RP (права)** | — |
| **Файл роута** | `server/routes/collections.js` |
| **Статус** | done |

**Аргументы запроса** (best-effort из хендлера; путь-параметры опущены):

| Аргумент | Где | Обяз. | Заметка |
|---|---|---|---|
| `block_ids` | body | | _подтвердить_ |
| `guidance` | body | | _подтвердить_ |
| `mode` | query | | _подтвердить_ |

**Коды ответов/ошибок** (из хендлера): `202`, `400`, `429`, `500` (+ `200`) — _уточнить причины вручную_

**Scope токена:** `read_write`. Требует прав collection admin (как декомпозиция).

Объединяет N блоков коллекции в один новый (recompose, N→1). Модель пишет ТОЛЬКО метаданные нового блока (имя, описание, слой, специальности, тип реализации) — всегда в режиме fast. Связи разводятся механически, без модели: внешнее ребро группы перевешивается на новый блок с сохранением направления соседа; ребро внутри группы отбрасывается; дубликаты схлопываются, петли исключаются. PG-функция `api.group_collection_blocks` атомарно удаляет N блоков (их рёбра снимаются каскадом) и вставляет один блок с перевешенными рёбрами под единым `op_id`. Операция обратима через `POST /api/collections/:id/undo` (Фаза 2).

**Риск:** `COSTLY_LLM` (op `COLLECTION_BLOCK_GROUP`). Для Bearer-токена глобальный confirm-гейт требует `{"confirm": true}` в теле — иначе `409` (гейт срабатывает до открытия SSE / постановки в очередь).

**Тело запроса** (`Content-Type: application/json`):

| Аргумент | Тип | Обяз. | Описание |
|---|---|---|---|
| `block_ids` | string[] | да | ID группируемых блоков, минимум 2 (иначе `400`) |
| `guidance` | string | нет | Ориентир для LLM: как назвать/описать объединённый блок |
| `confirm` | boolean | да (агент) | `{"confirm": true}` — иначе confirm-гейт вернёт `409` |

Pro-режима нет — группировка всегда fast.

**Query-параметры:**

| Параметр | Описание |
|---|---|
| `mode=async` | Асинхронный режим (только с Bearer-токеном). Возвращает `202 {job_id, poll}` — опрашивать через `GET /api/collections/:id/jobs/:jobId` (job-kind `collection_block_group`) |

**Заголовки:**

| Заголовок | Описание |
|---|---|
| `If-Match: <updated_at>` | Защита от TOCTOU. Если коллекция изменилась с момента снятия снимка — `412 Precondition Failed` (ранний `guardIfMatch`; PG-backstop `STALE` P0021 → `412` / SSE ошибка `{code:"stale"}`) |

**Режим SSE (без `?mode=async`):**

Ответ — поток `text/event-stream`. События:
- `stage` — прогресс (`{stage:"loading"|"generating"|"saving", status:"started"|"done"}`)
- `complete` — успех: `{removed_ids, new_block, edges, report}`
- `error` — ошибка (`{code:"stale"}` при If-Match fail; `{code:...}` при LLM-/валид.-ошибке, `422` при <2 блоков)

**Режим async:**

```
POST /api/collections/{id}/group?mode=async
Authorization: Bearer <token>
If-Match: <updated_at>
Content-Type: application/json

{"block_ids": ["b1", "b2", "b3"], "guidance": "Назови по итоговому результату", "confirm": true}
```

Ответ `202`:
```json
{"job_id": "uuid", "poll": "/api/collections/{id}/jobs/{job_id}"}
```

**Коды ошибок:** `409` — нужен `{"confirm": true}` (confirm-гейт); `400` — меньше 2 блоков в `block_ids`; `412` — конфликт `If-Match` / `STALE`; `403` — нет прав collection admin; `404` — коллекция не найдена (или в корзине); `429` — очередь async переполнена.

<!-- gen:start:related -->
## Связанные
- Экраны: [Редактор коллекции](../screens/collection-editor.md#collections-screen-collection-editor)
- [Конвенции](../../../shared/conventions.md#conventions) · [Роли](../../../shared/roles.md#roles) · [Ошибки](../../../shared/errors.md#errors) · [Глоссарий](../../../shared/glossary.md#glossary)
<!-- gen:end:related -->

---

Human view: https://docs.vnimanie.ai/specbuilder/v1/domains/collections/api/post-id-group/