Skip to main content
The can() endpoint is the core of Nozle’s entitlement system.

Request

Call this endpoint from a trusted backend with a restricted secret key. Derive 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 optional economics 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, /can evaluates that subscription of the customer. With entity_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 answers no_subscription.
  • Without either, /can evaluates 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 is allowed: false with the reason subscription_required: send subscription_id or entity_id. The newest subscription is never picked for you.
A customer with one current subscription sees no change. Usage is counted per subscription, so the usage of one Entity’s seat never counts against another subscription’s limit, and the counter continues across plan changes of the same subscription. 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.
A recurring Feature, such as seats or storage, keeps one running total across billing periods: a hard limit keeps blocking after a period ends instead of reopening on the first day. For these limits, a weighted sum or custom Feature counts the running sum of event values, not its time-weighted or custom billing value.

Denial reasons

A denial is an HTTP 200 response with allowed: false and one of these reason values: For example, an unknown feature code returns:

SDK wrappers

Node:
Python:
React: fetch the result through your authenticated backend and pass it to FeatureGate, UsageGate, or your own UI.

Availability and freshness

If usage cannot be read reliably, the hosted API returns HTTP 503 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.