Skip to main content

@krios/sdk

TypeScript client for the Krios delivery + management APIs. ESM, zero runtime deps, runs anywhere fetch is available.

Install

pnpm add @krios/sdk

Configure

import { KriosClient } from "@krios/sdk";

const krios = new KriosClient({
endpoint: "https://cms.example.com",
projectSlug: "demo",
apiKey: process.env.KRIOS_DELIVERY_KEY!,
locale: "en-US",
preview: false,
});
OptionNotes
endpointBase URL of the CMS deployment.
projectSlugThe project to read from.
apiKeyBearer key (delivery / preview / management).
localeDefault locale for reads. Override per call.
previewWhen true, requests drafts and sends an x-krios-preview: 1 request header. (The data-krios-* attributes used by the preview overlay are emitted by @krios/react's KriosRichText, not the SDK.)

Reading entries

const entry = await krios.getEntry("ckl_…", { locale: "fr-CA" });
const list = await krios.getEntries("articlePage", { page: 1, limit: 25 }); // { items, total, page, limit }
const bySlug = await krios.getEntryBySlug("hello-world", "main");

getEntry returns the full entry including resolved field values for the active locale. Reference / blocks fields are returned as { _ref, _type } placeholders by default; pass { include: 1 } to expand them inline.

Resolving routes

The single most useful method for frontends:

const result = await krios.resolveRoute("main", "/about/team");

switch (result.kind) {
case "entry": return render(result.entry);
case "redirect": return Response.redirect(result.target, result.status);
case "not_found": return notFound();
}

resolveRoute honors plain redirects + regex redirects + the auto-redirect-on-slug-change behavior described in Routing.

Writing (management keys only)

const krios = new KriosClient({
endpoint: "https://cms.example.com",
projectSlug: "demo",
apiKey: process.env.KRIOS_MANAGEMENT_KEY!, // server-only — never ship to client
});

const created = await krios.createEntry({
contentTypeApiName: "blogPost",
siteId: "site_main",
locale: "en-US",
treeParentId: "node_blog",
slug: "hello-world",
fields: { title: "Hello World", body: { type: "doc", content: [...] } },
});

await krios.updateEntry(created._id, {
version: 1, // the version you are updating from (optimistic concurrency)
locale: "en-US",
fields: { title: "Hello, World!" },
});

await krios.publishEntry(created._id, "en-US");

The SDK throws typed KriosError instances on 4xx / 5xx (with subclasses NotFoundError, ConflictError, ValidationError, AuthError, RateLimitError); catch and inspect err.code for the stable error code (version_conflict, field_permission_denied, etc.).

Retry behavior

429 responses trigger an exponential backoff retry honoring the Retry-After header. Retry is not configurable: it is fixed at 3 attempts with exponential backoff (~1s / 2s / 4s).

Type generation

For full type-safety on field reads, generate per-project interfaces:

krios types generate --output ./src/krios.types.ts
import type { ArticlePage } from "./krios.types";

const article = (await krios.getEntry("ckl_…")) as ArticlePage;
article.fields.body; // typed as the rich-text projection shape