Kanorio Developers
Back to KanorioAPI keys
OverviewCapabilitiesManagement APIDelivery APICustomer APIWebhooksElementsChangelog

API changelog

Changes to the REST API and MCP tools by release date. Deprecated endpoints send Deprecation and Sunset headers and are removed after the sunset date.

Versioning and change policy (opens in a new tab)

Headless brochure sites and blog: system host, portable content, reference slug filters and developer settings

2026-10-21
  • Addedsite.create_preview_token (POST /v1/sites/:id/preview-tokens): mint a read-only knr_pv_ preview token for reading unpublished drafts via the Content Delivery API (send X-Kanorio-Preview: knr_pv_… or Authorization: Bearer knr_pv_… with ?preview=1).
  • Addedsite.update_developer_settings (PATCH /v1/sites/:id/developer-settings): enable headlessEnabled (Content Delivery API, form submissions and blog publishing work while the hosted site remains unpublished) and set externalStorefrontUrl (hosted pages 302-redirect to your external frontend while /api/v1/*, /checkout and /account stay active); returns the site's permanent systemHost (s-<base32>.kanorio.com).
  • Addedposts.get, posts.create, posts.update, posts.publish and posts.unpublish now include structured segments[] and toc[] (H2/H3 headings with anchor ids) alongside contentMarkdown.
  • AddedFilter operators eq_slug (reference fields) and has_slug (multi_reference fields) in items.list and the Content Delivery API: filter by a referenced item's slug without a preliminary id lookup (for example ?filter[categories][has_slug]=news).
  • AddedContent Delivery API /api/v1/collections/{key}/items and .../{slug} now return a top-level assets map (url, width, height, alt, mimeType, fileSize, kind), full published fieldData on expand, X-Kanorio-Cache-Tags headers, and portable blog content with ?formats=markdown,html,plaintext.
  • Addedglobals.list_headers, globals.create_header and globals.delete_header (GET|POST /v1/sites/:id/globals/headers, DELETE …/:key), plus key parameter on globals.replace_header: manage multiple site headers for sub-brands or campaign pages.
  • Addedwebhooks.list, webhooks.create, webhooks.update_events, webhooks.delete and webhooks.test (under /v1/sites/:id/webhooks, scope site:integrations): register and manage webhook endpoints programmatically (Pro: up to 3 endpoints, Business: up to 10).

Deliverables: courses, e-books and downloads as a first-class resource

2026-10-21
  • Addeddeliverables.list/get/create/update/archive (GET|POST /v1/sites/:id/deliverables, GET|PATCH /v1/sites/:id/deliverables/:deliverableId, POST …/archive): a deliverable is what a buyer receives (course, e-book, audio series, template pack) — chapters and units, completion rule, certificate and comment settings. Products only sell it.
  • Addeddeliverable_units.replace_tree (PUT /v1/sites/:id/deliverables/:deliverableId/units), deliverable_units.update (PATCH /v1/sites/:id/deliverable-units/:unitId) and deliverable_units.reorder: two-level chapter/unit tree; unit kind is an open string (video, audio, file, text, quiz); files are referenced by media-library assetId; isPreview, releaseAt/releaseAfterDays, allowDownload and tier scope per unit.
  • Addedentitlements.list/grant/revoke/check (GET|POST /v1/sites/:id/entitlements, POST …/:entitlementId/revoke, GET …/check): who can access which deliverable, grants without a purchase (idempotent), and a point-in-time access check that accounts for preview, release schedule and expiry.
  • Addedprogress.list (GET /v1/sites/:id/deliverables/:deliverableId/progress): learner progress per deliverable.
  • Addedproducts.update accepts deliverables: [{ deliverableId, tierId?, accessDays? }] to replace the deliverables granted on purchase; products.* responses include deliverables.
  • AddedWebhook events deliverables.entitlement.granted, deliverables.entitlement.revoked and deliverables.progress.completed (identifiers only, no personal data).
  • ChangedDigital products no longer carry content directly: existing product contents were migrated into one deliverable per product and linked back automatically. Access checks now evaluate entitlements against deliverables and units.

Nested pages, automatic 301 redirects and breadcrumbs

2026-10-19
  • Addedpages.list, pages.get, pages.create and pages.update now return PagePathInfo fields: path (string[]), parentSlug, isDirectory, depth (0-3), ancestors, breadcrumbs and breadcrumbSource ("url" | "custom").
  • Addedpages.create and pages.update accept optional parentSlug (pass parentSlug plus the last segment rather than concatenating multi-segment paths) and breadcrumbParentSlug (override the breadcrumb parent without changing the URL; follows the target page when it is renamed and is cleared when it is deleted). Missing parent paths are automatically created as hidden folder pages. Renaming or moving a page automatically updates all descendant subpages and creates 301 redirects for previously published pages (pass createRedirect: false on pages.update to skip). Both return warnings (e.g. REDIRECT_SHADOWS_PAGE) when applicable.
  • Addedpages.delete accepts mode: "subtree" | "lift-children" when deleting a parent page that has subpages, and createRedirect (defaults to true) to control the 301 redirects created by "lift-children".
  • Addedglobals.update_site_settings accepts showBreadcrumbs (boolean, defaults to true) to toggle site-wide breadcrumb navigation and BreadcrumbList JSON-LD.
  • Addedsites.structure (GET /v1/sites/:id/structure): return the visual sitemap tree of a website — top-level pages with nested subpages (up to 3 levels), real page status, the ordered list of section types on each page, and summary counts for Kanorio-managed Store and Blog pages. Requires editor:enter.

Site search

2026-10-19
  • Addedsite.search (GET /v1/sites/:id/search?q=&kind=&limit=): search the live site the way visitors do — published pages, blog posts, blog categories and tags, products and product categories — with a snippet around the first matching term. Every term must match (AND); full-width characters, case and term order do not matter. Requires console:view. The same index serves https://{site}/api/v1/search.
  • Addedpages.update and posts.create / posts.update accept excludeFromSiteSearch (boolean, also returned on pages.list / pages.get / posts.get seo.excludeFromSiteSearch) to hide a published page, product page or blog post from visitor site search without affecting search engine indexing (robotsIndex).

Header utility buttons

2026-10-19
  • Addedglobals.replace_header: new optional field utilities, an ordered list of { id, enabled } for the feature buttons shown after the header CTA buttons (search, cart). An omitted utility keeps its default (search off, cart on; newly created sites default both to on), so existing headers render the same; a utility only appears when the site has that feature (search: published site with searchable content; cart: shopping cart turned on with at least one active product).

Collections: structured content with a public Content Delivery API

2026-10-19
  • Addedcollections.list/get/create/update/delete and items.list/get/create/update/delete/publish/unpublish/bulk_create/bulk_update (under /v1/sites/:id/collections): define collections with 17 field types plus json, write items with per-field validation errors, and read them anonymously from https://{site}/api/v1/collections/{key}/items with filter/sort/cursor paging, edge caching and CORS allowlists. New scopes collections:view and collections:manage.
  • Addedsite.get_allowed_origins and site.update_allowed_origins (GET/PUT /v1/sites/:id/allowed-origins): manage the CORS allowlist for the Content Delivery API.
  • AddedWebhook events collections.item.created/updated/published/unpublished/deleted and collections.items.bulkChanged.
  • AddedSystem collections blog, blog_categories, blog_tags and blog_authors expose the site's blog through collections.*, items.list/get and the Content Delivery API. They are read-only through items.*: writes return SYSTEM_COLLECTION; use blog.* or the Blog page. Changes made through the blog appear in the collection within the same request.

Automatic Kanorio branding badge removal on paid plans

2026-10-17
  • Changedglobals.update_site_settings: siteSettings no longer accepts hidePoweredByKanorio (the key is ignored if sent). The Kanorio branding badge on public sites is now shown on the free plan and hidden automatically on paid plans.

Content revision history and restore

2026-10-17
  • Addedrevisions.list, revisions.get and revisions.restore (GET /v1/sites/:id/revisions, GET /v1/sites/:id/revisions/:revisionId, POST /v1/sites/:id/revisions/:revisionId/restore): inspect 30-day revision snapshots for website drafts and blog posts, and restore either a single page or an entire draft with automatic pre-restore backup.

Header and footer layout, brand slot and social link controls

2026-10-17
  • Addedglobals.replace_header: new optional fields layout top-left, surface, showBrandLogo, showSiteName, logoSize, showSocialLinks (boolean or { desktop, tablet, mobile }), hiddenSocialLinkUrls, hiddenSocialLinkUrlsByDevice, showAccentLine and ctaIds (up to 2 buttons; ctaId keeps working).
  • Addedglobals.replace_footer: new optional fields logoFramed, hiddenSocialLinkUrls, ctaIds, ctaStyleById and showAccentLine; navItems accept linkType group, rendered as its own column.
  • Addedpage-main-visual and link-in-bio sections accept hiddenSocialLinkUrls to hide some of siteSettings.socialLinks in that section.
  • DeprecatedHeader variant (solid / transparent / glass) is accepted but ignored; the header background is controlled by surface.

Website analytics read endpoints

2026-10-17
  • Addedanalytics.overview, analytics.pages, and analytics.bots (GET /v1/sites/:id/analytics/overview, /pages, /bots): read-only traffic totals, attribution sources (including AI assistants and UTM campaigns), per-page engagement metrics, and AI crawler activity.

Content references media by assetId

2026-10-16
  • ChangedBreaking: pages.get, pages.replace_sections, globals.*, posts.* and campaigns create/update show this site's media as asset:<assetId> inside sections, header, footer, site settings, Markdown and email content, and add an assets map (assetId → asset object) to the response. URLs with a size variant or query, and URLs of other websites, are returned unchanged. Content read this way can be written back as is.
  • ChangedBreaking: content writes accept asset:<assetId> for this site's media and check it: ASSET_NOT_FOUND (details.assetIds) when the file is not in the site's media library, ASSET_NOT_ALLOWED when it is a product file.
  • ChangedBreaking: the share image input ogImage (an https URL) is replaced by ogImageAssetId on pages.update, posts.create and posts.update; null removes the share image. seo.ogImageAssetId is added to page and post responses, and seo.ogImage stays as the display URL.
  • ChangedBreaking: products.create and products.update take images as { assetId, alt? } instead of { url, alt?, width?, height? }; width and height come from the file. Product responses add images[].assetId (null for images that are not in the media library).
  • ChangedThe MCP server version is now 2.0.0 (initialize serverInfo and server.json).

Media library assets

2026-10-16
  • Addedmedia.get (GET /v1/sites/:id/media/:assetId): one file from the media library or the trash with every place the site uses it. New error code: ASSET_NOT_FOUND.
  • Addedmedia.replace (POST /v1/sites/:id/media/:assetId/replace): upload a new version of an image from base64 or an https URL. Every place that uses it switches over and keeps the same assetId; published pages switch after the next publish (awaitingPublish). Images only for now. New error codes: IMAGES_ONLY, REPLACE_NOT_AVAILABLE.
  • ChangedBreaking: media.* return one asset object (assetId, kind, status, missing, version, url, thumbnailUrl, fileName, mimeType, bytes, width, height, durationSeconds, pageCount, source, inUse, createdAt). media.upload and media.import_stock return { asset } instead of { id, url, … } (id was the CDN image id, not the assetId); media.upload_link_status returns asset objects with uploadedAt.
  • ChangedBreaking: media.list lists the whole media library as in the dashboard (images, video, audio, PDFs, documents, product files). Inputs are assetKind, unusedOnly, search, sort and offset (kind and limit were removed); the response adds hasMore and pages hold 40 files.

Replaced image versions

2026-10-15
  • ChangedReplacing an image keeps the older version until no published page uses it, then moves it to the trash. media.restore on such an older version restores it as a separate file and returns its new assetId; content that used the image keeps showing the current version. New error code: RESTORE_FAILED.
  • Changedmedia.list leaves out older versions kept after an image is replaced.

Media trash

2026-10-15
  • Addedmedia.trash, media.restore and media.purge (POST /v1/sites/:id/media/:assetId/trash, POST …/restore, DELETE /v1/sites/:id/media/:assetId). Trashed files stop showing on the site right away, still count toward storage, and are deleted permanently after 30 days. media.purge only accepts files already in the trash and fails with ASSET_IN_USE (details.usages) unless confirm: true when the site still uses the file. New error codes: NOT_IN_TRASH, PRODUCT_FILE_PROTECTED, EXPORT_HOLD, ASSET_IN_USE, DELETE_FAILED.
  • Changedmedia.list no longer returns files in the trash; they still count toward usage.quotaBytes.

OAuth client authentication, scope defaults and stability labels

2026-10-14
  • AddedOAuth token endpoint accepts private_key_jwt client assertions (RFC 7523) for CIMD and DCR clients that publish a jwks_uri; the authorization server metadata now advertises token_endpoint_auth_methods_supported [none, private_key_jwt].
  • ChangedAuthorization requests without a scope parameter (or with only unknown scopes such as offline_access) no longer fail with invalid_scope; the default "content" permission set is granted and shown on the consent page. Protected resource metadata now lists scopes_supported.
  • AddedEvery operation carries x-kanorio-stability in the OpenAPI document; deprecated operations are flagged with deprecated: true, x-kanorio-sunset and x-kanorio-replaced-by, and REST responses send Deprecation, Sunset and Link headers. The whole API is currently beta.
  • AddedMCP step-up authorization: when an OAuth access token lacks a capability's requiredScope, /api/mcp now responds with HTTP 403, WWW-Authenticate: Bearer error="insufficient_scope", scope="..." and _meta["mcp/www_authenticate"] so clients can re-authorize with unioned scopes.
  • ChangedPerplexity is now documented as an API-key client; its OAuth registration expects a client_secret that Kanorio does not issue.

Agent API beta

2026-10-05
  • AddedREST API at /api/v1 and MCP server at /api/mcp backed by the same capabilities registry; personal access tokens and OAuth 2.1 (PKCE, CIMD, DCR).
  • AddedOpenAPI 3.1 document at /api/v1/openapi.json and the kanorio CLI.