Connect to the menu API
Usehttps://api.fluid.app with Authorization: Bearer <token> and Content-Type: application/json for JSON writes. These unversioned admin endpoints require company-admin access with menus.view for reads and menus.update for writes. Mist’s fluid_api tool supplies the active company’s authentication and admin client header.
Replace path placeholders with returned IDs. Menu writes affect shared store data immediately, independently of publishing theme files.
Create a menu
Send this body toPOST /api/menus. Use linkable_type: "Link" for custom URLs; menu creation requires an item type.
Every menu needs at least one country, so send your company’s country IDs in country_ids. An empty list fails validation. New menus are inactive unless you send active: true.
menu. The returned tree uses menu_items and nested sub_menu_items; _attributes keys are for writes.
Choose item types
An item’slinkable_type decides where it links. Record types take the record’s ID in linkable_id and build the URL from its current slug, so the link follows a slug change.
Any other value, including
Category, links to /home/shop. Fluid removes the query string from every item URL. When it renders a menu, Fluid replaces the text home anywhere in an item’s URL with the current storefront’s name, so /home/shop follows a rep’s storefront. An external URL that contains home, such as https://example.com/homeware, changes too.
Items can nest to any depth through sub_menu_items_attributes.
Update or remove items
Send amenu wrapper to PUT /api/menus/:id. Within menu_items_attributes, omit id to create an item, include id to update it, or include id with _destroy: true to delete it. Apply the same rules recursively under sub_menu_items_attributes. Use IDs from a fresh menu read.
menu_item wrapper to PUT /api/menus/:menuId/menu_items/:itemId. Children still use sub_menu_items_attributes. Item reads and updates return a menu_item wrapper. To add one item, send a menu_item wrapper to POST /api/menus/:menuId/menu_items, with parent_id to nest it. Delete one item with DELETE /api/menus/:menuId/menu_items/:itemId, or an entire menu with DELETE /api/menus/:id.
Find an existing menu
GET /api/menus accepts status (active or inactive), page, per_page, search_query, country_ids, and sorted_by. Use title_asc, title_desc, created_at_asc, or created_at_desc for sorting. Encode country arrays as country_ids[]=1&country_ids[]=2.
This admin endpoint uses flat page numbers, not cursor pagination. List responses contain menus and meta with total_count, total_pages, current_page, and per_page.
Connect the menu to your theme
List and read existing menus before creating another. After a write, read the menu again to verify its labels, destinations, ordering, and children. Use the returned menuslug as the value of a section’s link_list setting. Do not derive it from the title: older menus can return a null slug.
section.settings.menu.menu_items, using each item’s title and url. Check desktop and mobile navigation in preview before finishing.
A link_list value can be a menu’s slug or its ID. In Liquid, the menu has title, handle, and menu_items, and each item has only title, url, and sub_menu_items. A blank value, or one that matches no menu, renders an empty menu. The menu’s active flag and countries don’t change what a link_list renders.
The setting’s value is saved in the template’s schema, and the visual editor saves it there too. The schema default applies only while no value is saved, so changing the default doesn’t move a header that already has one. The live storefront renders each template’s published version, and a theme push saves templates without publishing them.
The Base theme’s navbar reads its menu from the menu setting of its nav block, which defaults to main-menu.
Import a menu from another site
When you move a store to Fluid, rebuild its header menu after the pages, products, collections, and categories it links to exist.- Record the source header: each item’s title, URL, order, and children, including dropdown items that are hidden until hover and items that appear only in the mobile menu. Leave out header controls such as the logo, search, account, cart, and country or language selector. They aren’t menu items.
- Map each internal link to the
canonical_urlof the Fluid record that replaced it, or use that record’s type andlinkable_id. Don’t build a URL from the source handle. Keep external links as they are, and note any internal link you can’t map instead of pointing it at the home page. - Find the menu the header already names. Read the header’s
link_listvalue and match it againstGET /api/menus. - Replace that menu’s items with
PUT /api/menus/:id, adding the source items and sending_destroy: truefor the ones the source doesn’t have. Menu writes are live immediately, so the header changes without a theme publish. - If the value matches no menu, create one and use the returned
slug. Set it as the header’s value, then publish the theme so the live storefront picks it up. - Read the menu back and compare it with the source. Then load the live storefront and check the header and mobile menu.