Kaiten

Entitlements

Entitlement Types

BOOLEAN, NUMBER, NUMBER_AI_CREDIT, and CONFIG — the value shape of each type, what a NUMBER carries on the catalog, and what its grant carries on the License.

Overview

Every entitlement has a type, set at creation and immutable afterwards. The type fixes two things: the shape of the value a License grants, and whether the entitlement is measured at all. Only the NUMBER family is metered; a BOOLEAN or CONFIG value is read by your product, never reported against.

Examples use $KAITEN_API and $KAITEN_TOKEN as set up in the quickstart, and the Kaiten Sushi Shop catalog. On a stack seeded with the demo data these entitlements and their grants already exist with the definitions shown — sending one again returns 409 Conflict; read them instead. Slugs are kebab-case: the API refuses an underscore in a slug.


BOOLEAN

Included, or not. Used for feature gates that a flag rule or your product reads.

Grant value:

{ "type": "boolean", "value": true }

Kaiten Sushi Shop: delivery-tracking — false on Starter, true on every version of Premium, and the one entitlement that differs between the two versions of Standard: false on standard, the version the family serves, true on standard-v2. The delivery-tracking-enabled flag reads the grant, so the feature follows the License version without listing a single customer.

curl -X POST "$KAITEN_API/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Delivery Tracking",
    "slug": "delivery-tracking",
    "description": "Real-time delivery tracking for end customers.",
    "type": "BOOLEAN",
    "groupSlugs": ["delivery"]
  }'
curl -i -X POST "$KAITEN_API/licenses/premium-v2/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "entitlementSlug": "delivery-tracking",
    "value": { "type": "boolean", "value": true }
  }'

A grant is written on one version of a License, addressed by that version's slug — premium-v2 is the version the Premium family serves.

A BOOLEAN entitlement carries no aggregation method, no warning threshold, and no reset period — the API refuses them on this type. Its grant carries no overage allowance either.


NUMBER

A measurable quota. The entitlement declares how the quota is measured; each grant declares how much a License gives and how strictly that number is enforced.

Grant value:

{ "type": "number", "value": 20 }

-1 is the unlimited sentinel — a grant of -1 is never exceeded.

Kaiten Sushi Shop: monthly-orders (a SUM counter that resets every calendar month), menu-items, delivery-drivers, and locations (three LATEST gauges — each report states the current count).

curl -X POST "$KAITEN_API/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monthly Orders",
    "slug": "monthly-orders",
    "description": "Orders a restaurant can process per month.",
    "type": "NUMBER",
    "aggregationMethod": "SUM",
    "resetPeriod": "MONTH",
    "resetAnchor": "CALENDAR",
    "groupSlugs": ["restaurant-operations"],
    "icon": "lucide:shopping-cart",
    "unitSingular": "order",
    "unitPlural": "orders",
    "userFacing": true,
    "displayOrder": 2
  }'

The seeded catalog presents every entitlement to customers — an icon, a display order, and unit labels on the NUMBER ones — and sets no warning threshold; the tables below list what an entitlement can also carry.

curl -i -X POST "$KAITEN_API/licenses/starter/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "entitlementSlug": "monthly-orders",
    "value": { "type": "number", "value": 20 },
    "limitCapExceededOveragePercent": 0
  }'

What the entitlement carries — the measurement, identical for every License:

PropertyRequiredMeaning
aggregationMethodYes — defaults to SUM when omittedHow each append folds into the total: SUM, COUNT, AVERAGE, MAX, MIN, LATEST. Immutable once set.
warningThresholdPercentNo — 0 disables itPercentage of the granted value at which INSTANCE_ENTITLEMENT_USAGE_WARNING_THRESHOLD_REACHED fires, once per crossing
resetPeriod / resetAnchorNo — unset means a lifetime counterHOUR, DAY, WEEK, MONTH, or YEAR, anchored on the UTC CALENDAR or on the instance's LICENSE_START. Set together; immutable once set; not allowed with LATEST.
unitSingular / unitPluralNoBase unit labels, set together
saleUnitSingular / saleUnitPlural / saleUnitFactorNoThe unit the quota is sold in, when it differs — the trio is set together and requires the base units

What the grant carries — the contract, per License:

PropertyRequiredMeaning
valueYes{ "type": "number", "value": <n> }; -1 for unlimited
limitCapExceededOveragePercentNo — defaults to -1 for an unlimited value, 0 otherwise-1 when the value is -1; 0 for a hard cap; a positive percentage for a soft limit, accepted up to value + value × percent / 100

The seeded grants read the same entitlement three ways: Starter caps monthly-orders at 20 with 0 (hard cap), Standard grants 100 with 10, Premium 1,000 with 20. Usage & Thresholds carries the arithmetic; Metering the aggregation methods and the windows.


NUMBER_AI_CREDIT

A NUMBER whose unit is AI credits. It is a distinct type so that your catalog and your pricing pages can tell credits apart from other quotas — and so that the AI Control Plane Coming soon can build on it — but it is created, granted, measured, and enforced under exactly the NUMBER rules: an aggregation method is mandatory, the grant carries limitCapExceededOveragePercent, the same three values mean the same three things, and a report above the maximum allowed usage is refused the same way.

curl -X POST "$KAITEN_API/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Menu Copywriting Credits",
    "slug": "menu-copy-credits",
    "description": "AI credits for generated dish descriptions.",
    "type": "NUMBER_AI_CREDIT",
    "aggregationMethod": "SUM",
    "resetPeriod": "MONTH",
    "resetAnchor": "CALENDAR"
  }'

Kaiten Sushi Shop's seeded catalog has no AI-credit entitlement; the one above is an addition you can make next to it.


CONFIG

A structured value — a JSON object your product reads as-is. Used for settings that vary by License and are not a number or a switch.

Grant value:

{ "type": "object", "value": { "tier": "priority", "channels": ["email", "slack"], "response_sla_hours": 4 } }

Kaiten Sushi Shop: support-tier — the support channels and response commitment of each License (community, standard, priority), read by the product's help center.

curl -X POST "$KAITEN_API/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support Tier",
    "slug": "support-tier",
    "description": "Support channel and response commitment for the restaurant.",
    "type": "CONFIG",
    "groupSlugs": ["restaurant-operations"]
  }'
curl -i -X POST "$KAITEN_API/licenses/premium-v2/entitlements" \
  -H "Authorization: Bearer $KAITEN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "entitlementSlug": "support-tier",
    "value": {
      "type": "object",
      "value": { "tier": "priority", "channels": ["email", "slack"], "response_sla_hours": 4 }
    }
  }'

The grant's type discriminator for a CONFIG entitlement is object, not config. Like BOOLEAN, a CONFIG entitlement carries no measurement fields and its grant no overage allowance.


Comparison

BOOLEANNUMBER / NUMBER_AI_CREDITCONFIG
Grant value{"type": "boolean", …}{"type": "number", …} — -1 unlimited{"type": "object", …}
Aggregation methodForbiddenMandatoryForbidden
Warning threshold, reset periodForbiddenOptionalForbidden
Overage allowance on the grantNone-1 / 0 / > 0None
Usage reportingRefusedYesRefused
Crossing eventsNoYesNo
Typical useFeature gatesQuotas and limitsStructured settings

Entitlement properties

The body of POST /entitlements; PUT /entitlements/{slug} takes the same fields minus slug, and rejects a changed type, aggregationMethod, resetPeriod, or resetAnchor.

PropertyTypeRequiredDescription
namestringYesDisplay name — Monthly Orders
descriptionstringYesWhat the right means
typeenumAlways set itBOOLEAN, NUMBER, NUMBER_AI_CREDIT, or CONFIG; immutable — the spec declares no default
slugstringNo2–100 characters, ^[a-z0-9][a-z0-9-]*[a-z0-9]$, unique per organization; derived from the name with a random suffix when omitted — pass an explicit slug when you need a predictable one
aggregationMethodenumNUMBER family onlySUM (default), COUNT, AVERAGE, MAX, MIN, LATEST; immutable
warningThresholdPercentintegerNo0–100; 0 disables the warning
resetPeriodenumNoHOUR, DAY, WEEK, MONTH, YEAR; unset means a lifetime counter; immutable
resetAnchorenumWith resetPeriodCALENDAR (default) or LICENSE_START; immutable
unitSingular / unitPluralstringNoBase unit labels, NUMBER family only, set together
saleUnitSingular / saleUnitPlural / saleUnitFactorstring / numberNoSale unit trio, set together; saleUnitFactor > 0
userFacingbooleanNoShown in customer-facing components; defaults to false
displayOrderintegerNoAscending sort order in customer-facing components; defaults to 0
iconstringNoprovider:name token — lucide:shopping-cart
groupSlugsstring[]NoGroups to add the entitlement to

Exact reference — columns and CHECK constraints: the entitlement table.

On this page