Skip to main content
Entitlements answer “what does this customer get?” — for both dollar features and credit-backed features. Read them with hooks when you need the raw value to drive logic, labels, or meters; wrap UI in a gate component when you just want to render conditionally. Both resolve from the bulk entitlement cache populated by useCustomerone HTTP call serves every hook and gate on the page, so you can scatter as many as you like without extra round-trips. Every hook returns isLoading: boolean and error: Error | null — see Introduction. The typed hooks and gates also share two conventions, so they’re stated once here rather than repeated per feature type:
  • fallback — a type-safe default value returned while loading, on error, or when the customer has no entitlement for the slug. When a fallback value is returned instead of a live one, the hook’s isFallback is true.
  • Gate slots — every gate renders children on access, noAccessComponent (default null) on denial, and loadingComponent (default null) while resolving. The typed gates take fallback for the same purpose as the hooks. (FeatureGate is the exception — it uses fallback for the denied slot; see below.)
FeatureGate takes featureSlug. Every typed gate (BooleanGate, MeteredGate, CreditGate, ConfigGate, EnumGate) takes slug.

The six gates

useEntitlement

Reads one feature’s entitlement by slug and returns the raw, type-discriminated value. By default it serves the read from the bulk useCustomer cache. Pass requestedUsage (metered) or requestedValues (enum) to force a live POST /v1/customers/:id/check capacity probe instead. Prefer one of the typed wrappers below when you know the feature type. Parameters
string
required
The feature’s stable slug.
number
Metered features: ask “would I have access if I consumed N units now?”. Forces a live /check capacity probe rather than a cache read.
string[]
Enum features: check whether these requested values are in the allowed set. Also forces a live /check.
EntitlementValue
Value used while loading, on error, or on a cache miss. When returned, isFallback is true.
Returns
  • entitlementEntitlementValue | null — the resolved value. Narrow on entitlement.type ('boolean' | 'metered' | 'credit' | 'config' | 'enum') to read the type-specific fields — e.g. remaining for metered, creditBalance for credit, value for config, enumValues for enum.
  • isFallbackbooleantrue when entitlement came from options.fallback rather than a live read.

useEntitlements

Reads multiple features at once. By default it adds zero HTTP — it derives from useCustomer().entitlements, optionally filtered to the slugs you pass — and returns both the keyed map and a slug-sorted list for feature matrices. Pass { fresh: true } to force a live batch check (e.g. right after a mutation). Parameters
string[]
Optional filter. When provided, only these slugs are returned; omit it to get the customer’s entire entitlement map.
boolean
When true, skip the local cache and call POST /v1/customers/:id/check/batch for slugs. Requires a non-empty slugs argument (the server caps a batch at 50).
Record<string, EntitlementValue>
Per-slug values used while loading, on error, or for slugs the customer doesn’t have.
Returns
  • entitlementsRecord<featureSlug, EntitlementValue> — the filtered map, each value discriminated by type.
  • listArray<{ featureSlug } & EntitlementValue> — the same data sorted alphabetically by featureSlug. Ideal for iterating a table.

FeatureGate

The generic, type-agnostic gate: renders its children only when the customer has access to a feature, regardless of the feature’s type. It resolves through useEntitlement (served from the useCustomer cache) and exposes an onDenied callback that fires once with a typed reason when access is refused. Props
string
required
The feature’s stable slug.
ReactNode
required
Rendered when access is granted.
ReactNode
default:"null"
Rendered when access is denied.
ReactNode
default:"null"
Rendered while the entitlement is loading.
(reason: AccessDeniedReason) => void
Called once when access is denied (and again only after access is regained and lost again). The reason is one of: no_entitlement, no_active_subscription, usage_exceeded, credit_exhausted, not_loaded.
number
Metered features: capacity probe — would access be granted after consuming this many units? Forces a live POST /v1/customers/:id/check.
EntitlementValue
Type-safe entitlement default used while loading or on a cache miss. For ergonomics, prefer the typed gates and their fallback prop.
Probe metered capacity before showing an action:

Boolean features

An on/off feature flag — SSO, audit log, priority support. useBooleanEntitlement(slug, options?) returns a flat access booleantrue when the customer has the feature, false otherwise (or for any non-boolean / missing entitlement). Its options.fallback is { access: boolean }. BooleanGate renders children only when access is true.

Metered features

A metered feature with a per-period quota — API calls, seats, exports. useMeteredEntitlement(slug, options?) returns the full meter picture: access, remaining (quota left this period — granted − usage, the canonical “what’s left”), usage, limit (granted allowance), percentage (usage / limit × 100, 0 when unlimited), isUnlimited (when true, ignore limit/remaining/percentage), and nextResetAt (ISO timestamp of the next reset, or null). Pass options.requestedUsage to force a live /check capacity probe; options.fallback is { access: boolean; remaining?: number; isUnlimited?: boolean; limit?: number; usage?: number }. MeteredGate renders children only when access exists; pass requestedUsage so it succeeds only when that many units could still be consumed this period.
Passing requestedUsage to either the hook or the gate forces a server-side check — “do we have headroom for N more units?” — instead of reading the static remaining from cache:

Credit features

A credit-backed feature drawing from a wallet — AI credits, generation credits, prepaid balance. useCreditEntitlement(slug, options?) returns access and creditBalance (the wallet balance backing this feature). Render creditBalance with formatCredits(n) for unit denominations or as money for fiat denominations — never mix the two. Its options.fallback is { access: boolean; creditBalance: number }. CreditGate renders children only when access exists and the balance is at least requiredBalance (default 1).
CreditGate’s extra prop:
number
default:"1"
Minimum credit balance required to render children.

Config features

A config-valued feature whose entitlement carries a tunable value — “max file size”, “support tier” — a plan sets per tier. useConfigEntitlement(slug, options?) returns access and value (a number or string, or null when there’s no config entitlement). Its options.fallback is { access: boolean; value: number | string }. ConfigGate renders a render-prop children — a function (value: number | string) => ReactNode called with the resolved value when access is granted; noAccessComponent renders when access is denied or the value is null.

Enum features

An enum feature whose entitlement is a set of allowed string values — allowed regions, export formats, model tiers. useEnumEntitlement(slug, options?) returns access and enumValues (the array of allowed strings, empty for any non-enum / missing entitlement). Pass options.requestedValues to probe whether specific values are permitted (forces a live /check) — access then reflects whether those values are in the allowed set. Its options.fallback is { access: boolean; enumValues: string[] }. EnumGate renders children only when access exists; pass requestedValues to require specific values to be in the allowed set.

See also

Customer

useCustomer loads the entitlement cache these hooks and gates read from, plus a synchronous check().

Subscriptions

The subscriptions that grant these entitlements.