CommerceOS docsmenu

Storefront API

Content & regions

Menus and pages are classic CMS reads. Regions are the interesting part: named slots of merchant-editable block JSON that your code renders wherever it wants — the visual builder edits them, your storefront stays code.

GET/storefront/v1/menusrate tier: public-read
GET/storefront/v1/menus/:handlerate tier: public-read
wire · menu
▸ GET /storefront/v1/menus/main◂ 200 OK{ "handle": "main",  "items": [ { "label": "Shop", "url": "/collections/all" },             { "label": "About", "url": "/pages/about" } ] }
GET/storefront/v1/pagesrate tier: public-read
GET/storefront/v1/pages/:slugrate tier: public-read

Page body is plain text — paragraphs split on blank lines, never HTML. Render it with your own typography and you are immune to content-borne markup by construction.

Regions

GET/storefront/v1/regions/:keyrate tier: public-read

A region is a block tree in { id, type, settings, children } node shape. Merchants edit a draft in the Admin builder and publish explicitly — this endpoint always serves the published tree.

wire · region block tree
▸ GET /storefront/v1/regions/home-hero▸ X-Publishable-Key: pk_live_9f2…◂ 200 OK{  "key": "home-hero",  "updatedAt": "2026-07-07T10:12:44.000Z",  "blocks": [    { "id": "b1", "type": "heading",      "settings": { "text": "New season, new fits", "level": 1 } },    { "id": "b2", "type": "columns",      "settings": { "columns": 2 },      "children": [        { "id": "b3", "type": "image",          "settings": { "src": "https://cdn…/hero.webp", "alt": "Lookbook" } },        { "id": "b4", "type": "button",          "settings": { "text": "Shop tees", "href": "/collections/tees" } }      ] }  ]}
Block typesTypeDescription
headingleafText + level 1–3.
textleafParagraph text.
imageleafsrc + alt. https/relative URLs only.
buttonleafLabel + href. javascript: URLs are rejected at write time.
spacerleafVertical rhythm.
columnscontainerThe only type that carries children.

Hard limits, enforced at write time: depth ≤ 4, ≤ 50 nodes per region, ≤ 12 children per node. Unknown types, unknown settings keys, and over-limit trees are rejected — your renderer can still treat stored content as untrusted, and every SDK renderer does.

Every SDK ships a safe renderer for this exact subset — SDKs shows <Region> (React), composables (Vue), the use:region action (Svelte), zero-JS HTML serialization (Astro), and a real-DOM mount for everything else.