Navigation
Navigation menu management endpoints. Each menu is tied to a specific location (header, footer, sidebar, mobile) and contains a hierarchical list of items with multilingual labels.
Base path: /api/v1/navigation
Get Menu by Location
Returns the active menu for a given location. Intended for frontend navigation rendering — no authentication required.
Authentication: Not required
Path parameters
| Parameter | Type | Description |
|---|---|---|
location |
string | One of: header, footer, sidebar, mobile |
Response 200 OK — full NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
404 |
Navigation menu for location not found |
List Menus
Required permission: navigation:read
Response 200 OK
[
{
"id": "uuid",
"slug": "main-menu",
"location": "header",
"is_active": true,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": null
}
]
Create Menu
Required permission: navigation:create
Request body
| Field | Type | Required | Constraints |
|---|---|---|---|
slug |
string | ✅ | 2–255 characters, unique |
location |
string | ✅ | One of: header, footer, sidebar, mobile, unique |
is_active |
bool | ❌ | Default: true |
Response 201 Created — full NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
409 |
Navigation menu slug already exists |
409 |
Navigation menu for location already exists |
Get Menu
Required permission: navigation:read
Response 200 OK
{
"id": "uuid",
"slug": "main-menu",
"location": "header",
"is_active": true,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": null,
"items": [
{
"id": "uuid",
"menu_id": "uuid",
"parent_id": null,
"type": "internal",
"reference_type": "page",
"reference_id": "uuid",
"url": null,
"order": 0,
"is_active": true,
"translations": [
{
"id": "uuid",
"item_id": "uuid",
"language_id": "uuid",
"label": "About Us"
}
],
"children": [
{
"id": "uuid",
"menu_id": "uuid",
"parent_id": "uuid",
"type": "external",
"reference_type": null,
"reference_id": null,
"url": "https://example.com",
"order": 0,
"is_active": true,
"translations": [],
"children": []
}
],
"created_at": "2026-01-01T00:00:00Z",
"updated_at": null
}
]
}
Errors
| Status | Description |
|---|---|
404 |
Navigation menu not found |
Update Menu
Required permission: navigation:update
Request body — all fields optional
Response 200 OK — updated NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
404 |
Navigation menu not found |
409 |
Navigation menu slug already exists |
Delete Menu
Required permission: navigation:delete
Response 204 No Content
Warning
Deleting a menu permanently removes all its items and their translations.
Errors
| Status | Description |
|---|---|
404 |
Navigation menu not found |
Create Item
Required permission: navigation:update
Request body
{
"parent_id": null,
"type": "internal",
"reference_type": "page",
"reference_id": "uuid",
"url": null,
"order": 0,
"is_active": true,
"translations": [
{
"language_id": "uuid",
"label": "About Us"
}
]
}
| Field | Type | Required | Constraints |
|---|---|---|---|
parent_id |
UUID | ❌ | Must exist in this menu |
type |
string | ✅ | One of: internal, external, label |
reference_type |
string | ⚠️ | Required for internal — page, post, category, tag |
reference_id |
UUID | ⚠️ | Required for internal |
url |
string | ⚠️ | Required for external, max 500 characters |
order |
int | ❌ | Default: 0, min: 0 |
is_active |
bool | ❌ | Default: true |
translations |
array | ❌ | List of language labels |
Item type rules
| Type | reference_type |
reference_id |
url |
|---|---|---|---|
internal |
✅ Required | ✅ Required | — |
external |
— | — | ✅ Required |
label |
— | — | — |
Response 200 OK — updated NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
400 |
Invalid item type configuration |
404 |
Navigation menu not found |
404 |
Parent item not found in this menu |
404 |
Language not found |
Update Item
Required permission: navigation:update
Request body — all fields optional
{
"parent_id": "uuid",
"reference_type": "post",
"reference_id": "uuid",
"url": null,
"order": 1,
"is_active": false,
"translations": [
{
"language_id": "uuid",
"label": "Updated Label"
}
]
}
translationsis an optional list — if provided, each entry is upserted by theitem_id + language_idcombination. Existing translations for a given language will be updated; if no translation exists for that language, a new record will be created.
Response 200 OK — updated NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
400 |
Item cannot be its own parent |
400 |
Circular navigation hierarchy is not allowed |
404 |
Navigation menu not found |
404 |
Navigation item not found in this menu |
404 |
Parent item not found in this menu |
404 |
Language not found |
Delete Item
Required permission: navigation:delete
Response 204 No Content
Warning
Deleting an item permanently removes all its children and their translations.
Errors
| Status | Description |
|---|---|
404 |
Navigation menu not found |
404 |
Navigation item not found in this menu |
Reorder Items
Updates order and parent_id for multiple items in a single request.
Allows full restructuring of the menu hierarchy in one call.
Required permission: navigation:update
Request body
{
"items": [
{ "id": "uuid", "order": 0, "parent_id": null },
{ "id": "uuid", "order": 1, "parent_id": null },
{ "id": "uuid", "order": 0, "parent_id": "uuid" }
]
}
Response 200 OK — updated NavigationMenuResponse object.
Errors
| Status | Description |
|---|---|
404 |
Navigation menu not found |
404 |
Item not found in this menu |