Skip to main content

Store menus

The store menu is the merchant's choice of links for the navbar, the phone side menu and the footer. The API reads and writes it as one document: up to 12 top links with up to 10 sub-links each, up to 3 footer groups of 10 links, and one switch for the wide category panel. A store that never saved a menu shows the automatic links, and these two endpoints answer automatic: true for it.

The merchant edits the same document in the dashboard, in Customize, row Menu et liens / القائمة والروابط. See Menu and footer links in the merchant docs.

Before you start​

  • Reads need store:read and writes need store:write. Merchant keys carry both.
  • PUT replaces the whole document. Read it first, change what you need, and send it back with the version you read.
  • Idempotency-Key is optional on PUT. A keyed PUT is replayed for 24 hours. See Idempotency.

The menu document​

FieldTypeNotes
vintAlways 1.
megabooleantrue turns on the wide category panel. See The wide panel.
toparray of itemsThe navbar links, in order. 1 to 12. home, products, categories, track, contact and cart appear at most once each here; children are not counted.
footerarray of groupsThe footer columns, in order. Up to 3.

Items​

FieldTypeNotes
typestringOne of home, products, categories, category, page, track, contact, cart, url. See Item types.
labelstringUp to 40 characters. Empty means the target's own name, in the visitor's language for the built-in types. Required for url.
refint or nullThe category id for category, the page id for page, null for the other types.
urlstringThe address for url, up to 500 bytes. Empty for the other types.
show_subcategoriesbooleanTop-level category items only: also shows up to 10 subcategories of that category. Stored false everywhere else, children and footer links included.
childrenarray of itemsTop items only: up to 10 sub-links. A sub-link has no children of its own and cannot be a categories item.

Groups​

FieldTypeNotes
keystring or nullquick_links or categories for the two automatic groups, null for a group you add.
labelstringThe column title, up to 40 characters. It may be empty only when key is set: the store then shows the automatic title in the visitor's language. A typed title shows the same in every language.
linksarray of items1 to 10 links. Footer links have no children and no show_subcategories.

Labels are stored as plain text: HTML tags are removed and spaces are trimmed. The whole document is at most 16 KB.

Item types​

typeThe link opens
home/, the store home.
products/products, all products.
categoriesA drop-down list of the main categories and their subcategories, with an all-products row. In the footer, the categories part of the home page.
category/category/{ref}. ref must be a category of this store.
page/pages/{slug} of the page ref. ref must be a published page of this store. See Store pages.
track/track-order.
contactThe contact part of the home page.
cart/cart.
urlurl: a store path such as /pages/delivery, an anchor such as #products, an http:// or https:// address, tel: or mailto:.

A url without a scheme that looks like a domain, such as instagram.com/x, is stored as https://instagram.com/x. javascript:, data:, //, backslashes, quotes, spaces and angle brackets are refused with bad_url.

On the store, a link to a category or a page that was deleted since, or a page turned back into a draft, is left out with its sub-links. An inactive category is not shown.

The wide panel​

With "mega": true, a top item whose sub-links have their own sub-links shows on computers as a wide panel, one column per sub-link. The categories item does when a main category has subcategories. A category item with show_subcategories lists up to 10 subcategories, and with mega up to 10 of their own subcategories each, a third level. The categories item keeps the caps of the automatic menu: 10 main categories with 5 subcategories each in the navbar, 12 with 6 on the Promobi theme. On phones the side menu shows the same levels as an accordion.

GET /v1/store/menus​

The store's menu. For a store that never saved one, menus is the automatic menu and automatic is true.

Auth: platform key with store:read.

Request​

curl 'https://api.dzbuild.app/v1/store/menus' \
-H "Authorization: Bearer $DZ_KEY"

Response 200​

version is the token to send back with PUT. max gives the limits and types the accepted item types.

{
"data": {
"automatic": false,
"menus": {
"v": 1,
"mega": false,
"top": [
{"type": "home", "label": "", "ref": null, "url": "", "show_subcategories": false, "children": []},
{"type": "category", "label": "", "ref": 152, "url": "", "show_subcategories": true, "children": []},
{"type": "page", "label": "", "ref": 7, "url": "", "show_subcategories": false, "children": []}
],
"footer": [
{"label": "Infos", "links": [{"type": "track", "label": "", "ref": null, "url": ""}, {"type": "url", "label": "Instagram", "ref": null, "url": "https://instagram.com/my-store"}]}
]
},
"version": "3f9a1c07d2e4b851",
"max": {"top": 12, "children": 10, "groups": 3, "links": 10, "label": 40},
"types": ["home", "products", "category", "page", "track", "contact", "cart", "url", "categories"]
},
"meta": {"request_id": "5d2a8e1f07c3b946", "api_version": "v1"}
}

PUT /v1/store/menus​

Replaces the whole menu.

Auth: platform key with store:write. Idempotency-Key optional.

Body​

FieldTypeRequiredNotes
menusobject or nullyesThe new document. null brings back the automatic menu.
versionstringnoThe version you read. When it no longer matches, the call answers 409 write_conflict and changes nothing. Without it, the call overwrites whatever is stored.

Request​

curl -X PUT 'https://api.dzbuild.app/v1/store/menus' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: menus-sizes-1" \
-d '{"version": "3f9a1c07d2e4b851", "menus": {"v": 1, "mega": false, "top": [{"type": "home", "label": "", "ref": null, "url": "", "show_subcategories": false, "children": []}, {"type": "page", "label": "Guide des tailles", "ref": 9, "url": "", "show_subcategories": false, "children": []}], "footer": []}}'

Response 200​

menus is the document as stored, version the new token and change_id the change log id. A body that changes nothing answers change_id: null.

{
"data": {
"menus": {
"v": 1,
"mega": false,
"top": [
{"type": "home", "label": "", "ref": null, "url": "", "show_subcategories": false, "children": []},
{"type": "page", "label": "Guide des tailles", "ref": 9, "url": "", "show_subcategories": false, "children": []}
],
"footer": []
},
"version": "b70e4d2a9c15f383",
"change_id": 90420,
"automatic": false
},
"meta": {"request_id": "a81c3f5e92d07b64", "api_version": "v1"}
}

"menus": null answers automatic: true with the automatic menu in menus.

Undo​

PUT answers with a change_id. POST /v1/changes/{change_id}/undo puts back the menu as it was before that call, the automatic menu included. The undo needs store:write and an Idempotency-Key.

  • When the menu changed again since that call, the undo answers 409 menus_changed and changes nothing. Undo the newer change first.
  • A change undone a second time answers 409 already_undone.
  • Menus the merchant saves in Customize are not recorded, so they cannot be undone through the API.
  • GET /v1/changes?entity=store.menus lists the menu changes, newest first, with store:read. entity_id is menus.
  • An installed app's token cannot read or undo changes: GET /v1/changes and the undo answer 403 forbidden. Write answers still carry the change_id.
curl -X POST 'https://api.dzbuild.app/v1/changes/90420/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-90420"

Errors​

HTTPCodeCause
400bad_requestThe body is not a JSON object, menus is missing or is neither an object nor null, or version is not a string.
401unauthorizedBad or missing key.
402quota_exceededThe store's monthly request quota is used up. See Rate limits.
403forbiddenMissing scope: store:read or Missing scope: store:write, or API access requires an active Enterprise plan for a merchant key whose store is not on an active Enterprise plan.
404not_foundThe store does not exist.
409write_conflictThe version you sent no longer matches: the error carries the current menus (null while the store shows the automatic links) and version, so you can merge and retry. The same code without them means another write landed at the same moment: read again, then retry.
409menus_changedUndo only: the menu changed since the change you undo.
409already_undoneUndo only: the change was already undone.
413payload_too_largeThe body is over 1 MB.
422invalid_menusA value was refused. fields gives {path, code} for it. See the codes below.
422idempotency_key_reuseThe same Idempotency-Key was used with another body.
429rate_limitedToo many requests. Wait for Retry-After.
500server_errorThe request failed. Retry with the same Idempotency-Key.

path starts with menus. and points at the refused value, such as menus.top.0.url or menus.footer.1.links.10; it is menus alone for too_large. The code is one of these.

codeCause
bad_urlAn empty, refused or too long url.
invalidA shape error: a list where an object is expected or the reverse, such as top that is not an array.
too_manyMore than 12 top items, 10 children, 3 groups or 10 links in a group. path names the first item over the limit.
top_requiredtop is empty. To drop a custom menu, send "menus": null.
unknown_typetype is not one of the nine types.
unknown_keyA footer group key other than quick_links, categories or null.
unknown_categoryref is not a category of this store.
unknown_pageref is not a published page of this store.
label_requiredA url item without a label, or a footer group without a label and without a key.
label_too_longA label over 40 characters.
links_requiredA footer group with no link.
duplicate_typeA second home, products, categories, track, contact or cart item in top.
nested_too_deepchildren inside a sub-link or a footer link, or a categories item as a sub-link.
too_largeThe document is over 16 KB.
{
"error": {
"code": "invalid_menus",
"message": "Invalid menu at menus.top.0.url (bad_url); the caps and types are in GET /v1/store/menus.",
"fields": [{"path": "menus.top.0.url", "code": "bad_url"}]
},
"meta": {"request_id": "c27e90b4f13a5d68", "api_version": "v1"}
}

Limits​

  • Top menu: 12 items, each with up to 10 sub-links.
  • Footer: 3 groups of up to 10 links.
  • Label: 40 characters. Url: 500 bytes. Document: 16 KB.
  • The limits are the same on every plan.

MCP tools​

The MCP server, version 1.9.0, gives an AI assistant two menu tools with the same rules: menus_get returns the whole document with its version and caps, menus_set writes it back with that version, and change_undo reverts a write.

This page for AI toolsView as MarkdownOpen in ChatGPTOpen in Claude