API 参考
Globals
Management API: GET /sites/{id}/globals, GET /sites/{id}/globals/headers, POST /sites/{id}/globals/headers, …
Read the site-level draft shared by all pages: the primary header and footer (from globalSections), siteSettings (customButtons referenced by sections via ctaIds, socialLinks) and the revision marker contentUpdatedAt. Call it before globals.replace_header / globals.replace_footer / globals.update_site_settings and pass contentUpdatedAt back as ifUnmodifiedSince. Images of the site's media library appear as asset:<assetId>; assets holds them (with display URLs). Errors: FORBIDDEN (also when the website does not exist), WEBSITE_NOT_FOUND.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Response 200
headerobject | nullrequiredPrimary header section, or null when the site has none yet.
footerobject | nullrequiredsharedSectionsobject[]requiredOther shared content sections; pages embed them with a global-section-ref item.
sharedSections[].idstring | nullrequiredsharedSections[].typestringrequiredsiteSettingsobject | nullrequiredassetsobjectrequiredThe media-library files referenced as asset:<assetId>, by assetId.
contentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
Errors
FORBIDDEN403 · also when the website does not existWEBSITE_NOT_FOUND404
MCP tool globals_get
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/globals" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"header": {
"id": "sec_header01",
"type": "header",
"navItems": [
{
"id": "nav_home",
"text": "Home",
"linkType": "internal",
"pageSlug": "/"
},
{
"id": "nav_about",
"text": "About Us",
"linkType": "internal",
"pageSlug": "/about"
}
],
"ctaIds": [
"btn_order"
]
},
"footer": {
"id": "sec_footer01",
"type": "footer",
"copyright": "© 2026 Sunny Bakery"
},
"sharedSections": [
{
"id": "sec_header01",
"type": "header"
},
{
"id": "sec_footer01",
"type": "footer"
}
],
"siteSettings": {
"customButtons": [
{
"id": "btn_order",
"text": "Order online",
"url": "/shop",
"style": "brand"
}
],
"socialLinks": [
{
"platform": "instagram",
"url": "https://www.instagram.com/sunnybakery.example"
}
]
},
"assets": {},
"contentUpdatedAt": "2026-10-06T08:00:00.000Z"
}List all headers in globalSections: the primary header plus any secondary headers created for specific pages (ADR-0001). Most websites only need the primary header. All headers are returned in one page. Errors: FORBIDDEN, WEBSITE_NOT_FOUND.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Response 200
dataobject[]requireddata[].idstringrequiredPass this id to pages.update globalHeaderId to assign the header to a page.
data[].keystringrequireddata[].isPrimarybooleanrequireddata[].headerobjectrequiredhasMorebooleanrequiredTrue when another page exists; pass nextCursor to fetch it.
nextCursorstring | nullrequiredCursor for the next page, or null on the last page.
assetsobjectrequiredThe media-library files referenced as asset:<assetId>, by assetId.
contentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
Errors
FORBIDDEN403WEBSITE_NOT_FOUND404
MCP tool globals_list_headers
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/globals/headers" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"data": [
{
"id": "sec_header01",
"key": "primary",
"isPrimary": true,
"header": {
"id": "sec_header01",
"type": "header",
"navItems": [
{
"id": "nav_home",
"text": "Home",
"linkType": "internal",
"pageSlug": "/"
},
{
"id": "nav_about",
"text": "About Us",
"linkType": "internal",
"pageSlug": "/about"
}
],
"ctaIds": [
"btn_order"
]
}
}
],
"assets": {},
"contentUpdatedAt": "2026-10-06T08:00:00.000Z",
"hasMore": false,
"nextCursor": null
}Create a secondary header in globalSections with a human-readable key. Only use this when specific pages need a different navigation bar (for example a sub-brand or campaign microsite); most websites only need the primary header. After creating the header, assign its returned id to a page with pages.update({ globalHeaderId }). Saved as draft only; call site.publish to go live. Errors: FORBIDDEN, WEBSITE_NOT_FOUND, VALIDATION, KEY_TAKEN, CONFLICT, WRITE_FROZEN, ASSET_NOT_FOUND (details.assetIds: not in this site's media library), ASSET_NOT_ALLOWED (product files cannot be shown on pages).
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Request body
ifUnmodifiedSincestringrequiredcontentUpdatedAt from globals.get. Required: the write is rejected with CONFLICT when the site-level draft changed since (details.contentUpdatedAt holds the current value).
keystringrequiredUnique header key (a-z, 0-9, hyphen, underscore; 1-40 chars). 'primary' refers to the main site header.
headerobjectrequiredComplete header object. navItems is the navigation: one { id, text, linkType: "internal", pageSlug } per visible page (the header never lists pages automatically); keep text short (1-3 words) since it has to fit a single desktop row — it is not the page title. Use linkType: "group" to nest related pages under one dropdown instead of adding many top-level items (desktop headers work best with 7 or fewer top-level items). Use ctaIds (up to 2) to show buttons from siteSettings.customButtons. layout picks the desktop arrangement (top-spread, top-left, top-center, top-stacked, side-left) — top-stacked puts navigation on its own full-width row below the logo/CTA row and suits sites with many nav items; surface sets the background tone; showBrandLogo / showSiteName / logoSize control the brand slot and showSocialLinks (boolean or per device) plus hiddenSocialLinkUrls choose which social links appear; utilities orders and toggles the feature buttons (search, cart) after the CTA buttons. The logo comes from the website's brand settings unless logoOverride is set.
header.type"header"requiredheader.idstringrequiredStable id; pages reference it via globalHeaderId.
header.keystringHuman-readable key for this header (e.g. 'primary', 'campaign', 'docs').
header.ctaobjectheader.cta.idstringheader.cta.icon"briefcase" | "star" | "award" | "crown" | "flame" | "zap" | "target" | "rocket" | "flag" | "gem" | "diamond" | "scroll" | "fingerprint" | "smile" | "laugh" | "clock" | "phone" | "mail" | "bell" | "settings" | "check-circle" | "info" | "help-circle" | "headset" | "megaphone" | "newspaper" | "hourglass" | "stamp" | "milestone" | "quote" | "table" | "list-ordered" | "list-checks" | "arrow-right" | "message-circle" | "external-link" | "download" | "play" | "pause" | "bookmark" | "search" | "filter" | "thumbs-up" | "share-2" | "eye" | "phone-call" | "send" | "lock" | "rotate-ccw" | "clipboard-check" | "alarm-clock" | "utensils" | "utensils-crossed" | "chef-hat" | "coffee" | "pizza" | "soup" | "ice-cream-cone" | "sandwich" | "beef" | "fish" | "salad" | "cookie" | "cake" | "cake-slice" | "dessert" | "cup-soda" | "wine" | "beer" | "martini" | "milk" | "wheat" | "egg" | "croissant" | "popcorn" | "candy" | "apple" | "cherry" | "banana" | "citrus" | "grape" | "carrot" | "drumstick" | "cooking-pot" | "shrimp" | "donut" | "bean" | "vegan" | "store" | "shopping-bag" | "shopping-cart" | "shopping-basket" | "package" | "package-check" | "boxes" | "truck" | "motorbike" | "warehouse" | "tag" | "tags" | "ticket-percent" | "barcode" | "qr-code" | "scan-qr-code" | "credit-card" | "smartphone-nfc" | "wallet" | "banknote" | "coins" | "dollar-sign" | "percent" | "badge-percent" | "receipt" | "shirt" | "heart" | "heart-pulse" | "stethoscope" | "hospital" | "syringe" | "pill" | "pill-bottle" | "bandage" | "cross" | "thermometer" | "briefcase-medical" | "scissors" | "sparkles" | "scan-face" | "hand" | "bath" | "droplet" | "droplets" | "flower" | "flower-2" | "sun" | "moon" | "book-open" | "book-text" | "book-copy" | "book-marked" | "book-check" | "graduation-cap" | "school" | "library" | "monitor-play" | "backpack" | "pencil" | "pen-tool" | "file-text" | "scroll-text" | "notebook-pen" | "languages" | "calculator" | "presentation" | "lightbulb" | "brain" | "puzzle" | "laptop" | "monitor" | "smartphone" | "tablet" | "code" | "code-2" | "terminal" | "server" | "database" | "cloud" | "cpu" | "globe" | "network" | "circuit-board" | "brain-circuit" | "bot" | "blocks" | "palette" | "brush" | "paint-bucket" | "pen-line" | "image" | "image-plus" | "camera" | "video" | "film" | "clapperboard" | "music" | "music-2" | "music-4" | "mic" | "mic-2" | "headphones" | "speaker" | "radio" | "podcast" | "piano" | "plane" | "map-pin" | "map-pinned" | "navigation" | "route" | "compass" | "mountain" | "tree-pine" | "trees" | "tent" | "umbrella" | "anchor" | "ship" | "car" | "bike" | "bus" | "train" | "luggage" | "hotel" | "bed-double" | "concierge-bell" | "wifi" | "parking-square" | "air-vent" | "washing-machine" | "cigarette-off" | "accessibility" | "dumbbell" | "biceps-flexed" | "footprints" | "timer" | "watch" | "medal" | "trophy" | "swords" | "badge-check" | "activity" | "building" | "building-2" | "factory" | "house" | "house-plus" | "map-pin-house" | "door-open" | "door-closed" | "key" | "key-round" | "fence" | "sofa" | "ruler" | "hard-hat" | "hammer" | "wrench" | "paint-roller" | "brush-cleaning" | "cat" | "dog" | "bird" | "rabbit" | "squirrel" | "paw-print" | "bone" | "leaf" | "sprout" | "clover" | "tractor" | "cloud-sun" | "cloud-rain" | "snowflake" | "leafy-green" | "tree-deciduous" | "wind" | "waves" | "recycle" | "landmark" | "vault" | "scale" | "gavel" | "shield" | "shield-check" | "badge-dollar-sign" | "hand-coins" | "trending-up" | "trending-down" | "bar-chart" | "bar-chart-2" | "bar-chart-3" | "pie-chart" | "line-chart" | "chart-no-axes-combined" | "users" | "users-round" | "user-circle" | "user-plus" | "hand-heart" | "hand-helping" | "heart-handshake" | "handshake" | "baby" | "church" | "party-popper" | "sparkle" | "gift" | "ticket" | "calendar" | "calendar-days" | "calendar-check" | "calendar-clock"header.cta.textstringheader.cta.urlstringOptional link: absolute http(s)/tel:/mailto: URL, site-relative path (/about) or anchor (#id).
header.cta.style"brand" | "default" | "ghost"header.ctaIdstringLegacy single button id from siteSettings.customButtons. Prefer ctaIds; when both are set ctaIds wins.
header.ctaIdsstring[]Up to 2 ids of buttons defined in siteSettings.customButtons, shown at the right of the header (and at the bottom of the side-left sidebar / mobile menu).
header.ctaStyleByIdobjectPer-button style override keyed by customButton id: brand (filled brand color), default (neutral), or ghost (text with arrow).
header.layout"top-spread" | "top-left" | "top-center" | "top-stacked" | "side-left"Desktop header layout: top-spread (default), top-left (nav next to logo), top-center (centered nav), top-stacked (nav on its own full-width row below the logo/CTA row; best for many nav items or long labels), or side-left (fixed left sidebar).
header.surface"auto" | "default" | "muted" | "tint" | "brand" | "contrast"Header background tone: default (light bar with blur), muted, tint, brand or contrast; text colors adapt automatically. auto behaves like default.
header.showBrandLogobooleanShow the brand logo (default true). When false and showSiteName is false, nothing is rendered in the brand slot.
header.showSiteNamebooleanShow the website name next to (or instead of) the logo (default false; the name is still shown when no logo exists).
header.logoSize"sm" | "md" | "lg"Logo size in the header (default md).
header.showSocialLinksboolean | objectShow siteSettings.socialLinks in the header, either for every device (boolean) or per device. Defaults: desktop only for the side-left layout, tablet and mobile menu on.
header.showSocialLinks.desktopbooleanheader.showSocialLinks.tabletbooleanheader.showSocialLinks.mobilebooleanheader.hiddenSocialLinkUrlsstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDeviceobjectPer-device blacklist of social link urls; a device without its own list falls back to hiddenSocialLinkUrls.
header.hiddenSocialLinkUrlsByDevice.desktopstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDevice.tabletstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDevice.mobilestring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.variant"solid" | "transparent" | "glass"Deprecated and ignored: the header background is controlled by surface. Accepted for backward compatibility.
header.shrinkOnScrollbooleanCompact the header after scrolling (default true).
header.showProgressBarbooleanheader.showAccentLinebooleanShow a thin brand-gradient line at the bottom edge (default false).
header.isVisiblebooleanheader.navItemsobject[]Navigation links. The header never lists pages automatically; add one internal item per visible page.
header.navItems[].idstringrequiredheader.navItems[].textstringrequiredheader.navItems[].linkType"internal" | "external" | "group"requiredheader.navItems[].pageSlugstringheader.navItems[].anchorIdstringheader.navItems[].externalUrlstringOptional link: absolute http(s)/tel:/mailto: URL, site-relative path (/about) or anchor (#id).
header.navItems[].openInNewTabbooleanheader.navItems[].childrenobject[]header.navItems[].linkobjectheader.utilitiesobject[]Header utility buttons (site features shown at the right of the header, after the CTA buttons), in display order; each id at most once. enabled shows or hides it; an omitted id keeps its default (search: off, cart: on, language: on, account: on; newly created sites default all to on). A utility only renders when the site has that feature: search needs a published site with searchable content; cart needs the shopping cart turned on in store settings and at least one active product; language needs at least two published site languages; account needs the customer sign-in entry turned on under Settings › Customer accounts (signed-in customers always see it). On phones only the first 2 visible utilities stay next to the menu button; the rest move to the top of the mobile menu.
header.utilities[].id"search" | "cart" | "language" | "account"requiredsearch: site search button; cart: shopping cart button; language: language switcher; account: customer sign-in / account panel.
header.utilities[].enabledbooleanrequiredheader.isGlobalbooleanheader.logoOverrideanyHeader-specific logo (e.g. a wide wordmark). Omit to use the website's brand logo.
Response 201
keystringrequiredisPrimaryfalserequiredheaderobjectrequiredassetsobjectrequiredThe media-library files referenced as asset:<assetId>, by assetId.
contentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
warningsobject[]requiredContent-quality warnings about navItems: long labels or too many top-level items. These are fixed content rules, not a prediction of whether the header will overflow at some width — the renderer always collapses items that do not fit into a "more" menu, so the site never breaks either way. Empty array when there is nothing to flag.
warnings[].code"NAV_LABEL_TOO_LONG" | "NAV_TOO_MANY_ITEMS"requiredwarnings[].messagestringrequiredwarnings[].navItemIdsstring[]ids of the navItems the warning is about, when applicable.
Errors
FORBIDDEN403WEBSITE_NOT_FOUND404VALIDATION400KEY_TAKEN409CONFLICT409WRITE_FROZEN503ASSET_NOT_FOUND404 · details.assetIds: not in this site's media libraryASSET_NOT_ALLOWED422 · product files cannot be shown on pages
MCP tool globals_create_header
curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/globals/headers" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ifUnmodifiedSince":"2026-10-06T08:00:00.000Z","key":"campaign","header":{"id":"hdr_campaign_01","type":"header","navItems":[{"id":"nav_home","text":"Home","linkType":"internal","pageSlug":"/"},{"id":"nav_about","text":"About Us","linkType":"internal","pageSlug":"/about"}],"ctaIds":["btn_order"],"key":"campaign"}}'{
"key": "campaign",
"isPrimary": false,
"header": {
"id": "hdr_campaign_01",
"type": "header",
"navItems": [
{
"id": "nav_home",
"text": "Home",
"linkType": "internal",
"pageSlug": "/"
},
{
"id": "nav_about",
"text": "About Us",
"linkType": "internal",
"pageSlug": "/about"
}
],
"ctaIds": [
"btn_order"
],
"key": "campaign"
},
"assets": {},
"contentUpdatedAt": "2026-10-06T08:00:00.000Z",
"warnings": []
}Delete a secondary header by key and automatically reassign any pages using it back to the primary header. The primary header cannot be deleted. Saved as draft only; call site.publish to go live. Errors: FORBIDDEN, WEBSITE_NOT_FOUND, HEADER_NOT_FOUND, PRIMARY_HEADER_PROTECTED, CONFLICT, WRITE_FROZEN.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
keystring · pathrequiredUnique header key (a-z, 0-9, hyphen, underscore; 1-40 chars). 'primary' refers to the main site header.
ifUnmodifiedSincestring · queryrequiredcontentUpdatedAt from globals.get. Required: the write is rejected with CONFLICT when the site-level draft changed since (details.contentUpdatedAt holds the current value).
Response 200
deletedKeystringrequiredreassignedPagesintegerrequiredcontentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
Errors
FORBIDDEN403WEBSITE_NOT_FOUND404HEADER_NOT_FOUND404PRIMARY_HEADER_PROTECTED409CONFLICT409WRITE_FROZEN503
MCP tool globals_delete_header
curl -X DELETE "https://app.kanorio.com/api/v1/sites/{id}/globals/headers/{key}?ifUnmodifiedSince=2026-10-06T08%3A00%3A00.000Z" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"deletedKey": "campaign",
"reassignedPages": 1,
"contentUpdatedAt": "2026-10-06T08:00:00.000Z"
}Update site settings
/sites/{id}/globals/site-settingsPartially update siteSettings (only the keys you send are replaced; optimistic concurrency). customButtons is the single list of CTA buttons for the whole site: define them here (text, url, optional icon and style), then reference their ids from sections, the header and the footer via ctaIds (up to 2 per place). Buttons without an id get one; read it back from the response. Replaces the whole list when sent. socialLinks: [{ platform, url }] rendered in the footer and social sections. Contact fields (address/phone/email/hours) are business facts and are not editable here. Saved as draft only; call site.publish to go live. Errors: FORBIDDEN, WEBSITE_NOT_FOUND, VALIDATION, CONFLICT, WRITE_FROZEN, ASSET_NOT_FOUND (details.assetIds: not in this site's media library), ASSET_NOT_ALLOWED (product files cannot be shown on pages).
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Request body
ifUnmodifiedSincestringrequiredcontentUpdatedAt from globals.get. Required: the write is rejected with CONFLICT when the site-level draft changed since (details.contentUpdatedAt holds the current value).
siteSettingsobjectrequiredKeys to replace: customButtons (max 2 are shown per section; the list itself can be longer), socialLinks, socialIconColor, showBreadcrumbs (boolean, defaults to true; controls site-wide breadcrumb navigation and BreadcrumbList JSON-LD).
siteSettings.socialLinksobject[]siteSettings.socialLinks[].platform"website" | "facebook" | "instagram" | "line_oa" | "threads" | "tiktok" | "douyin" | "youtube" | "twitter" | "whatsapp" | "linkedin" | "xhs" | "pinterest" | "behance" | "bluesky" | "discord" | "messenger" | "dribbble" | "github" | "mastodon" | "medium" | "reddit" | "snapchat" | "substack" | "patreon" | "ko_fi" | "buymeacoffee" | "linktree" | "tumblr" | "quora" | "nextdoor" | "soundcloud" | "bandcamp" | "tidal" | "notion" | "figma" | "canva" | "signal" | "slack" | "zoom" | "bilibili" | "weibo" | "wechat" | "zhihu" | "douban" | "strava" | "letterboxd" | "goodreads" | "yelp" | "foursquare" | "tripadvisor" | "stackoverflow" | "shopify" | "skype" | "viber" | "wordpress" | "deezer" | "mixcloud" | "dailymotion" | "gitlab" | "bitbucket" | "trello" | "dropbox" | "codepen" | "artstation" | "audible" | "gojek" | "bukalapak" | "zalo" | "kakaotalk" | "naver" | "aliexpress" | "amazon" | "ebay" | "etsy" | "paypal" | "stripe" | "alipay" | "jkopay" | "line_pay" | "taiwan_pay" | "pxpay" | "ipass_money" | "grab" | "meituan" | "dianping" | "plurk" | "dcard" | "bahamut" | "shopee" | "rakuten" | "rakuten_tickets" | "taobao" | "pinkoi" | "carousell" | "momo" | "pchome" | "yahoo_shopping" | "yahoo_mall" | "ruten" | "coupang" | "books_com_tw" | "etmall" | "friday" | "spotify" | "vocus" | "telegram" | "twitch" | "vimeo" | "surveycake" | "apple_podcast" | "apple_music" | "firstory" | "kkbox" | "soundon" | "uber" | "uber_eats" | "foodpanda" | "keeta" | "deliveroo" | "nidin" | "ichef" | "dudoo" | "hahow" | "pressplay" | "udemy" | "google_maps" | "google_forms" | "google_reviews" | "typeform" | "openrice" | "inline" | "funnow" | "accupass" | "kktix" | "eztable" | "104_jobs" | "1111_jobs" | "518_jobs" | "yes123" | "yourator" | "meet_jobs" | "cake" | "calendly" | "booking_com" | "agoda" | "airbnb" | "asiayo" | "kkday" | "klook" | "house591" | "youbike" | "irent" | "hktvmall" | "payme" | "octopus" | "alipay_hk" | "jobsdb" | "lihkg" | "price_com_hk" | "cityline" | "joox" | "ctgoodjobs" | "discuss_com_hk" | "hse28" | "spacious" | "urbtix" | "jd_com" | "yesstyle" | "ztore" | "moov" | "flickr" | "meetup" | "kickstarter" | "product_hunt" | "lastfm" | "scribd" | "pocket" | "steam" | "vk" | "xing" | "orcid" | "researchgate"requiredsiteSettings.socialLinks[].urlstringrequiredsiteSettings.customButtonsobject[]siteSettings.customButtons[].idstringsiteSettings.customButtons[].iconType"icon" | "platform"siteSettings.customButtons[].icon"briefcase" | "star" | "award" | "crown" | "flame" | "zap" | "target" | "rocket" | "flag" | "gem" | "diamond" | "scroll" | "fingerprint" | "smile" | "laugh" | "clock" | "phone" | "mail" | "bell" | "settings" | "check-circle" | "info" | "help-circle" | "headset" | "megaphone" | "newspaper" | "hourglass" | "stamp" | "milestone" | "quote" | "table" | "list-ordered" | "list-checks" | "arrow-right" | "message-circle" | "external-link" | "download" | "play" | "pause" | "bookmark" | "search" | "filter" | "thumbs-up" | "share-2" | "eye" | "phone-call" | "send" | "lock" | "rotate-ccw" | "clipboard-check" | "alarm-clock" | "utensils" | "utensils-crossed" | "chef-hat" | "coffee" | "pizza" | "soup" | "ice-cream-cone" | "sandwich" | "beef" | "fish" | "salad" | "cookie" | "cake" | "cake-slice" | "dessert" | "cup-soda" | "wine" | "beer" | "martini" | "milk" | "wheat" | "egg" | "croissant" | "popcorn" | "candy" | "apple" | "cherry" | "banana" | "citrus" | "grape" | "carrot" | "drumstick" | "cooking-pot" | "shrimp" | "donut" | "bean" | "vegan" | "store" | "shopping-bag" | "shopping-cart" | "shopping-basket" | "package" | "package-check" | "boxes" | "truck" | "motorbike" | "warehouse" | "tag" | "tags" | "ticket-percent" | "barcode" | "qr-code" | "scan-qr-code" | "credit-card" | "smartphone-nfc" | "wallet" | "banknote" | "coins" | "dollar-sign" | "percent" | "badge-percent" | "receipt" | "shirt" | "heart" | "heart-pulse" | "stethoscope" | "hospital" | "syringe" | "pill" | "pill-bottle" | "bandage" | "cross" | "thermometer" | "briefcase-medical" | "scissors" | "sparkles" | "scan-face" | "hand" | "bath" | "droplet" | "droplets" | "flower" | "flower-2" | "sun" | "moon" | "book-open" | "book-text" | "book-copy" | "book-marked" | "book-check" | "graduation-cap" | "school" | "library" | "monitor-play" | "backpack" | "pencil" | "pen-tool" | "file-text" | "scroll-text" | "notebook-pen" | "languages" | "calculator" | "presentation" | "lightbulb" | "brain" | "puzzle" | "laptop" | "monitor" | "smartphone" | "tablet" | "code" | "code-2" | "terminal" | "server" | "database" | "cloud" | "cpu" | "globe" | "network" | "circuit-board" | "brain-circuit" | "bot" | "blocks" | "palette" | "brush" | "paint-bucket" | "pen-line" | "image" | "image-plus" | "camera" | "video" | "film" | "clapperboard" | "music" | "music-2" | "music-4" | "mic" | "mic-2" | "headphones" | "speaker" | "radio" | "podcast" | "piano" | "plane" | "map-pin" | "map-pinned" | "navigation" | "route" | "compass" | "mountain" | "tree-pine" | "trees" | "tent" | "umbrella" | "anchor" | "ship" | "car" | "bike" | "bus" | "train" | "luggage" | "hotel" | "bed-double" | "concierge-bell" | "wifi" | "parking-square" | "air-vent" | "washing-machine" | "cigarette-off" | "accessibility" | "dumbbell" | "biceps-flexed" | "footprints" | "timer" | "watch" | "medal" | "trophy" | "swords" | "badge-check" | "activity" | "building" | "building-2" | "factory" | "house" | "house-plus" | "map-pin-house" | "door-open" | "door-closed" | "key" | "key-round" | "fence" | "sofa" | "ruler" | "hard-hat" | "hammer" | "wrench" | "paint-roller" | "brush-cleaning" | "cat" | "dog" | "bird" | "rabbit" | "squirrel" | "paw-print" | "bone" | "leaf" | "sprout" | "clover" | "tractor" | "cloud-sun" | "cloud-rain" | "snowflake" | "leafy-green" | "tree-deciduous" | "wind" | "waves" | "recycle" | "landmark" | "vault" | "scale" | "gavel" | "shield" | "shield-check" | "badge-dollar-sign" | "hand-coins" | "trending-up" | "trending-down" | "bar-chart" | "bar-chart-2" | "bar-chart-3" | "pie-chart" | "line-chart" | "chart-no-axes-combined" | "users" | "users-round" | "user-circle" | "user-plus" | "hand-heart" | "hand-helping" | "heart-handshake" | "handshake" | "baby" | "church" | "party-popper" | "sparkle" | "gift" | "ticket" | "calendar" | "calendar-days" | "calendar-check" | "calendar-clock"siteSettings.customButtons[].platform"website" | "facebook" | "instagram" | "line_oa" | "threads" | "tiktok" | "douyin" | "youtube" | "twitter" | "whatsapp" | "linkedin" | "xhs" | "pinterest" | "behance" | "bluesky" | "discord" | "messenger" | "dribbble" | "github" | "mastodon" | "medium" | "reddit" | "snapchat" | "substack" | "patreon" | "ko_fi" | "buymeacoffee" | "linktree" | "tumblr" | "quora" | "nextdoor" | "soundcloud" | "bandcamp" | "tidal" | "notion" | "figma" | "canva" | "signal" | "slack" | "zoom" | "bilibili" | "weibo" | "wechat" | "zhihu" | "douban" | "strava" | "letterboxd" | "goodreads" | "yelp" | "foursquare" | "tripadvisor" | "stackoverflow" | "shopify" | "skype" | "viber" | "wordpress" | "deezer" | "mixcloud" | "dailymotion" | "gitlab" | "bitbucket" | "trello" | "dropbox" | "codepen" | "artstation" | "audible" | "gojek" | "bukalapak" | "zalo" | "kakaotalk" | "naver" | "aliexpress" | "amazon" | "ebay" | "etsy" | "paypal" | "stripe" | "alipay" | "jkopay" | "line_pay" | "taiwan_pay" | "pxpay" | "ipass_money" | "grab" | "meituan" | "dianping" | "plurk" | "dcard" | "bahamut" | "shopee" | "rakuten" | "rakuten_tickets" | "taobao" | "pinkoi" | "carousell" | "momo" | "pchome" | "yahoo_shopping" | "yahoo_mall" | "ruten" | "coupang" | "books_com_tw" | "etmall" | "friday" | "spotify" | "vocus" | "telegram" | "twitch" | "vimeo" | "surveycake" | "apple_podcast" | "apple_music" | "firstory" | "kkbox" | "soundon" | "uber" | "uber_eats" | "foodpanda" | "keeta" | "deliveroo" | "nidin" | "ichef" | "dudoo" | "hahow" | "pressplay" | "udemy" | "google_maps" | "google_forms" | "google_reviews" | "typeform" | "openrice" | "inline" | "funnow" | "accupass" | "kktix" | "eztable" | "104_jobs" | "1111_jobs" | "518_jobs" | "yes123" | "yourator" | "meet_jobs" | "cake" | "calendly" | "booking_com" | "agoda" | "airbnb" | "asiayo" | "kkday" | "klook" | "house591" | "youbike" | "irent" | "hktvmall" | "payme" | "octopus" | "alipay_hk" | "jobsdb" | "lihkg" | "price_com_hk" | "cityline" | "joox" | "ctgoodjobs" | "discuss_com_hk" | "hse28" | "spacious" | "urbtix" | "jd_com" | "yesstyle" | "ztore" | "moov" | "flickr" | "meetup" | "kickstarter" | "product_hunt" | "lastfm" | "scribd" | "pocket" | "steam" | "vk" | "xing" | "orcid" | "researchgate"siteSettings.customButtons[].textstringsiteSettings.customButtons[].urlstringOptional link: absolute http(s)/tel:/mailto: URL, site-relative path (/about) or anchor (#id).
siteSettings.customButtons[].linkobjectsiteSettings.customButtons[].openInNewTabbooleansiteSettings.customButtons[].style"brand" | "default" | "ghost"siteSettings.customButtons[].iconPosition"left" | "right"siteSettings.socialIconColorobjectsiteSettings.socialIconColor.lightstringsiteSettings.socialIconColor.darkstringsiteSettings.showBreadcrumbsboolean
Response 200
siteSettingsobjectrequiredsiteSettings as stored; customButtons[].id are the ids to use in ctaIds.
assetsobjectrequiredThe media-library files referenced as asset:<assetId>, by assetId.
contentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
Errors
FORBIDDEN403WEBSITE_NOT_FOUND404VALIDATION400CONFLICT409WRITE_FROZEN503ASSET_NOT_FOUND404 · details.assetIds: not in this site's media libraryASSET_NOT_ALLOWED422 · product files cannot be shown on pages
MCP tool globals_update_site_settings
curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/globals/site-settings" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ifUnmodifiedSince":"2026-10-06T08:00:00.000Z","siteSettings":{"customButtons":[{"id":"btn_order","text":"Order online","url":"/shop","style":"brand"}]}}'{
"siteSettings": {
"customButtons": [
{
"id": "btn_order",
"text": "Order online",
"url": "/shop",
"style": "brand"
}
],
"socialLinks": [
{
"platform": "instagram",
"url": "https://www.instagram.com/sunnybakery.example"
}
]
},
"assets": {},
"contentUpdatedAt": "2026-10-06T08:00:00.000Z"
}Replace the primary header or a secondary header identified by key (whole object, optimistic concurrency). The header's id stays the one pages already reference; when the site has no header yet, the given id is used and attached to every page. Typical use after creating pages: rebuild navItems so each visible page has an internal link. Saved as draft only; call site.publish to go live. Reference a logoOverride image as asset:<assetId>. Errors: FORBIDDEN, WEBSITE_NOT_FOUND, HEADER_NOT_FOUND, VALIDATION (details lists the failing field), CONFLICT, WRITE_FROZEN, ASSET_NOT_FOUND (details.assetIds: not in this site's media library), ASSET_NOT_ALLOWED (product files cannot be shown on pages).
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Request body
ifUnmodifiedSincestringrequiredcontentUpdatedAt from globals.get. Required: the write is rejected with CONFLICT when the site-level draft changed since (details.contentUpdatedAt holds the current value).
keystringHeader key to replace (default 'primary'; pass a secondary header key from globals.list_headers to replace that header).
headerobjectrequiredComplete header object. navItems is the navigation: one { id, text, linkType: "internal", pageSlug } per visible page (the header never lists pages automatically); keep text short (1-3 words) since it has to fit a single desktop row — it is not the page title. Use linkType: "group" to nest related pages under one dropdown instead of adding many top-level items (desktop headers work best with 7 or fewer top-level items). Use ctaIds (up to 2) to show buttons from siteSettings.customButtons. layout picks the desktop arrangement (top-spread, top-left, top-center, top-stacked, side-left) — top-stacked puts navigation on its own full-width row below the logo/CTA row and suits sites with many nav items; surface sets the background tone; showBrandLogo / showSiteName / logoSize control the brand slot and showSocialLinks (boolean or per device) plus hiddenSocialLinkUrls choose which social links appear; utilities orders and toggles the feature buttons (search, cart) after the CTA buttons. The logo comes from the website's brand settings unless logoOverride is set.
header.type"header"requiredheader.idstringrequiredStable id; pages reference it via globalHeaderId.
header.keystringHuman-readable key for this header (e.g. 'primary', 'campaign', 'docs').
header.ctaobjectheader.cta.idstringheader.cta.icon"briefcase" | "star" | "award" | "crown" | "flame" | "zap" | "target" | "rocket" | "flag" | "gem" | "diamond" | "scroll" | "fingerprint" | "smile" | "laugh" | "clock" | "phone" | "mail" | "bell" | "settings" | "check-circle" | "info" | "help-circle" | "headset" | "megaphone" | "newspaper" | "hourglass" | "stamp" | "milestone" | "quote" | "table" | "list-ordered" | "list-checks" | "arrow-right" | "message-circle" | "external-link" | "download" | "play" | "pause" | "bookmark" | "search" | "filter" | "thumbs-up" | "share-2" | "eye" | "phone-call" | "send" | "lock" | "rotate-ccw" | "clipboard-check" | "alarm-clock" | "utensils" | "utensils-crossed" | "chef-hat" | "coffee" | "pizza" | "soup" | "ice-cream-cone" | "sandwich" | "beef" | "fish" | "salad" | "cookie" | "cake" | "cake-slice" | "dessert" | "cup-soda" | "wine" | "beer" | "martini" | "milk" | "wheat" | "egg" | "croissant" | "popcorn" | "candy" | "apple" | "cherry" | "banana" | "citrus" | "grape" | "carrot" | "drumstick" | "cooking-pot" | "shrimp" | "donut" | "bean" | "vegan" | "store" | "shopping-bag" | "shopping-cart" | "shopping-basket" | "package" | "package-check" | "boxes" | "truck" | "motorbike" | "warehouse" | "tag" | "tags" | "ticket-percent" | "barcode" | "qr-code" | "scan-qr-code" | "credit-card" | "smartphone-nfc" | "wallet" | "banknote" | "coins" | "dollar-sign" | "percent" | "badge-percent" | "receipt" | "shirt" | "heart" | "heart-pulse" | "stethoscope" | "hospital" | "syringe" | "pill" | "pill-bottle" | "bandage" | "cross" | "thermometer" | "briefcase-medical" | "scissors" | "sparkles" | "scan-face" | "hand" | "bath" | "droplet" | "droplets" | "flower" | "flower-2" | "sun" | "moon" | "book-open" | "book-text" | "book-copy" | "book-marked" | "book-check" | "graduation-cap" | "school" | "library" | "monitor-play" | "backpack" | "pencil" | "pen-tool" | "file-text" | "scroll-text" | "notebook-pen" | "languages" | "calculator" | "presentation" | "lightbulb" | "brain" | "puzzle" | "laptop" | "monitor" | "smartphone" | "tablet" | "code" | "code-2" | "terminal" | "server" | "database" | "cloud" | "cpu" | "globe" | "network" | "circuit-board" | "brain-circuit" | "bot" | "blocks" | "palette" | "brush" | "paint-bucket" | "pen-line" | "image" | "image-plus" | "camera" | "video" | "film" | "clapperboard" | "music" | "music-2" | "music-4" | "mic" | "mic-2" | "headphones" | "speaker" | "radio" | "podcast" | "piano" | "plane" | "map-pin" | "map-pinned" | "navigation" | "route" | "compass" | "mountain" | "tree-pine" | "trees" | "tent" | "umbrella" | "anchor" | "ship" | "car" | "bike" | "bus" | "train" | "luggage" | "hotel" | "bed-double" | "concierge-bell" | "wifi" | "parking-square" | "air-vent" | "washing-machine" | "cigarette-off" | "accessibility" | "dumbbell" | "biceps-flexed" | "footprints" | "timer" | "watch" | "medal" | "trophy" | "swords" | "badge-check" | "activity" | "building" | "building-2" | "factory" | "house" | "house-plus" | "map-pin-house" | "door-open" | "door-closed" | "key" | "key-round" | "fence" | "sofa" | "ruler" | "hard-hat" | "hammer" | "wrench" | "paint-roller" | "brush-cleaning" | "cat" | "dog" | "bird" | "rabbit" | "squirrel" | "paw-print" | "bone" | "leaf" | "sprout" | "clover" | "tractor" | "cloud-sun" | "cloud-rain" | "snowflake" | "leafy-green" | "tree-deciduous" | "wind" | "waves" | "recycle" | "landmark" | "vault" | "scale" | "gavel" | "shield" | "shield-check" | "badge-dollar-sign" | "hand-coins" | "trending-up" | "trending-down" | "bar-chart" | "bar-chart-2" | "bar-chart-3" | "pie-chart" | "line-chart" | "chart-no-axes-combined" | "users" | "users-round" | "user-circle" | "user-plus" | "hand-heart" | "hand-helping" | "heart-handshake" | "handshake" | "baby" | "church" | "party-popper" | "sparkle" | "gift" | "ticket" | "calendar" | "calendar-days" | "calendar-check" | "calendar-clock"header.cta.textstringheader.cta.urlstringOptional link: absolute http(s)/tel:/mailto: URL, site-relative path (/about) or anchor (#id).
header.cta.style"brand" | "default" | "ghost"header.ctaIdstringLegacy single button id from siteSettings.customButtons. Prefer ctaIds; when both are set ctaIds wins.
header.ctaIdsstring[]Up to 2 ids of buttons defined in siteSettings.customButtons, shown at the right of the header (and at the bottom of the side-left sidebar / mobile menu).
header.ctaStyleByIdobjectPer-button style override keyed by customButton id: brand (filled brand color), default (neutral), or ghost (text with arrow).
header.layout"top-spread" | "top-left" | "top-center" | "top-stacked" | "side-left"Desktop header layout: top-spread (default), top-left (nav next to logo), top-center (centered nav), top-stacked (nav on its own full-width row below the logo/CTA row; best for many nav items or long labels), or side-left (fixed left sidebar).
header.surface"auto" | "default" | "muted" | "tint" | "brand" | "contrast"Header background tone: default (light bar with blur), muted, tint, brand or contrast; text colors adapt automatically. auto behaves like default.
header.showBrandLogobooleanShow the brand logo (default true). When false and showSiteName is false, nothing is rendered in the brand slot.
header.showSiteNamebooleanShow the website name next to (or instead of) the logo (default false; the name is still shown when no logo exists).
header.logoSize"sm" | "md" | "lg"Logo size in the header (default md).
header.showSocialLinksboolean | objectShow siteSettings.socialLinks in the header, either for every device (boolean) or per device. Defaults: desktop only for the side-left layout, tablet and mobile menu on.
header.showSocialLinks.desktopbooleanheader.showSocialLinks.tabletbooleanheader.showSocialLinks.mobilebooleanheader.hiddenSocialLinkUrlsstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDeviceobjectPer-device blacklist of social link urls; a device without its own list falls back to hiddenSocialLinkUrls.
header.hiddenSocialLinkUrlsByDevice.desktopstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDevice.tabletstring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.hiddenSocialLinkUrlsByDevice.mobilestring[]Urls from siteSettings.socialLinks to hide in this section (blacklist; omitted or empty shows all).
header.variant"solid" | "transparent" | "glass"Deprecated and ignored: the header background is controlled by surface. Accepted for backward compatibility.
header.shrinkOnScrollbooleanCompact the header after scrolling (default true).
header.showProgressBarbooleanheader.showAccentLinebooleanShow a thin brand-gradient line at the bottom edge (default false).
header.isVisiblebooleanheader.navItemsobject[]Navigation links. The header never lists pages automatically; add one internal item per visible page.
header.navItems[].idstringrequiredheader.navItems[].textstringrequiredheader.navItems[].linkType"internal" | "external" | "group"requiredheader.navItems[].pageSlugstringheader.navItems[].anchorIdstringheader.navItems[].externalUrlstringOptional link: absolute http(s)/tel:/mailto: URL, site-relative path (/about) or anchor (#id).
header.navItems[].openInNewTabbooleanheader.navItems[].childrenobject[]header.navItems[].linkobjectheader.utilitiesobject[]Header utility buttons (site features shown at the right of the header, after the CTA buttons), in display order; each id at most once. enabled shows or hides it; an omitted id keeps its default (search: off, cart: on, language: on, account: on; newly created sites default all to on). A utility only renders when the site has that feature: search needs a published site with searchable content; cart needs the shopping cart turned on in store settings and at least one active product; language needs at least two published site languages; account needs the customer sign-in entry turned on under Settings › Customer accounts (signed-in customers always see it). On phones only the first 2 visible utilities stay next to the menu button; the rest move to the top of the mobile menu.
header.utilities[].id"search" | "cart" | "language" | "account"requiredsearch: site search button; cart: shopping cart button; language: language switcher; account: customer sign-in / account panel.
header.utilities[].enabledbooleanrequiredheader.isGlobalbooleanheader.logoOverrideanyHeader-specific logo (e.g. a wide wordmark). Omit to use the website's brand logo.
Response 200
headerobjectrequiredHeader as stored (id may differ from the one sent when the site already had one).
assetsobjectrequiredThe media-library files referenced as asset:<assetId>, by assetId.
contentUpdatedAtstring | nullrequiredRevision marker of the site-level draft (Website.contentUpdatedAt). Pass it back as ifUnmodifiedSince.
warningsobject[]requiredContent-quality warnings about navItems: long labels or too many top-level items. These are fixed content rules, not a prediction of whether the header will overflow at some width — the renderer always collapses items that do not fit into a "more" menu, so the site never breaks either way. Empty array when there is nothing to flag.
warnings[].code"NAV_LABEL_TOO_LONG" | "NAV_TOO_MANY_ITEMS"requiredwarnings[].messagestringrequiredwarnings[].navItemIdsstring[]ids of the navItems the warning is about, when applicable.
Errors
FORBIDDEN403WEBSITE_NOT_FOUND404HEADER_NOT_FOUND404VALIDATION400 · details lists the failing fieldCONFLICT409WRITE_FROZEN503ASSET_NOT_FOUND404 · details.assetIds: not in this site's media libraryASSET_NOT_ALLOWED422 · product files cannot be shown on pages
MCP tool globals_replace_header
curl -X PUT "https://app.kanorio.com/api/v1/sites/{id}/globals/header" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ifUnmodifiedSince":"2026-10-06T08:00:00.000Z","header":{"id":"sec_header01","type":"header","navItems":[{"id":"nav_home","text":"Home","linkType":"internal","pageSlug":"/"},{"id":"nav_about","text":"About Us","linkType":"internal","pageSlug":"/about"}],"ctaIds":["btn_order"]}}'{
"header": {
"id": "sec_header01",
"type": "header",
"navItems": [
{
"id": "nav_home",
"text": "Home",
"linkType": "internal",
"pageSlug": "/"
},
{
"id": "nav_about",
"text": "About Us",
"linkType": "internal",
"pageSlug": "/about"
}
],
"ctaIds": [
"btn_order"
]
},
"assets": {},
"contentUpdatedAt": "2026-10-06T08:00:00.000Z",
"warnings": []
}