can() endpoint is the core of Nozle’s entitlement system.
Request
cust_123 from the authenticated application user; publishable keys are rejected.
See Which subscription is checked.
Response
Field reference
Runtime behavior
The service may cache entitlement and usage state. Always treat the returned decision as point-in-time and enforce it immediately before protected work. A subscription on an override plan (a plan made from a catalog plan for one customer, for example a negotiated price or a subscription created from a quote) gets the entitlements and usage limits of the catalog plan it was made from. Its usage is still priced with the override plan’s own charges. The optionaleconomics object is also point-in-time, but it is not a financial ledger entry. Calling /can never consumes usage, changes a pricing period, or records cost. If a Feature uses detailed_events_only, the estimate is unavailable because the actual Cost Events do not exist yet. If it uses add_both, the known Feature Event Cost is returned and future_detailed_cost_events appears in excludes. An estimate older than the policy’s maximum_snapshot_age_seconds is returned as stale and follows on_unavailable.
Estimated revenue is the standard charge’s unit price × the units of this call. A count Feature adds 1 unit. A sum Feature adds the value of its value property (field_name) in the call’s metadata, for example {"tokens": 500}; without that value the estimate is unavailable with revenue_quantity_missing in excludes. Max, latest, unique count, weighted sum and custom aggregations do not add a fixed amount per call, so their estimate is unavailable with non_additive_revenue_aggregation. When the estimate is unavailable, a margin policy decides with its on_unavailable value (allow, warn or deny), and policy.reason is economics_unavailable.
Which subscription is checked
Plan, entitlements, limits and usage all come from one subscription, and only subscriptions that are current at this moment count: started, not ended, and before their end date.- With
subscription_id,/canevaluates that subscription of the customer. Withentity_id, it evaluates the Entity’s own subscription, else the customer’s own subscription (not owned by an Entity). When both are sent, the subscription must belong to that Entity. An unknown or ended selection answersno_subscription. - Without either,
/canevaluates the customer’s only current subscription. A customer with several current subscriptions is evaluated on its own subscription (not owned by an Entity) when there is exactly one. Otherwise the answer isallowed: falsewith the reasonsubscription_required: sendsubscription_idorentity_id. The newest subscription is never picked for you.
POST /billing/upgrade selects the subscription the same way. For a customer with several current subscriptions it answers 409 subscription_required unless exactly one of them is the customer’s own.
Usage and billing periods
used follows the billing period in which Nozle invoices the usage, for every plan interval (weekly, monthly, quarterly, semiannual, yearly), for calendar and anniversary billing, and in the customer’s time zone (the customer’s, else its billing entity’s):
- Periods start at midnight in that time zone. A weekly calendar period starts on Monday.
- An anniversary subscription that starts on the 29th to the 31st starts on the last day of shorter months.
- A yearly or semiannual plan that bills its charges monthly resets monthly.
Denial reasons
A denial is an HTTP200 response with allowed: false and one of these reason values:
For example, an unknown feature code returns:
SDK wrappers
Node:FeatureGate, UsageGate, or your own UI.
Availability and freshness
If usage cannot be read reliably, the hosted API returns HTTP503 with a structured error and request ID, without an access decision. Treat it as unavailable; do not convert the failure into allowed: true or zero usage. Use bounded retries within your request budget and retain the request ID for support.
Entitlement configuration refresh is approximately once per minute. A plan or quota edit may take that interval to appear in can() results. Usage projections are asynchronous, and a separate can() followed by track() does not reserve quota atomically. Use Track and Consume Credits for atomic product-credit consumption.