Сайдбар документации
Эндпоинты /docs/sidebar, которые читают и меняют меню фрейма документации: чтение, замена целиком, порядок, правка, скрытие и показ пункта; как сайдбар устроен для человека — Сайдбар документации.
Во всех примерах API — https://onpress.pro/api/v2, SITE — id сайта (SITE_ID), OP_TOKEN — токен op_XXXX. Права на всех эндпоинтах страницы — администратор сайта. Как выбирается сайт и в какой форме приходят отказы — Доступ и токен.
Примеры сняты на этой документации (сайт onpress.pro).
Режим и общие поля
Режим определяется по разметке фрейма при каждом запросе и стоит в ответе полем source:
source | Что выводит фрейм | С чем работают эндпоинты |
|---|---|---|
dataset | блок onpress/repeat по пользовательским данным со ссылками внутри (menu.docs, menu.api) | с этими данными; страницы не трогаются. Те же данные читает и пишет /data/{name}, но без проверки ссылок и сверки версии |
pages | блок onpress/docs-nav | с деревом страниц документации, см. Дерево страниц |
| Поле | Где | Смысл |
|---|---|---|
frame | запрос или тело | фрейм документации, слаг или id; без него — опция сайта onpress_docs_frame, затем слаг docs |
menu | запрос или тело | имя меню, когда фрейм выводит несколько; без него — по адресам пунктов, см. ниже |
if_sha256 | тело | версия меню из GET; другая — 409 sidebar_changed |
dry_run | тело или запрос | показать изменения без записи |
Пункт меню — объект title, необязательный url и вложенные пункты под ключом уровня: ключи берутся из фрейма и стоят в ответе GET полем keys (на onpress.pro — items у группы, children у пункта). Пункты глубже, чем выводит фрейм (levels), сохраняются, но не видны.
Как назвать пункт — в пути эндпоинта, в parent, after, before, order:
| Форма | Пример |
|---|---|
| ссылка пункта; в пути — тильды вместо слешей | /docs/v2/ru/guides/frames/, docs~v2~ru~frames |
| id или слаг страницы — ищется по её адресу | 6257 |
| подпись группы без ссылки, без учёта регистра | СУЩНОСТИ |
| координата: индексы с нуля через точку | @1.0.2 |
Какое меню. Названо menu — оно. Одно меню во фрейме — оно. Иначе PUT и show выбирают меню, чей общий каталог (root в GET) — самое длинное начало адресов пунктов: /docs/v2/ru/reference/… уходит в menu.api, остальное /docs/v2/ru/guides/… — в menu.docs. Остальные эндпоинты берут меню, где нашёлся пункт.
Ссылки проверяются. Каждая ссылка на путь сайта (начинается с /) должна вести на опубликованную или приватную страницу; внешние адреса и якоря не проверяются. PUT проверяет всё меню, остальные записи — только новые ссылки.
Чужая правка не затирается. Перед записью меню перечитывается; если его успели поменять, ответ 409 sidebar_changed и ничего не записано.
GET /docs/sidebar
Отдаёт меню сайдбара деревом, его версию sha256 и битые ссылки. Например, прочитать меню справочника API:
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/docs/sidebar?menu=menu.api"
{
"success": true,
"site_id": "ef7QmgyEc",
"home_url": "https://onpress.pro",
"source": "dataset",
"frame": { "id": "fd26d10638458973", "slug": "docs" },
"frame_source": "default",
"total": 33,
"menus": [
{
"name": "menu.api",
"lang": "ru",
"option": "onpress_dataset_menu.api__ru",
"root": "/docs/v2/ru/reference/",
"levels": 3,
"keys": ["items", "children"],
"updated_at_gmt": "2026-10-23 15:47:20",
"sha256": "2d272058…",
"total": 33,
"links": 29,
"broken": 0,
"items": [
{ "title": "НАЧАЛО", "items": [
{ "title": "Основы API", "url": "/docs/v2/ru/reference/", "children": [
{ "title": "Авторизация", "url": "/docs/v2/ru/reference/access/" }
] }
] }
]
}
],
"broken": []
}
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
menu | string | все меню | одно меню |
lang | string | язык фрейма | язык варианта, если фрейм его не задал; фрейм с "lang":"ru" всегда отдаёт ru |
frame | string | фрейм документации сайта | фрейм, слаг или id |
total — пунктов вместе с группами, links — из них со ссылкой на страницу сайта. broken — ссылки в никуда: menu, at, title, url, reason (page_not_found или page_not_published с page_id и status). Отказы — 404 sidebar_menu_not_found и 404 docs_frame_not_found, полный список — в кодах ошибок.
PUT /docs/sidebar
Заменяет меню присланным списком целиком. Например, проверить новый порядок без записи — тело {"menu": "menu.docs", "items": […], "dry_run": true}. Ответ:
Пункт, названный страницей — {"id": 6261}, {"slug": "data"} или просто 6261, — превращается в {"title": "<заголовок>", "url": "<адрес>"}; присланный title важнее. Вложенные пункты под чужим для уровня ключом переносятся под ключ фрейма с предупреждением. "hidden": true исключает пункт, status отбрасывается с предупреждением, missing игнорируется.
{
"success": true,
"source": "dataset",
"menu": { "name": "menu.docs", "lang": "ru", "option": "onpress_dataset_menu.docs__ru", "root": "/docs/v2/ru/guides/" },
"items": 32,
"changes": [
{ "action": "changed", "title": "Фреймы", "url": "/docs/v2/ru/guides/frames/", "order": { "from": "1.1", "to": "1.0" }, "at": "1.0" },
{ "action": "changed", "title": "Страницы", "url": "/docs/v2/ru/guides/pages/", "order": { "from": "1.0", "to": "1.1" }, "at": "1.1" }
],
"unchanged": false,
"sha256_before": "223572ab…",
"sha256": "9b1e04c7…",
"warnings": [],
"dry_run": true,
"applied": false,
"tree": [ … ]
}
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
items | array | — | меню целиком, обязательно |
menu | string | по адресам пунктов | какое меню заменить |
if_sha256 | string | — | версия из GET; другая — 409 sidebar_changed |
dry_run | bool | false | показать changes без записи |
changes — по пункту на отличие: added, removed или changed с тем, что поменялось: title, moved (другая ветка), order (другое место среди тех же соседей) или другое поле пункта. Пункт узнаётся по ссылке, группа — по подписи. После записи добавляются applied: true, updated_at_gmt и rebaked — пересборка страниц, которые выводят меню. Отказы — 400 bad_items, 409 sidebar_items_unresolved (errors: [{at, url, reason}], ничего не записано), 409 sidebar_menu_ambiguous, 409 sidebar_changed; полный список — в кодах ошибок.
POST /docs/sidebar/reorder
Меняет порядок пунктов в одной ветке: целиком списком или сдвигом одного пункта. Например, поставить «Фреймы» первыми в группе «Сущности»:
curl -s -X POST "$API/site/$SITE/docs/sidebar/reorder" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"parent": "СУЩНОСТИ", "order": ["/docs/v2/ru/guides/frames/"]}'
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
parent + order | string, array | 0 — верхний уровень | ветка и её пункты по порядку; неназванные встают после (appended — сколько) |
id + after / before / position | string | — | сдвинуть один пункт среди его соседей |
menu, if_sha256, dry_run | — | — | см. общие поля |
Ответ — как у PUT, плюс parent и order — ссылки пунктов ветки по порядку. Отказы — 400 bad_reorder, 409 not_a_sibling (пункт из другой ветки; перенос — PATCH с parent), 404 item_not_found.
PATCH /docs/sidebar/items/{ref}
Меняет один пункт: подпись, ссылку, ветку или место. Например, переименовать пункт «Данные» без записи:
curl -s -X PATCH "$API/site/$SITE/docs/sidebar/items/docs~v2~ru~data" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"title": "Данные сайта", "dry_run": true}'
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
title | string | — | подпись пункта; заголовок страницы не меняется |
url | string | — | куда ведёт пункт — опубликованная страница; "" делает пункт подписью без ссылки |
parent | string | — | другая ветка: группа или пункт; 0 — верхний уровень |
after, before, position | string, number | — | место среди соседей после переноса |
hidden | bool | — | true — убрать, как /hide |
Ответ — как у PUT, плюс item с подписью и ссылкой после правки. Отказы — 400 nothing_to_update, 400 status_not_in_sidebar (статус меняется у страницы), 404 item_not_found, 409 ambiguous_item (candidates), 409 bad_parent (перенос внутрь себя).
POST /docs/sidebar/items/{ref}/hide и /show
hide убирает пункт вместе с вложенными, предупреждение называет их число. show добавляет пунктом страницу {ref} (id, слаг или путь); тело — title, parent, after, before, position, menu. Без parent пункт встаёт под ближайший пункт-предок по адресу страницы; такого нет — 400 parent_required. Страница уже в меню — applied: false, unchanged: true. Например, показать страницу «Коды ошибок» без записи:
curl -s -X POST "$API/site/$SITE/docs/sidebar/items/docs~v2~ru~errors~codes/show" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"dry_run": true}'
{
"success": true,
"source": "dataset",
"menu": { "name": "menu.docs", "lang": "ru", "option": "onpress_dataset_menu.docs__ru", "root": "/docs/v2/ru/guides/" },
"item": { "title": "Коды ошибок", "url": "/docs/v2/ru/guides/errors/codes/", "page_id": 6300, "hidden": false },
"changes": [ { "action": "added", "title": "Коды ошибок", "url": "/docs/v2/ru/guides/errors/codes/", "at": "4.3.0" } ],
"dry_run": true,
"applied": false
}
Дерево страниц
Когда фрейм выводит onpress/docs-nav, source — pages, и пункт — страница, которую собирает фрейм документации: вложенность — её родитель, порядок — menu_order, подпись — заголовок, скрытый пункт — страница с меткой скрытия.
GET отдаёт tree: у узла id, title, slug, status, parent, menu_order, hidden, url, link, lang, children; параметры include_hidden, statuses, public (только publish), lang (дерево одного языка).
PUT принимает пункты-страницы (id, slug, url) с необязательными title (меняет заголовок страницы), status, hidden, children; missing: "hide" (по умолчанию) скрывает страницы документации вне дерева, "keep" оставляет; запрос заменяет дерево одного языка и выполняется одной транзакцией.
Перенос пункта в другую ветку меняет адрес страницы и её поддерева, старые адреса отвечают 301 на новые (moved, old_paths). Скрытие раздела с видимыми детьми поднимает детей на верхний уровень — ответ предупреждает. reorder, PATCH (title, status, parent, hidden, after/before/position), hide, show работают со страницами; url в PATCH и menu в этом режиме — ошибка.
Коды ошибок
| Код | Статус | Когда |
|---|---|---|
bad_items | 400 | items не массив |
bad_reorder | 400 | нет ни order, ни id |
nothing_to_update | 400 | PATCH без полей; url в дереве страниц |
status_not_in_sidebar | 400 | status для меню из данных |
parent_required | 400 | show не нашёл ветку; укажите parent |
item_ref_required | 400 | пустая ссылка на пункт |
bad_item_url, empty_item | — | в sidebar_items_unresolved.errors: url не строка; пункт без подписи, ссылки и вложенных |
item_not_found | 404 | такого пункта в меню нет |
sidebar_menu_not_found | 404 | фрейм не выводит меню с таким именем |
docs_frame_not_found | 404 | названного фрейма на сайте нет |
page_not_found | 404 | нет такой страницы |
ambiguous_item | 409 | подпись или ссылка в меню не одна; координаты в candidates |
ambiguous_page | 409 | слаг у нескольких страниц; candidates |
bad_parent | 409 | перенос пункта внутрь себя |
not_a_sibling | 409 | в order пункт из другой ветки |
sidebar_menu_ambiguous | 409 | меню несколько, и непонятно, какое; список в menus |
sidebar_changed | 409 | меню поменялось после чтения или во время запроса |
sidebar_items_unresolved | 409 | ссылка в никуда, неизвестная страница, пустой пункт; ничего не записано, разбор в errors |
duplicate_item | 409 | дерево страниц: страница дважды |
bad_missing, bad_status | 400 | дерево страниц: неверные missing, statuses |
unknown_language | 422 | дерево страниц: языка lang нет на сайте |