Appearance
menu
6 endpoints.
GET /api/v1/menu
Get Menu
The menu tree visible to the current user on the active site.
200 — Successful Response
json
{
"items": {
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"title": {
"type": "string",
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Url"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Icon"
},
"app_slug": {
"type": "string",
"title": "App Slug"
},
"min_role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Min Role"
},
"sort_order": {
"type": "integer",
"title": "Sort Order"
},
"colour": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Colour"
},
"children": {
"items": {
"$ref": "#/components/schemas/MenuItemOut"
},
"type": "array",
"title": "Children"
}
},
"type": "object",
"required": [
"id",
"title",
"app_slug",
"sort_order"
],
"title": "MenuItemOut"
},
"type": "array",
"title": "Response Get Menu Api V1 Menu Get"
}POST /api/v1/menu
Create Menu Item
Request body
json
{
"properties": {
"parent_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Parent Id"
},
"title": {
"type": "string",
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Url"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Icon"
},
"app_slug": {
"type": "string",
"title": "App Slug",
"default": "system"
},
"min_role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Min Role"
},
"sort_order": {
"type": "integer",
"title": "Sort Order",
"default": 0
},
"active": {
"type": "boolean",
"title": "Active",
"default": true
}
},
"type": "object",
"required": [
"title"
],
"title": "MenuItemIn"
}201 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"title": {
"type": "string",
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Url"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Icon"
},
"app_slug": {
"type": "string",
"title": "App Slug"
},
"min_role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Min Role"
},
"sort_order": {
"type": "integer",
"title": "Sort Order"
},
"colour": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Colour"
},
"children": {
"items": {
"$ref": "#/components/schemas/MenuItemOut"
},
"type": "array",
"title": "Children"
}
},
"type": "object",
"required": [
"id",
"title",
"app_slug",
"sort_order"
],
"title": "MenuItemOut"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/menu/{item_id}
Update Menu Item
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
item_id | path | yes | integer |
Request body
json
{
"properties": {
"parent_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Parent Id"
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Url"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Icon"
},
"app_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "App Slug"
},
"min_role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Min Role"
},
"sort_order": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Sort Order"
},
"active": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Active"
}
},
"type": "object",
"title": "MenuItemPatch"
}200 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"title": {
"type": "string",
"title": "Title"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Url"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Icon"
},
"app_slug": {
"type": "string",
"title": "App Slug"
},
"min_role": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Min Role"
},
"sort_order": {
"type": "integer",
"title": "Sort Order"
},
"colour": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Colour"
},
"children": {
"items": {
"$ref": "#/components/schemas/MenuItemOut"
},
"type": "array",
"title": "Children"
}
},
"type": "object",
"required": [
"id",
"title",
"app_slug",
"sort_order"
],
"title": "MenuItemOut"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/menu/{item_id}
Delete Menu Item
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
item_id | path | yes | integer |
200 — Successful Response
json
{
"type": "object",
"additionalProperties": true,
"title": "Response Delete Menu Item Api V1 Menu Item Id Delete"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/menu/reorder
Reorder Menu
Persist a new top-to-bottom order for a parent's children by rewriting sort_order. Reorders siblings within that parent only — the top-level groups (apps) themselves are never touched here; their order comes from the Apps Library (POST /apps/reorder).
The client sends only the ids it can see (visibility is gated by installed apps + role). We renumber the parent's WHOLE sibling set so those submitted ids lead in the given order, and any sibling the client couldn't see keeps its relative position right after — so reordering a partial view never makes two siblings collide on the same sort_order or silently shuffles a hidden group into the middle of the visible ones.
The same order is ALWAYS mirrored onto every other site's menu (the menu is a single platform-wide structure), matched by a stable content key since ids differ per site. Sites that don't have the parent/items are skipped; the response reports how many sites were written.
Request body
json
{
"properties": {
"parent_id": {
"type": "integer",
"title": "Parent Id"
},
"ordered_ids": {
"items": {
"type": "integer"
},
"type": "array",
"title": "Ordered Ids"
}
},
"type": "object",
"required": [
"parent_id"
],
"title": "ReorderIn"
}200 — Successful Response
json
{
"additionalProperties": true,
"type": "object",
"title": "Response Reorder Menu Api V1 Menu Reorder Post"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/menu/reset
Reset Menu
Wipe the active site's menu and rebuild the canonical defaults.
200 — Successful Response
json
{
"additionalProperties": true,
"type": "object",
"title": "Response Reset Menu Api V1 Menu Reset Post"
}