---
title: "Сохранить дельту (операции над узлами) вместо документа целиком"
method: POST
path: "/save/patch"
tags: ["boards"]
---

# Сохранить дельту (операции над узлами) вместо документа целиком

`POST /save/patch`

## Request

- Base URL: `https://maketa.pro/maketa/api`
- URL: `https://maketa.pro/maketa/api/save/patch`
- Auth: one of:
  - none
  - API key in header `x-maketa-key`

Права — те же, что у /save. Только для документов модели v2 (дерево). Операции применяются к текущему документу под замком доски, итог проходит тот же разбор, что и полный /save (белые списки полей, целостность дерева, квоты) — отказ любой операции откатывает весь патч. `baseRev` обязателен: при несовпадении — 409 с текущим `doc` в ответе (объедините правки, пересчитайте патч от него и повторите с новым baseRev). `opId` — идемпотентность: повтор с тем же opId отвечает ok с текущим rev и ничего не применяет (сервер помнит последние 50 на доску). Лимиты: общая корзина с /save (600/ч на IP), ≤ 2000 операций, тело ≤ 1 МиБ. Тело принимается и как text/plain (так шлёт navigator.sendBeacon).

## Request body

- PatchRequest
  - `id` string, required
  - `edit` string: edit-токен (не нужен при x-maketa-key своей доски или linkAccess=edit)
  - `baseRev` integer, required: Ревизия, к которой относится патч (rev из последнего /load, /save, /save/patch или /rev). Обязателен.
  - `opId` string: Идемпотентность повтора: уникален для каждого патча
  - `ops` PatchOp[], required
    - `op` 'set' | 'del', required
    - `path` string, required: name · screensOrder · screens/<sid> (метаданные экрана без nodes) · screens/<sid>/nodes/<nid> (узел целиком) · shared/slots · shared/nodes/<nid>
    - `value` unknown

## Response `200`

Применено (или уже было применено — `repeated: true`)

- object
  - `ok` boolean
  - `rev` integer
  - `updatedAt` integer
  - `repeated` boolean: Повтор opId — патч не применялся второй раз

## Other responses

- `400`: bad_base_rev · bad_ops · too_many_ops · bad_op · bad_path · bad_value · unknown_screen · bad_screens_order · meta_has_nodes · patch_needs_v2 · и все ошибки разбора документа (unknown_node, tree_cycle, …). В `op` — номер операции.
- `401`: Нет или неверный/просроченный ключ (bad_key | key_expired | no_key). hint подскажет, как получить новый.
- `402`: plan_limit — предел тарифа (только при включённых тарифах, MAKETA_PLANS=1). limit: boards | screens | bytes | collaborators | flex | mcpKeys | mcpWrite | seats; used/max — числа; upgrade — какой тариф снимает предел (pro | studio | null); hint — подсказка по-русски. Просмотр по ссылке, экспорт экрана и чтение через API не ограничиваются никогда.
- `403`: Прав нет (forbidden | quota_boards)
- `404`: Не существует (not_found)
- `409`: conflict — на сервере более новая ревизия; в ответе `rev`, `updatedAt` и текущий `doc`
- `410`: Удалено навсегда (gone) — с deletedAt и reason
- `413`: patch_too_large — тело больше 1 МиБ; или doc_too_large после применения
- `429`: Rate limit / квота (too_many | quota_saves); retryAfterMin — минут до сброса окна

---

[API](https://skmtc.dev/maketa/apis/maketa-api.md) · [All operations](https://skmtc.dev/maketa/apis/maketa-api/llms.txt) · [OpenAPI document](https://skmtc.dev/maketa/apis/maketa-api/revisions/ef044d6259d8?raw)
