SDKs & tools
TypeScript SDK
Typed clients for the Management API, Content Delivery API and Customer API, plus helpers for webhooks, previews, SEO files and the edge.
@kanorio/sdk is a thin, fully typed client generated from the three OpenAPI documents. Paths, parameters, request bodies and responses are checked at compile time. It runs anywhere fetch does: Node.js, edge runtimes, Deno, Bun and browsers.
npm install @kanorio/sdk
Clients
| Function | API | Credential |
|---|---|---|
createManagementClient({ token }) | Management API at https://app.kanorio.com/api/v1 | knr_pat_ or knr_sa_. Server only. |
createDeliveryClient({ siteUrl, previewToken? }) | Content Delivery API of one site | None, or knr_pv_ for drafts |
createCustomerClient({ siteUrl, token }) | Customer API of one site | knr_cat_ |
Each client has get, post, put, patch and delete. Path parameters go in params, query parameters in query and the JSON body in body.
import { createManagementClient } from "@kanorio/sdk"; const kanorio = createManagementClient({ token: process.env.KANORIO_TOKEN! }); const page = await kanorio.get("/sites/{id}/pages/{pageId}", { params: { id: "ws_example123", pageId: "pg_example456" }, });
token can be a function, so you can fetch a rotated secret on each request.
Errors
Non-2xx responses throw KanorioApiError with code, status, message and details. retryAfter is filled from the Retry-After header or details.retryAfter.
import { KanorioApiError } from "@kanorio/sdk"; try { await kanorio.post("/sites/{id}/posts/{postId}/publish", { params: { id, postId }, body: {} }); } catch (error) { if (error instanceof KanorioApiError && error.code === "SITE_NOT_PUBLISHED") { await kanorio.post("/sites/{id}/publish", { params: { id }, body: {} }); } else { throw error; } }
Pagination
paginate turns any list endpoint into an async iterator that follows nextCursor. listAll collects every page into an array.
import { createDeliveryClient, paginate } from "@kanorio/sdk"; const delivery = createDeliveryClient({ siteUrl: "https://s-xxxxxxxxxxxx.kanorio.com" }); for await (const item of paginate((cursor) => delivery.get("/collections/{key}/items", { params: { key: "projects" }, query: { cursor, limit: 100 } }) )) { console.log(item.slug); }
Helpers
| Import | What it does |
|---|---|
verifyWebhookSignature, createRevalidateHandler | Verify X-Kanorio-Signature and revalidate data.cacheTags (prefixed with kanorio:). See Webhooks. |
cacheTag, localizeCacheTags, prefixCacheTags | Build the cache tags a fetch should carry (cacheTag.collection("blog"), cacheTag.item(id), localizeCacheTags(tags, "fr-FR")), with the same kanorio: prefix the webhook handler revalidates |
seoRewrites({ siteUrl, framework }) | Serve the site's sitemap, robots.txt, llms.txt and feeds from your own domain |
fetchDeliveryJsonLd({ siteUrl, path }) | Schema.org JSON-LD for a page |
@kanorio/sdk/edge › createKanorioMiddleware | Apply redirects (exact, then /* wildcard), block AI crawlers the owner blocked, serve the IndexNow key file and, on multilingual sites, the locale rules: redirect the primary locale's prefix to the root, serve /{prefix}/llms.txt and /{prefix}/rss.xml, match redirects without the prefix, and report the request's locale in evaluate() |
requestLocaleOf, localizedPath, languageSwitcher | Resolve the locale from a pathname with the site's locales[] (GET /site), build the same path in another locale, list the language menu |
buildAlternates | Canonical and hreflang for one page from resolvedLocale / availableLocales, with the hosted site's rules (self-canonical per locale, x-default to the primary locale, fallback pages canonical to the primary) |
@kanorio/sdk/preview › createPreviewRouteHandler | Turn the dashboard's preview link into a draft-mode session |
@kanorio/sdk/forms › forms.client | Fetch a form, its bot-protection challenge and upload tickets, then submit |
parseDeliveryCacheTags, frameworkCacheTags | Read X-Kanorio-Cache-Tags from a Content Delivery API response, raw or prefixed for your framework's cache |
Types for your content model
Collections are defined per site, so their field types come from the site itself. Generate them with the CLI:
npx @kanorio/cli types --site https://s-xxxxxxxxxxxx.kanorio.com --out src/kanorio.d.ts
Versioning
The SDK follows semantic versioning. Its version is sent with each request, so Kanorio can warn you about deprecated operations you still call. See Versioning.