Kaiten

Get Started

Quickstart

The whole chain in ten minutes — model a customer and their contract in the console, enforce a usage limit, and watch a feature flag follow the contract.

In about ten minutes you will build Kaiten's core chain, end to end: a metered Entitlement granted by a License, a Customer with an Instance running under that License — then report usage until the limit pushes back, and evaluate a feature flag whose rule reads the entitlement. In the last step the quota runs out and the flag flips on its own, because the contract is the source of truth.

Each step happens in the console; the API equivalent is one unfold away under the step. Two operations — reporting usage and evaluating the flag — are API calls by nature (in production your product makes them), and the console is where you watch their effect. Only the setup differs between Kaiten Cloud and the Community Edition.

Set up your environment

  1. Sign up at kaiten.sh and create your Organization — the root of everything you model, isolated from other organizations.
  2. If your organization is a Kaiten Cloud demo sandbox, a banner above every page offers Seed demo data. Seeding runs in the background: the banner reads Seeding demo data… until the run ends, and the entities then appear in the regular views. An organization that is not a demo sandbox shows no banner and starts empty; this quickstart works there too, because it builds its own entities.
  3. Export the Kaiten Cloud API base URL for the API calls later in this guide:
export KAITEN_API="https://app.kaiten.sh/api"

You need Docker with Compose v2, Git, Task, and Node.js — the console's dev server runs on your machine, not in Docker. Clone the repository, then start the stack with the demo seed profile loaded:

git clone https://github.com/kaitencloud/kaiten.git
cd kaiten
cp .env.example .env   # the defaults work locally
task dev               # the backend, its accounts, the Kaiten Sushi Shop dataset, and the console

task dev runs task quickstart — the stack under the compose project kaiten-oss, its accounts, and seed-data, the seeder service of compose.yml, whose default profile, demo, is the Kaiten Sushi Shop dataset — then generates the console's API client and starts its dev server. task up starts the same stack without product data. The console is at http://localhost:3000 — the dev user switcher signs you in as one of the seeded users, no identity provider involved. The API answers through Envoy on KAITEN_PORT (6060 in .env.example); export it for the API calls later in this guide:

export KAITEN_API="http://localhost:6060/api"

The full self-hosting reference — seed data, Docker Compose, environment variables, identity provider — is in the self-hosting section.

The demo sandbox and the demo seed profile load the same dataset: the Kaiten Sushi Shop, a restaurant-software vendor with four customers on three License families, entitlements with usage, and flags that read them. The console tour walks through it; this quickstart builds its own entities next to it.

Model a customer and their contract

You build the model from the offer outward: first what you sell — an Entitlement granted by a License — then who buys it — a Customer — then where it runs for them — an Instance under that License. The cast: you are Kaiten Sushi Shop, a restaurant-software vendor, signing the restaurant Sakura Kyoto.

The unfolds under each step show the same operation as an API call, with the response abridged to the fields the flow uses — your id values and timestamps will differ. Running them needs the token you'll create in the next step.

The Entitlement

A NUMBER entitlement is a metered quota. This one counts priority orders, sums each report, and resets monthly. How strictly the quota is enforced is not decided here — it is written on each License's grant, in the next step.

  1. Open Entitlements and click New Entitlement.
  2. Name: Priority Orders · Slug: priority-orders · Description: Priority orders a restaurant can place per month. Click Next.
  3. On the Type configuration step — Type: Number · Aggregation Method: Sum · Usage resets: Every month · Window aligned on: Calendar. Click Create Entitlement.

The License, granting 5 priority orders a month

  1. Open Licenses and click New License: Name Omakase, Type Paid, Description The top tier — everything on the menu.
  2. Under Entitlements & limits, on the same page, click Add entitlement: Entitlement Priority Orders, Threshold / limit 5, Overage allowance (%) 0 — a hard cap: a report that would take the total past 5 is refused.
  3. Click Create License. The License is published unless Save as draft is ticked.

The second action writes the contract side — how much this tier grants, and how strictly. The chain so far: Omakase → 5 priority orders / month, hard cap.

The Omakase License in the console: Paid, Published, version 1, granting Priority Orders at 5 as a hard limitThe Omakase License in the console: Paid, Published, version 1, granting Priority Orders at 5 as a hard limit

The Customer

  1. Open Customers and create a new customer.
  2. Name: Sakura Kyoto — the slug auto-generates to sakura-kyoto.

The Instance

The Instance ties it together: the production copy of your product running for Sakura Kyoto, under the Omakase License.

  1. Open the Sakura Kyoto customer and, in its Instances card, click New Instance.
  2. Name: Sakura Kyoto Production — slug sakura-kyoto-production — Description: Production instance for Sakura Kyoto. Click Next.
  3. On Choose the license — License: Omakase v1; the License Date range defaults to one year from today. Click Next.
  4. Leave Deployment empty — and Metadata, a step that appears where the organization declares metadata fields for instances — and click Create Instance.

The chain is complete: Sakura Kyoto → sakura-kyoto-production → Omakase → 5 priority orders / month.

Create a service account and token

Everything from here on is your product talking to Kaiten — and programmatic access goes through a service account, a machine identity in your organization, holding API tokens (ksh_...) with explicit scopes.

  1. Open Integrations → Service Accounts, click Create Service Account, and name it quickstart.
  2. On the service account, click Generate Token. On the New Token page, name the token local-dev and, under Access, set Customers, Instances, Licenses, Entitlements and Feature Flags to Read & write — on a short screen, Adjust per resource opens that table. The summary lists the scopes the token will carry: the five write: scopes this guide needs, each with its read:.
  3. Click Create Token, then Copy token. The token is shown once, on that page: Kaiten keeps only a hash of it.
export KAITEN_TOKEN="ksh_..."
The New Token page for the quickstart service account: the token named local-dev, and under Access the ten scopes it will carry, read and write on customers, entitlements, feature flags, instances and licenses.The New Token page for the quickstart service account: the token named local-dev, and under Access the ten scopes it will carry, read and write on customers, entitlements, feature flags, instances and licenses.

Enforce the limit

Reporting usage is an API act by nature — in production your product's backend reports, through one of the Kaiten SDKs — the Go client, the Python client, or @kaitencloud/server — or plain HTTP as below. Report 4 priority orders:

curl -X POST "$KAITEN_API/instances/sakura-kyoto-production/entitlements/priority-orders/usage" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": {"type": "number", "value": 4}, "behavior": "append"}'
{
  "entitlementId": "a1e2d3c4-b5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "entitlementSlug": "priority-orders",
  "licenseId": "b2f3e4d5-c6a7-4b8c-9d0e-1f2a3b4c5d6e",
  "licenseSlug": "omakase",
  "value": {"type": "number", "value": 4, "event_count": 1},
  "limit": {"type": "number", "value": 5},
  "currentPeriodStart": "2026-09-01T00:00:00Z",
  "currentPeriodEnd": "2026-10-01T00:00:00Z"
}

value is the observed side, limit the contract side, and the period bounds show the monthly window this counter lives in. Now open Customers → Instances, then Sakura Kyoto Production, then its Entitlements & Usage tab: Priority Orders reads the same 4 / 5 — the console and the API read one record.

Sakura Kyoto Production's usage: Priority Orders at 4 of 5 (80 %), Near limitSakura Kyoto Production's usage: Priority Orders at 4 of 5 (80 %), Near limit

One order remains. Try to report three more — 4 + 3 would exceed the granted 5, and the Omakase grant is a hard cap with no allowance past it:

curl -i -X POST "$KAITEN_API/instances/sakura-kyoto-production/entitlements/priority-orders/usage" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": {"type": "number", "value": 3}, "behavior": "append"}'
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
  "title": "Conflict",
  "status": 409,
  "code": "ReportEntitlementUsageMetric.ThresholdExceeded",
  "detail": "Usage for priority-orders exceeds the allowed threshold",
  "instance": "/api/instances/sakura-kyoto-production/entitlements/priority-orders/usage"
}

The report is refused and not written — the stored total is still 4. That refusal is itself recorded: an ENTITLEMENT_USAGE_REPORT_REJECTED event lands in the audit trail, so the pushback is as auditable as the acceptance. Had the grant carried a 50 % allowance instead of 0, the maximum allowed usage would have been 7.5 and the same report would have been accepted at 7 — the allowance, like the value, is the grant's decision.

Evaluate a flag that reads the contract

Feature flags in Kaiten evaluate through OFREP (the OpenFeature Remote Evaluation Protocol) with CEL targeting rules — and a rule can read the instance's entitlements directly through the server-provided __kaiten facts. Create a flag that keeps the priority-ordering flow visible only while the quota has room:

  1. Open Feature Flags and click New Feature Flag. On Basic Information — Name: Priority ordering · Slug: priority-ordering-enabled, typed after the name, which fills the slug in as you type · Type: Boolean. Leave the switch in the header on Enabled.
  2. On Variants Configuration, a boolean flag starts with two variants named true and false, whose values are locked: rename them on and off. On Default Variant, keep Simple Variant and choose off.
  3. On Targeting Rules, click Add First Rule: Targeting Type Basic Targeting, Name Priority orders left, Variant on, and the CEL Expression below. Click Save, then Create Feature Flag.
__kaiten.entitlements["priority-orders"].remaining > 0.0
The Priority ordering flag's Targeting tab: the Enabled and Boolean badges, Try it and Configure, its rule returning on, then the fallbackThe Priority ordering flag's Targeting tab: the Enabled and Boolean badges, Try it and Configure, its rule returning on, then the fallback

Evaluation is the API call your product makes on every check. Evaluate the flag for the instance:

curl -X POST "$KAITEN_API/ofrep/v1/evaluate/flags/priority-ordering-enabled" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"context": {"targetingKey": "sakura-kyoto", "kaiten": {"instanceSlug": "sakura-kyoto-production"}}}'
{
  "key": "priority-ordering-enabled",
  "value": true,
  "variant": "on",
  "reason": "TARGETING_MATCH"
}

Usage is 4 of 5, so remaining is 1.0, the rule matches, the flag is on. Now consume the last order:

curl -X POST "$KAITEN_API/instances/sakura-kyoto-production/entitlements/priority-orders/usage" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": {"type": "number", "value": 1}, "behavior": "append"}'

The total reaches the cap exactly — accepted, and Kaiten emits INSTANCE_ENTITLEMENT_USAGE_REACHED, the event you would wire to an alert or an upsell flow. Evaluate the flag again, same call, no deploy, no config change:

{
  "key": "priority-ordering-enabled",
  "value": false,
  "variant": "off",
  "reason": "DEFAULT"
}

remaining is 0.0, no rule matches, the default variant serves. The contract turned the feature off. Commercial state and runtime behavior are one system here, so they cannot drift apart.

On this page