Kanorio

API 參考

Pages

Management API: GET /sites/{id}/pages, POST /sites/{id}/pages, PUT /sites/{id}/pages/order, …

這頁只有英文版。API 參考、Webhook 事件與變更紀錄維持英文,和程式碼裡的欄位名稱、錯誤碼一致。
Base URL https://app.kanorio.com/api/v1ErrorsPagination

List pages

GET/sites/{id}/pages
betaeditor:enterdefault (120/minute per token)

List the pages of a website (home page first), with slug, visibility, SEO fields, systemManaged, lockedCoreSectionTypes and the revision marker updatedAt. Sections are not included; use pages.get. Per-product pages are not included; product copy, SEO and publish state live on products.*. For the whole page tree in one call use sites.structure. Errors: FORBIDDEN, INVALID_CURSOR.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • limitinteger · query

    Maximum number of items to return, 1–100. Defaults to 20.

  • cursorstring · query

    Opaque cursor from the previous page's nextCursor. Omit for the first page.

Response 200

  • dataobject[]required
  • data[].idstringrequired
  • data[].slugstringrequired

    URL path, "/" for the home page.

  • data[].pathstring[]required

    Path segments (e.g. ["services", "haircut"] for "/services/haircut"; [] for "/").

  • data[].parentSlugstring | nullrequired

    Immediate parent page slug for generic nested pages (e.g. "/services" for "/services/haircut"; null for "/", top-level pages, and system pages such as blog/shop/product/legal).

  • data[].isDirectorybooleanrequired

    True when this is a hidden folder page that exists to group subpage URLs.

  • data[].depthintegerrequired

    Hierarchy depth: 0 for home page, 1 for top-level pages, up to 3.

  • data[].ancestorsobject[]required

    Visible ancestor pages from root to immediate parent (only generic pages participate; system pages such as blog, shop, product, and legal always return []).

  • data[].ancestors[].idstringrequired
  • data[].ancestors[].slugstringrequired
  • data[].ancestors[].titlestringrequired
  • data[].breadcrumbsobject[]required

    Visible breadcrumb trail shown on the page and in BreadcrumbList JSON-LD (up to 4 items; empty when the page has no visible ancestors or is a system page).

  • data[].breadcrumbs[].namestringrequired
  • data[].breadcrumbs[].urlstringrequired
  • data[].breadcrumbSource"url" | "custom"required

    Whether breadcrumbs follow the URL hierarchy ("url") or a custom breadcrumbParentSlug override ("custom").

  • data[].breadcrumbParentSlugstring | nullrequired

    Optional parent page slug override for breadcrumbs and structured data only.

  • data[].titlestringrequired
  • data[].pageTypestringrequired
  • data[].isHomePagebooleanrequired
  • data[].isVisiblebooleanrequired

    Hidden pages are not published or linked from navigation.

  • data[].orderintegerrequired
  • data[].globalHeaderIdstring | nullrequired
  • data[].globalFooterIdstring | nullrequired
  • data[].updatedAtstringrequired

    Revision marker. Pass it back as ifUnmodifiedSince when replacing sections.

  • data[].seoobjectrequired
  • data[].seo.seoTitlestring | nullrequired
  • data[].seo.seoDescriptionstring | nullrequired
  • data[].seo.seoKeywordsstring[] | nullrequired
  • data[].seo.ogTitlestring | nullrequired
  • data[].seo.ogDescriptionstring | nullrequired
  • data[].seo.ogImagestring | nullrequired

    Share image display URL (changes with versions; do not store it).

  • data[].seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • data[].seo.ogImageFramingobject | null
  • data[].seo.canonicalUrlstring | nullrequired
  • data[].seo.robotsIndexstring | nullrequired
  • data[].seo.robotsFollowstring | nullrequired
  • data[].seo.excludeFromSiteSearchbooleanrequired

    When true, this page is excluded from visitor site search (independent of robotsIndex).

  • data[].systemManagedbooleanrequired

    True when Kanorio owns this page (shop index, blog index, taxonomy templates). Those pages cannot be created or deleted.

  • data[].lockedCoreSectionTypesstring[]required

    Section types locked at index 0. pages.replace_sections must keep exactly one of each, with its locked source. Empty for ordinary pages.

  • hasMorebooleanrequired

    True when another page exists; pass nextCursor to fetch it.

  • nextCursorstring | nullrequired

    Cursor for the next page, or null on the last page.

Errors

  • FORBIDDEN 403
  • INVALID_CURSOR 400

MCP tool pages_list

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/pages" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "data": [
    {
      "id": "pg_example456",
      "slug": "/",
      "path": [],
      "parentSlug": null,
      "isDirectory": false,
      "depth": 0,
      "ancestors": [],
      "breadcrumbs": [],
      "breadcrumbSource": "url",
      "breadcrumbParentSlug": null,
      "title": "Home",
      "pageType": "generic",
      "isHomePage": true,
      "isVisible": true,
      "order": 0,
      "globalHeaderId": "sec_header01",
      "globalFooterId": "sec_footer01",
      "updatedAt": "2026-10-06T08:00:00.000Z",
      "seo": {
        "seoTitle": "Sunny Bakery",
        "seoDescription": "Artisan sourdough bakery in Taipei.",
        "seoKeywords": [
          "sourdough",
          "artisan bakery"
        ],
        "ogTitle": null,
        "ogDescription": null,
        "ogImage": null,
        "ogImageAssetId": null,
        "ogImageFraming": null,
        "canonicalUrl": null,
        "robotsIndex": null,
        "robotsFollow": null,
        "excludeFromSiteSearch": false
      },
      "systemManaged": false,
      "lockedCoreSectionTypes": []
    },
    {
      "id": "pg_example789",
      "slug": "/about",
      "path": [
        "about"
      ],
      "parentSlug": null,
      "isDirectory": false,
      "depth": 1,
      "ancestors": [],
      "breadcrumbs": [],
      "breadcrumbSource": "url",
      "breadcrumbParentSlug": null,
      "title": "About Us",
      "pageType": "generic",
      "isHomePage": false,
      "isVisible": true,
      "order": 1,
      "globalHeaderId": "sec_header01",
      "globalFooterId": "sec_footer01",
      "updatedAt": "2026-10-06T08:00:00.000Z",
      "seo": {
        "seoTitle": "About Us | Sunny Bakery",
        "seoDescription": "Naturally leavened sourdough baked fresh every morning.",
        "seoKeywords": [
          "sourdough",
          "artisan bakery"
        ],
        "ogTitle": null,
        "ogDescription": null,
        "ogImage": null,
        "ogImageAssetId": null,
        "ogImageFraming": null,
        "canonicalUrl": null,
        "robotsIndex": null,
        "robotsFollow": null,
        "excludeFromSiteSearch": false
      },
      "systemManaged": false,
      "lockedCoreSectionTypes": []
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

Create a page

POST/sites/{id}/pages
betacontent:editdefault (120/minute per token)

Create an empty page (up to 3 levels deep). Pass parentSlug (e.g. "/services") plus the last segment in slug (e.g. "/haircut") rather than concatenating multi-segment paths yourself; if the parent page does not exist yet, a hidden folder page is created automatically. Omit slug to have one generated from the title. The home page ("/") already exists and cannot be created; link-in-bio pages have a dedicated flow. The new page uses the home page's header and footer unless you pass globalHeaderId/globalFooterId. It is not added to the navigation automatically: after creating pages, call globals.replace_header with a navItem per visible page (use a short label, not the page title). pageType cannot be a system page (shop, blog, taxonomy templates) or link-in-bio; Kanorio creates those. Passing one returns SYSTEM_PAGE_LOCKED. Fill the page afterwards with pages.replace_sections. Errors: FORBIDDEN, VALIDATION, SLUG_TAKEN, RESERVED_SLUG, RESERVED_SEGMENT, SEGMENT_TOO_LONG, DEPTH_EXCEEDED, PARENT_NOT_ALLOWED, BREADCRUMB_PARENT_INVALID, HOME_NOT_CREATABLE, LINK_IN_BIO_DEDICATED_ENTRY, SYSTEM_PAGE_LOCKED, PAGE_LIMIT_REACHED.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

Request body

  • titlestringrequired

    Page title; also used for navigation labels.

  • slugstring

    Last URL segment starting with "/" (e.g. "/haircut" when parentSlug is "/services"), or full path (e.g. "/about"). Generated from title when omitted.

  • parentSlugstring | null

    Optional parent page slug (e.g. "/services"). Pass parentSlug + last segment instead of concatenating "/a/b" yourself.

  • breadcrumbParentSlugstring | null

    Optional parent page slug override for breadcrumbs and BreadcrumbList JSON-LD only (use only when the typical user trail differs from the URL path; does not change the URL).

  • pageType"generic" | "article" | "legal-cookie-policy" | "legal-privacy-policy" | "legal-terms-of-service" | "legal-purchase-terms" | "legal-return-policy" | "legal-disclaimer"

    Defaults to generic. System pages (shop, blog, taxonomy templates) and link-in-bio cannot be created here.

  • isVisibleboolean

    Defaults to true. Hidden pages are not published.

  • globalHeaderIdstring | null

    Header from globalSections. Defaults to the home page's header; pass null for a page without a header.

  • globalFooterIdstring | null

    Footer from globalSections. Defaults to the home page's footer; pass null for a page without a footer.

  • seoTitlestring
  • seoDescriptionstring

Response 201

  • idstringrequired
  • slugstringrequired

    URL path, "/" for the home page.

  • pathstring[]required

    Path segments (e.g. ["services", "haircut"] for "/services/haircut"; [] for "/").

  • parentSlugstring | nullrequired

    Immediate parent page slug for generic nested pages (e.g. "/services" for "/services/haircut"; null for "/", top-level pages, and system pages such as blog/shop/product/legal).

  • isDirectorybooleanrequired

    True when this is a hidden folder page that exists to group subpage URLs.

  • depthintegerrequired

    Hierarchy depth: 0 for home page, 1 for top-level pages, up to 3.

  • ancestorsobject[]required

    Visible ancestor pages from root to immediate parent (only generic pages participate; system pages such as blog, shop, product, and legal always return []).

  • ancestors[].idstringrequired
  • ancestors[].slugstringrequired
  • ancestors[].titlestringrequired
  • breadcrumbsobject[]required

    Visible breadcrumb trail shown on the page and in BreadcrumbList JSON-LD (up to 4 items; empty when the page has no visible ancestors or is a system page).

  • breadcrumbs[].namestringrequired
  • breadcrumbs[].urlstringrequired
  • breadcrumbSource"url" | "custom"required

    Whether breadcrumbs follow the URL hierarchy ("url") or a custom breadcrumbParentSlug override ("custom").

  • breadcrumbParentSlugstring | nullrequired

    Optional parent page slug override for breadcrumbs and structured data only.

  • titlestringrequired
  • pageTypestringrequired
  • isHomePagebooleanrequired
  • isVisiblebooleanrequired

    Hidden pages are not published or linked from navigation.

  • orderintegerrequired
  • globalHeaderIdstring | nullrequired
  • globalFooterIdstring | nullrequired
  • updatedAtstringrequired

    Revision marker. Pass it back as ifUnmodifiedSince when replacing sections.

  • seoobjectrequired
  • seo.seoTitlestring | nullrequired
  • seo.seoDescriptionstring | nullrequired
  • seo.seoKeywordsstring[] | nullrequired
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL (changes with versions; do not store it).

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.ogImageFramingobject | null
  • seo.ogImageFraming.focusobject
  • seo.ogImageFraming.screensobject
  • seo.ogImageFraming.fitMode"contain" | "cover"
  • seo.ogImageFraming.padColorstring
  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndexstring | nullrequired
  • seo.robotsFollowstring | nullrequired
  • seo.excludeFromSiteSearchbooleanrequired

    When true, this page is excluded from visitor site search (independent of robotsIndex).

  • systemManagedbooleanrequired

    True when Kanorio owns this page (shop index, blog index, taxonomy templates). Those pages cannot be created or deleted.

  • lockedCoreSectionTypesstring[]required

    Section types locked at index 0. pages.replace_sections must keep exactly one of each, with its locked source. Empty for ordinary pages.

  • warningsstring[]

    Non-fatal warnings from this write (e.g. REDIRECT_SHADOWS_PAGE when a manual redirect intercepts this URL).

Errors

  • FORBIDDEN 403
  • VALIDATION 400
  • SLUG_TAKEN 409
  • RESERVED_SLUG 422
  • RESERVED_SEGMENT 422
  • SEGMENT_TOO_LONG 422
  • DEPTH_EXCEEDED 422
  • PARENT_NOT_ALLOWED 422
  • BREADCRUMB_PARENT_INVALID 422
  • HOME_NOT_CREATABLE 422
  • LINK_IN_BIO_DEDICATED_ENTRY 422
  • SYSTEM_PAGE_LOCKED 422
  • PAGE_LIMIT_REACHED 422

MCP tool pages_create

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/pages" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"About Us","slug":"/about","isVisible":true}'
Response
{
  "id": "pg_example789",
  "slug": "/about",
  "path": [
    "about"
  ],
  "parentSlug": null,
  "isDirectory": false,
  "depth": 1,
  "ancestors": [],
  "breadcrumbs": [],
  "breadcrumbSource": "url",
  "breadcrumbParentSlug": null,
  "title": "About Us",
  "pageType": "generic",
  "isHomePage": false,
  "isVisible": true,
  "order": 1,
  "globalHeaderId": "sec_header01",
  "globalFooterId": "sec_footer01",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "seo": {
    "seoTitle": "About Us | Sunny Bakery",
    "seoDescription": "Naturally leavened sourdough baked fresh every morning.",
    "seoKeywords": [
      "sourdough",
      "artisan bakery"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "ogImageFraming": null,
    "canonicalUrl": null,
    "robotsIndex": null,
    "robotsFollow": null,
    "excludeFromSiteSearch": false
  },
  "systemManaged": false,
  "lockedCoreSectionTypes": []
}

Reorder pages

PUT/sites/{id}/pages/order
betacontent:editdefault (120/minute per token)

Set the order of all non-home pages (the home page is always first). Order drives the page list in the console; navigation links come from the header's navItems, which you manage with globals.replace_header. pageIds must list every non-home page from pages.list exactly once; legal pages created with the site count too. Legacy per-product pages are omitted and keep their current position. Errors: FORBIDDEN, FOREIGN_PAGE (an id is not a page of this site), HOME_NOT_SORTABLE (home page included), INCOMPLETE_ORDER (some pages missing or duplicated).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

Request body

  • pageIdsstring[]required

    All non-home page ids in the desired order.

Response 200

  • pagesobject[]required
  • pages[].idstringrequired
  • pages[].slugstringrequired

    URL path, "/" for the home page.

  • pages[].pathstring[]required

    Path segments (e.g. ["services", "haircut"] for "/services/haircut"; [] for "/").

  • pages[].parentSlugstring | nullrequired

    Immediate parent page slug for generic nested pages (e.g. "/services" for "/services/haircut"; null for "/", top-level pages, and system pages such as blog/shop/product/legal).

  • pages[].isDirectorybooleanrequired

    True when this is a hidden folder page that exists to group subpage URLs.

  • pages[].depthintegerrequired

    Hierarchy depth: 0 for home page, 1 for top-level pages, up to 3.

  • pages[].ancestorsobject[]required

    Visible ancestor pages from root to immediate parent (only generic pages participate; system pages such as blog, shop, product, and legal always return []).

  • pages[].ancestors[].idstringrequired
  • pages[].ancestors[].slugstringrequired
  • pages[].ancestors[].titlestringrequired
  • pages[].breadcrumbsobject[]required

    Visible breadcrumb trail shown on the page and in BreadcrumbList JSON-LD (up to 4 items; empty when the page has no visible ancestors or is a system page).

  • pages[].breadcrumbs[].namestringrequired
  • pages[].breadcrumbs[].urlstringrequired
  • pages[].breadcrumbSource"url" | "custom"required

    Whether breadcrumbs follow the URL hierarchy ("url") or a custom breadcrumbParentSlug override ("custom").

  • pages[].breadcrumbParentSlugstring | nullrequired

    Optional parent page slug override for breadcrumbs and structured data only.

  • pages[].titlestringrequired
  • pages[].pageTypestringrequired
  • pages[].isHomePagebooleanrequired
  • pages[].isVisiblebooleanrequired

    Hidden pages are not published or linked from navigation.

  • pages[].orderintegerrequired
  • pages[].globalHeaderIdstring | nullrequired
  • pages[].globalFooterIdstring | nullrequired
  • pages[].updatedAtstringrequired

    Revision marker. Pass it back as ifUnmodifiedSince when replacing sections.

  • pages[].seoobjectrequired
  • pages[].seo.seoTitlestring | nullrequired
  • pages[].seo.seoDescriptionstring | nullrequired
  • pages[].seo.seoKeywordsstring[] | nullrequired
  • pages[].seo.ogTitlestring | nullrequired
  • pages[].seo.ogDescriptionstring | nullrequired
  • pages[].seo.ogImagestring | nullrequired

    Share image display URL (changes with versions; do not store it).

  • pages[].seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • pages[].seo.ogImageFramingobject | null
  • pages[].seo.canonicalUrlstring | nullrequired
  • pages[].seo.robotsIndexstring | nullrequired
  • pages[].seo.robotsFollowstring | nullrequired
  • pages[].seo.excludeFromSiteSearchbooleanrequired

    When true, this page is excluded from visitor site search (independent of robotsIndex).

  • pages[].systemManagedbooleanrequired

    True when Kanorio owns this page (shop index, blog index, taxonomy templates). Those pages cannot be created or deleted.

  • pages[].lockedCoreSectionTypesstring[]required

    Section types locked at index 0. pages.replace_sections must keep exactly one of each, with its locked source. Empty for ordinary pages.

Errors

  • FORBIDDEN 403
  • FOREIGN_PAGE 422 · an id is not a page of this site
  • HOME_NOT_SORTABLE 422 · home page included
  • INCOMPLETE_ORDER 400 · some pages missing or duplicated

MCP tool pages_reorder

curl -X PUT "https://app.kanorio.com/api/v1/sites/{id}/pages/order" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pageIds":["pg_example789"]}'
Response
{
  "pages": [
    {
      "id": "pg_example456",
      "slug": "/",
      "path": [],
      "parentSlug": null,
      "isDirectory": false,
      "depth": 0,
      "ancestors": [],
      "breadcrumbs": [],
      "breadcrumbSource": "url",
      "breadcrumbParentSlug": null,
      "title": "Home",
      "pageType": "generic",
      "isHomePage": true,
      "isVisible": true,
      "order": 0,
      "globalHeaderId": "sec_header01",
      "globalFooterId": "sec_footer01",
      "updatedAt": "2026-10-06T08:00:00.000Z",
      "seo": {
        "seoTitle": "Sunny Bakery",
        "seoDescription": "Artisan sourdough bakery in Taipei.",
        "seoKeywords": [
          "sourdough",
          "artisan bakery"
        ],
        "ogTitle": null,
        "ogDescription": null,
        "ogImage": null,
        "ogImageAssetId": null,
        "ogImageFraming": null,
        "canonicalUrl": null,
        "robotsIndex": null,
        "robotsFollow": null,
        "excludeFromSiteSearch": false
      },
      "systemManaged": false,
      "lockedCoreSectionTypes": []
    },
    {
      "id": "pg_example789",
      "slug": "/about",
      "path": [
        "about"
      ],
      "parentSlug": null,
      "isDirectory": false,
      "depth": 1,
      "ancestors": [],
      "breadcrumbs": [],
      "breadcrumbSource": "url",
      "breadcrumbParentSlug": null,
      "title": "About Us",
      "pageType": "generic",
      "isHomePage": false,
      "isVisible": true,
      "order": 1,
      "globalHeaderId": "sec_header01",
      "globalFooterId": "sec_footer01",
      "updatedAt": "2026-10-06T08:00:00.000Z",
      "seo": {
        "seoTitle": "About Us | Sunny Bakery",
        "seoDescription": "Naturally leavened sourdough baked fresh every morning.",
        "seoKeywords": [
          "sourdough",
          "artisan bakery"
        ],
        "ogTitle": null,
        "ogDescription": null,
        "ogImage": null,
        "ogImageAssetId": null,
        "ogImageFraming": null,
        "canonicalUrl": null,
        "robotsIndex": null,
        "robotsFollow": null,
        "excludeFromSiteSearch": false
      },
      "systemManaged": false,
      "lockedCoreSectionTypes": []
    }
  ]
}

Retrieve a page

GET/sites/{id}/pages/{pageId}
betaeditor:enterdefault (120/minute per token)

Get one page including its current draft sections, hierarchy metadata (path, parentSlug, isDirectory, depth, ancestors, breadcrumbs, breadcrumbSource), systemManaged, lockedCoreSectionTypes and updatedAt. Always read the page right before pages.replace_sections and pass updatedAt back as ifUnmodifiedSince. Images and files of the site's media library appear as asset:<assetId> in sections; assets holds them (with display URLs). Per-product pages return PAGE_NOT_FOUND; use products.get. On a system page, keep the locked core section at index 0 and do not change its source. Errors: FORBIDDEN, PAGE_NOT_FOUND.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • pageIdstring · pathrequired

    Page id. Get it from pages.list.

Response 200

  • idstringrequired
  • slugstringrequired

    URL path, "/" for the home page.

  • pathstring[]required

    Path segments (e.g. ["services", "haircut"] for "/services/haircut"; [] for "/").

  • parentSlugstring | nullrequired

    Immediate parent page slug for generic nested pages (e.g. "/services" for "/services/haircut"; null for "/", top-level pages, and system pages such as blog/shop/product/legal).

  • isDirectorybooleanrequired

    True when this is a hidden folder page that exists to group subpage URLs.

  • depthintegerrequired

    Hierarchy depth: 0 for home page, 1 for top-level pages, up to 3.

  • ancestorsobject[]required

    Visible ancestor pages from root to immediate parent (only generic pages participate; system pages such as blog, shop, product, and legal always return []).

  • ancestors[].idstringrequired
  • ancestors[].slugstringrequired
  • ancestors[].titlestringrequired
  • breadcrumbsobject[]required

    Visible breadcrumb trail shown on the page and in BreadcrumbList JSON-LD (up to 4 items; empty when the page has no visible ancestors or is a system page).

  • breadcrumbs[].namestringrequired
  • breadcrumbs[].urlstringrequired
  • breadcrumbSource"url" | "custom"required

    Whether breadcrumbs follow the URL hierarchy ("url") or a custom breadcrumbParentSlug override ("custom").

  • breadcrumbParentSlugstring | nullrequired

    Optional parent page slug override for breadcrumbs and structured data only.

  • titlestringrequired
  • pageTypestringrequired
  • isHomePagebooleanrequired
  • isVisiblebooleanrequired

    Hidden pages are not published or linked from navigation.

  • orderintegerrequired
  • globalHeaderIdstring | nullrequired
  • globalFooterIdstring | nullrequired
  • updatedAtstringrequired

    Revision marker. Pass it back as ifUnmodifiedSince when replacing sections.

  • seoobjectrequired
  • seo.seoTitlestring | nullrequired
  • seo.seoDescriptionstring | nullrequired
  • seo.seoKeywordsstring[] | nullrequired
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL (changes with versions; do not store it).

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.ogImageFramingobject | null
  • seo.ogImageFraming.focusobject
  • seo.ogImageFraming.screensobject
  • seo.ogImageFraming.fitMode"contain" | "cover"
  • seo.ogImageFraming.padColorstring
  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndexstring | nullrequired
  • seo.robotsFollowstring | nullrequired
  • seo.excludeFromSiteSearchbooleanrequired

    When true, this page is excluded from visitor site search (independent of robotsIndex).

  • sectionsobject[]required

    Current draft sections (what the editor shows), not the published copy. Media-library files appear as asset:<assetId>.

  • assetsobjectrequired

    The media-library files the sections use, by assetId.

  • systemManagedbooleanrequired

    True when Kanorio owns this page (shop index, blog index, taxonomy templates). Those pages cannot be created or deleted.

  • lockedCoreSectionTypesstring[]required

    Section types locked at index 0. pages.replace_sections must keep exactly one of each, with its locked source. Empty for ordinary pages.

Errors

  • FORBIDDEN 403
  • PAGE_NOT_FOUND 404

MCP tool pages_get

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/pages/{pageId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "pg_example456",
  "slug": "/",
  "path": [],
  "parentSlug": null,
  "isDirectory": false,
  "depth": 0,
  "ancestors": [],
  "breadcrumbs": [],
  "breadcrumbSource": "url",
  "breadcrumbParentSlug": null,
  "title": "Home",
  "pageType": "generic",
  "isHomePage": true,
  "isVisible": true,
  "order": 0,
  "globalHeaderId": "sec_header01",
  "globalFooterId": "sec_footer01",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "seo": {
    "seoTitle": "Sunny Bakery",
    "seoDescription": "Artisan sourdough bakery in Taipei.",
    "seoKeywords": [
      "sourdough",
      "artisan bakery"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "ogImageFraming": null,
    "canonicalUrl": null,
    "robotsIndex": null,
    "robotsFollow": null,
    "excludeFromSiteSearch": false
  },
  "systemManaged": false,
  "lockedCoreSectionTypes": [],
  "sections": [
    {
      "id": "sec_hero01",
      "type": "hero",
      "title": "Freshly baked sourdough every morning",
      "subtitle": "Natural starter, local grain. Doors open at 7 a.m.",
      "image": "asset:asset_example01",
      "ctaIds": [
        "btn_order"
      ]
    },
    {
      "id": "sec_faq01",
      "type": "faq",
      "title": "Frequently Asked Questions",
      "items": [
        {
          "question": "Can I pre-order loaves?",
          "answer": "Yes, place pre-orders by 5 p.m. the day before."
        }
      ]
    }
  ],
  "assets": {
    "asset_example01": {
      "assetId": "asset_example01",
      "kind": "image",
      "visibility": "public",
      "tags": [],
      "processing": null,
      "status": "active",
      "missing": false,
      "version": 1,
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "thumbnailUrl": null,
      "fileName": "sunny-bakery-hero.jpg",
      "mimeType": "image/jpeg",
      "bytes": 482133,
      "streaming": "none",
      "billableBytes": 482133,
      "width": 2400,
      "height": 1600,
      "durationSeconds": null,
      "pageCount": null,
      "source": "IMAGE_CONTENT",
      "inUse": true,
      "focus": null,
      "edgeColor": null,
      "altText": null,
      "watermarkExempt": false,
      "createdAt": "2026-10-01T02:30:00.000Z"
    }
  }
}

Update a page

PATCH/sites/{id}/pages/{pageId}
betacontent:editdefault (120/minute per token)

Update a page's properties: title, slug, parentSlug, createRedirect, breadcrumbParentSlug, visibility, header/footer reference, SEO fields (seoTitle, seoDescription, seoKeywords, og*, canonicalUrl, robots*) and excludeFromSiteSearch. Only the fields you send change; sections are untouched (use pages.replace_sections). Nullable fields (parentSlug, breadcrumbParentSlug, globalHeaderId, globalFooterId, ogImageAssetId) can be cleared by passing null; all other fields can only be replaced, not cleared. Slug, parentSlug and visibility changes take effect on the published site immediately; renaming automatically updates descendant subpages and creates 301 redirects for previously published pages unless createRedirect is false. Errors: FORBIDDEN, PAGE_NOT_FOUND, PARENT_NOT_FOUND, PARENT_NOT_ALLOWED, DEPTH_EXCEEDED, SEGMENT_TOO_LONG, RESERVED_SLUG, RESERVED_SEGMENT, BREADCRUMB_PARENT_INVALID, REDIRECT_CONFLICT, REDIRECT_LIMIT, VALIDATION, SLUG_TAKEN, HOME_SLUG_IMMUTABLE, HOME_NOT_HIDEABLE, ASSET_NOT_FOUND, ASSET_NOT_ALLOWED.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • pageIdstring · pathrequired

    Page id. Get it from pages.list.

Request body

  • titlestring

    Page title; also the default navigation label.

  • slugstring

    New URL path (or last segment when parentSlug is provided), e.g. "/about". Renaming a page also renames all its descendant subpages and creates 301 redirects for previously published pages. The home page slug cannot change.

  • parentSlugstring | null

    Move this page (and its subpages) under a new parent page slug (e.g. "/services"), or pass null to move it to the top level. Pass parentSlug + last segment rather than concatenating "/a/b" yourself.

  • createRedirectboolean

    Whether to create 301 permanent redirects for previously published pages when renaming or moving (defaults to true).

  • breadcrumbParentSlugstring | null

    Override the parent page shown in breadcrumbs and BreadcrumbList JSON-LD (pass null to reset to URL hierarchy). Use only when the page's logical category differs from its URL; does not change the URL or create redirects. Renaming or deleting the target page updates or clears this override automatically.

  • isVisibleboolean

    Hidden pages are not published. The home page cannot be hidden.

  • globalHeaderIdstring | null

    Header from globalSections to show on this page; null removes it.

  • globalFooterIdstring | null
  • seoTitlestring
  • seoDescriptionstring
  • seoKeywordsstring[]
  • ogTitlestring
  • ogDescriptionstring
  • ogImageAssetIdstring | null

    Share image: assetId of an image in the media library (media.list, media.upload). null removes it; without a share image a title card is generated automatically.

  • ogImageFramingobject | null
  • ogImageFraming.focusobject
  • ogImageFraming.focus.xnumberrequired
  • ogImageFraming.focus.ynumberrequired
  • ogImageFraming.screensobject
  • ogImageFraming.screens.desktopobject
  • ogImageFraming.screens.tabletobject
  • ogImageFraming.screens.mobileobject
  • ogImageFraming.fitMode"contain" | "cover"
  • ogImageFraming.padColorstring
  • canonicalUrlstring
  • robotsIndex"index" | "noindex"
  • robotsFollow"follow" | "nofollow"
  • excludeFromSiteSearchboolean

    Exclude this page from visitor site search (/api/v1/search and the /search page); does not affect search engine indexing (robotsIndex).

  • ifUnmodifiedSincestring

    Optional optimistic-concurrency marker: the page's updatedAt from pages.get. If the page changed since, the call fails with CONFLICT (details.conflict.updatedAt) instead of silently overwriting.

Response 200

  • idstringrequired
  • slugstringrequired

    URL path, "/" for the home page.

  • pathstring[]required

    Path segments (e.g. ["services", "haircut"] for "/services/haircut"; [] for "/").

  • parentSlugstring | nullrequired

    Immediate parent page slug for generic nested pages (e.g. "/services" for "/services/haircut"; null for "/", top-level pages, and system pages such as blog/shop/product/legal).

  • isDirectorybooleanrequired

    True when this is a hidden folder page that exists to group subpage URLs.

  • depthintegerrequired

    Hierarchy depth: 0 for home page, 1 for top-level pages, up to 3.

  • ancestorsobject[]required

    Visible ancestor pages from root to immediate parent (only generic pages participate; system pages such as blog, shop, product, and legal always return []).

  • ancestors[].idstringrequired
  • ancestors[].slugstringrequired
  • ancestors[].titlestringrequired
  • breadcrumbsobject[]required

    Visible breadcrumb trail shown on the page and in BreadcrumbList JSON-LD (up to 4 items; empty when the page has no visible ancestors or is a system page).

  • breadcrumbs[].namestringrequired
  • breadcrumbs[].urlstringrequired
  • breadcrumbSource"url" | "custom"required

    Whether breadcrumbs follow the URL hierarchy ("url") or a custom breadcrumbParentSlug override ("custom").

  • breadcrumbParentSlugstring | nullrequired

    Optional parent page slug override for breadcrumbs and structured data only.

  • titlestringrequired
  • pageTypestringrequired
  • isHomePagebooleanrequired
  • isVisiblebooleanrequired

    Hidden pages are not published or linked from navigation.

  • orderintegerrequired
  • globalHeaderIdstring | nullrequired
  • globalFooterIdstring | nullrequired
  • updatedAtstringrequired

    Revision marker. Pass it back as ifUnmodifiedSince when replacing sections.

  • seoobjectrequired
  • seo.seoTitlestring | nullrequired
  • seo.seoDescriptionstring | nullrequired
  • seo.seoKeywordsstring[] | nullrequired
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL (changes with versions; do not store it).

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.ogImageFramingobject | null
  • seo.ogImageFraming.focusobject
  • seo.ogImageFraming.screensobject
  • seo.ogImageFraming.fitMode"contain" | "cover"
  • seo.ogImageFraming.padColorstring
  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndexstring | nullrequired
  • seo.robotsFollowstring | nullrequired
  • seo.excludeFromSiteSearchbooleanrequired

    When true, this page is excluded from visitor site search (independent of robotsIndex).

  • systemManagedbooleanrequired

    True when Kanorio owns this page (shop index, blog index, taxonomy templates). Those pages cannot be created or deleted.

  • lockedCoreSectionTypesstring[]required

    Section types locked at index 0. pages.replace_sections must keep exactly one of each, with its locked source. Empty for ordinary pages.

  • warningsstring[]

    Non-fatal warnings from this write (e.g. REDIRECT_SHADOWS_PAGE when a manual redirect intercepts this URL).

Errors

  • FORBIDDEN 403
  • PAGE_NOT_FOUND 404
  • PARENT_NOT_FOUND 404
  • PARENT_NOT_ALLOWED 422
  • DEPTH_EXCEEDED 422
  • SEGMENT_TOO_LONG 422
  • RESERVED_SLUG 422
  • RESERVED_SEGMENT 422
  • BREADCRUMB_PARENT_INVALID 422
  • REDIRECT_CONFLICT 409
  • REDIRECT_LIMIT 403
  • VALIDATION 400
  • SLUG_TAKEN 409
  • HOME_SLUG_IMMUTABLE 422
  • HOME_NOT_HIDEABLE 422
  • ASSET_NOT_FOUND 404
  • ASSET_NOT_ALLOWED 422

MCP tool pages_update

curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/pages/{pageId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"seoTitle":"About Us | Sunny Bakery","seoDescription":"Naturally leavened sourdough baked fresh every morning.","ogImageAssetId":"asset_example01"}'
Response
{
  "id": "pg_example789",
  "slug": "/about",
  "path": [
    "about"
  ],
  "parentSlug": null,
  "isDirectory": false,
  "depth": 1,
  "ancestors": [],
  "breadcrumbs": [],
  "breadcrumbSource": "url",
  "breadcrumbParentSlug": null,
  "title": "About Us",
  "pageType": "generic",
  "isHomePage": false,
  "isVisible": true,
  "order": 1,
  "globalHeaderId": "sec_header01",
  "globalFooterId": "sec_footer01",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "seo": {
    "seoTitle": "About Us | Sunny Bakery",
    "seoDescription": "Naturally leavened sourdough baked fresh every morning.",
    "seoKeywords": [
      "sourdough",
      "artisan bakery"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "ogImageFraming": null,
    "canonicalUrl": null,
    "robotsIndex": null,
    "robotsFollow": null,
    "excludeFromSiteSearch": false
  },
  "systemManaged": false,
  "lockedCoreSectionTypes": []
}

Delete a page

DELETE/sites/{id}/pages/{pageId}
betacontent:editdefault (120/minute per token)

Delete a page and its draft content. The home page and system pages (shop, blog, taxonomy templates) cannot be deleted; system pages return SYSTEM_PAGE_LOCKED. When the page has subpages, you must pass mode: "subtree" (delete the page and all its subpages) or "lift-children" (move subpages up one level with 301 redirects before deleting the parent); omitting mode returns HAS_CHILDREN with details.children. Errors: FORBIDDEN, PAGE_NOT_FOUND, HOME_NOT_DELETABLE, SYSTEM_PAGE_LOCKED, HAS_CHILDREN, SLUG_TAKEN, REDIRECT_CONFLICT, REDIRECT_LIMIT.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • pageIdstring · pathrequired

    Page id. Get it from pages.list.

  • mode"subtree" | "lift-children" · query

    Required when deleting a parent page that has subpages: "subtree" deletes all descendants; "lift-children" moves subpages up one level first.

  • createRedirectboolean · query

    With mode "lift-children": whether to create 301 redirects from the old subpage URLs for previously published subpages (defaults to true). Ignored otherwise.

Response 200

  • idstringrequired
  • deletedtruerequired
  • deletedCountinteger
  • liftedCountinteger

Errors

  • FORBIDDEN 403
  • PAGE_NOT_FOUND 404
  • HOME_NOT_DELETABLE 422
  • SYSTEM_PAGE_LOCKED 422
  • HAS_CHILDREN 409
  • SLUG_TAKEN 409
  • REDIRECT_CONFLICT 409
  • REDIRECT_LIMIT 403

MCP tool pages_delete

curl -X DELETE "https://app.kanorio.com/api/v1/sites/{id}/pages/{pageId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "pg_example789",
  "deleted": true,
  "deletedCount": 1
}

Replace sections

PUT/sites/{id}/pages/{pageId}/sections
betacontent:editdefault (120/minute per token)

Replace the whole draft section list of a page (optimistic concurrency). Get the shapes from sections.describe; read the page with pages.get and pass its updatedAt as ifUnmodifiedSince. If someone else (another agent or a person in the editor) changed the page since, the call fails with CONFLICT and details.updatedAt holds the current revision: re-read the page, merge, retry. Changes are saved as draft only; call site.publish to go live. Reference images and files as asset:<assetId> (from media.list, media.upload, media.import_stock, media.upload_link_status); values you read with pages.get can be sent back unchanged. Text fields are normalized to the format that field supports (see sections.describe conventions.textFormat), not rejected; check `formatNotes` in the response for fields that were reformatted. On a system page the locked core section stays at index 0 with its locked source; removing it, duplicating it, or changing that source returns CORE_SECTION_VIOLATION. Errors: FORBIDDEN, PAGE_NOT_FOUND, VALIDATION (details lists the failing section index and field), CONFLICT, CORE_SECTION_VIOLATION, ASSET_NOT_FOUND (details.assetIds: not in this site's media library), ASSET_NOT_ALLOWED (product files cannot be shown on pages).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • pageIdstring · pathrequired

    Page id. Get it from pages.list.

Request body

  • ifUnmodifiedSincestringrequired

    The page's updatedAt from pages.get/pages.list. Required: the write is rejected with CONFLICT when it no longer matches.

  • sectionsobject[]required

    Complete ordered list of section objects, each with `type` and a unique `id`.

Response 200

  • idstringrequired
  • sectionsobject[]required

    Sections as stored after sanitization (media as asset:<assetId>).

  • assetsobjectrequired

    The media-library files the sections use, by assetId.

  • updatedAtstringrequired

    New revision marker; use it for the next replace.

  • formatNotesstring[]

    Field paths whose text was reformatted to the field's supported Markdown syntax (e.g. a heading became bold text).

Errors

  • FORBIDDEN 403
  • PAGE_NOT_FOUND 404
  • VALIDATION 400 · details lists the failing section index and field
  • CONFLICT 409
  • CORE_SECTION_VIOLATION 422
  • ASSET_NOT_FOUND 404 · details.assetIds: not in this site's media library
  • ASSET_NOT_ALLOWED 422 · product files cannot be shown on pages

MCP tool pages_replace_sections

curl -X PUT "https://app.kanorio.com/api/v1/sites/{id}/pages/{pageId}/sections" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ifUnmodifiedSince":"2026-10-06T08:00:00.000Z","sections":[{"id":"sec_hero01","type":"hero","title":"Freshly baked sourdough every morning","subtitle":"Natural starter, local grain. Doors open at 7 a.m.","image":"asset:asset_example01","ctaIds":["btn_order"]},{"id":"sec_faq01","type":"faq","title":"Frequently Asked Questions","items":[{"question":"Can I pre-order loaves?","answer":"Yes, place pre-orders by 5 p.m. the day before."}]}]}'
Response
{
  "id": "pg_example456",
  "sections": [
    {
      "id": "sec_hero01",
      "type": "hero",
      "title": "Freshly baked sourdough every morning",
      "subtitle": "Natural starter, local grain. Doors open at 7 a.m.",
      "image": "asset:asset_example01",
      "ctaIds": [
        "btn_order"
      ]
    },
    {
      "id": "sec_faq01",
      "type": "faq",
      "title": "Frequently Asked Questions",
      "items": [
        {
          "question": "Can I pre-order loaves?",
          "answer": "Yes, place pre-orders by 5 p.m. the day before."
        }
      ]
    }
  ],
  "assets": {
    "asset_example01": {
      "assetId": "asset_example01",
      "kind": "image",
      "visibility": "public",
      "tags": [],
      "processing": null,
      "status": "active",
      "missing": false,
      "version": 1,
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "thumbnailUrl": null,
      "fileName": "sunny-bakery-hero.jpg",
      "mimeType": "image/jpeg",
      "bytes": 482133,
      "streaming": "none",
      "billableBytes": 482133,
      "width": 2400,
      "height": 1600,
      "durationSeconds": null,
      "pageCount": null,
      "source": "IMAGE_CONTENT",
      "inUse": true,
      "focus": null,
      "edgeColor": null,
      "altText": null,
      "watermarkExempt": false,
      "createdAt": "2026-10-01T02:30:00.000Z"
    }
  },
  "updatedAt": "2026-10-06T08:01:30.000Z"
}