Skip to main content

Feature Access Without Plan Checks

Entitlements answer the question your application asks on every request: “can this customer use this feature, and how much of it?” Instead of hard-coding plan names into your product (if (plan === 'pro')), you attach feature grants to plans in Recurso and query the customer’s effective entitlements at runtime. Change what a plan includes and every subscriber picks it up immediately — no deploy.
  • Plan-level grants — each plan carries a set of features it grants
  • Two kindsboolean (on/off features) and limit (numeric quotas)
  • Effective resolution — a customer’s entitlements are computed as the union across all of their active and trialing subscriptions
  • Fast check endpoint — a single-query hot path built for per-request feature gating

Entitlement Kinds

Feature keys are machine identifiers: up to 128 characters matching ^[A-Za-z0-9][A-Za-z0-9._:-]*$ (letters, digits, ., _, :, -). Validation is strict per kind: boolean entitlements require bool_value and must omit limit_value; limit entitlements require a limit_value of >= 0 and must omit bool_value. Violations return a validation_failed error.

Grant Features to a Plan

Setting a plan’s entitlements is a full replacement (PUT semantics): feature keys absent from the request are removed from the plan.
Because the endpoint replaces the whole set, always send the complete list of features the plan should grant. Sending only the one you changed deletes the rest. Duplicate feature_key values in one request are rejected.
Read a plan’s grants back with GET /v1/plans/{id}/entitlements (or recurso.entitlements.getForPlan(planId)). Plan entitlements are also editable on the plan detail page in the dashboard.

Effective Entitlements: Union Semantics

A customer may hold several subscriptions at once — a base plan plus an add-on plan, or an old and a new plan overlapping during a migration. Their effective entitlements are the union across the plans of every active and trialing subscription: Additional rules:
  • Subscriptions in any other state (canceled, paused, past_due, …) contribute nothing — only active and trialing count. Trials get full feature access; expiry removes it automatically.
  • If the same feature_key appears as boolean on one plan and limit on another, the effective entitlement resolves to limit.
Fetch the effective set — each entry lists the plan_ids that contributed to it, so you can show why a customer has a feature:

Feature Gating with the Check Endpoint

GET /v1/entitlements/check is the hot path: one indexed query answering a single customer_id + feature pair. A feature the customer does not have answers granted: false with a null limit — it is never a 404.

Node SDK gating pattern

For latency-sensitive paths, cache check results in your app for a short TTL (30–60 seconds) keyed by customer_id:feature. Entitlements only change when a subscription or plan changes, so a short cache is safe and removes the round-trip from your request path.
Recurso stores and resolves entitlements; metering usage against limits is your application’s job. Recurso tells you the customer is entitled to 25 seats — your app counts how many they have used. For metered billing on usage, see Usage-Based Billing.

API Reference