Programmatic Monetization
Pricing rules often depend on who's calling or what your API returns. A few examples:
- Restrict bulk export to the Enterprise plan.
- Offer advanced search only to plans that include it.
- Bill an AI endpoint by the tokens it returns, and a search endpoint by the rows it matches — not a flat amount per call.
You can enforce rules and meter usage declaratively with features and entitlements on your plans, in code with custom policies, or both together. This guide covers the code path, for decisions that need runtime logic. It shows two techniques, then combines them:
- Gate operations by plan — read the caller's subscription and allow or block the request based on their plan or entitlements.
- Meter from the response — compute usage from the response body, report it, and enforce a quota on it.
Both build on the MonetizationInboundPolicy: the
subscription data it exposes and its
dynamic metering methods. Add that policy to your
monetized routes first.
Gate operations by plan
To make an operation available on some plans but not others, read the
subscription in a custom code inbound policy and block the request when the plan
doesn't qualify. Place the policy after monetization-inbound so the
subscription data exists on the context.
Code
To gate on a specific feature instead of the whole plan, check its entitlement:
Code
Register the policy and apply it after monetization-inbound on the routes you
want to protect:
Code
Code
Meter from the response
For variable-cost endpoints, meter a request by something you only know once the
backend responds — the number of records returned, items processed, or tokens
generated. Compute the value in a custom code outbound policy and report it with
MonetizationInboundPolicy.addMeters.
Code
addMeters accumulates with any static meters and earlier calls; use
setMeters to replace the runtime value instead. The policy sends the combined
total once the response goes out, and only for the configured status codes. See
Dynamic Metering for the full API and merge rules.
Block on a response-derived meter
addMeters runs in an outbound policy — it sees the response only after the
handler returns. By then it's too late to block the current request, and because
the meter never appeared in the policy's static config, the inbound quota check
never ran for it. A caller who is already over their limit still gets through.
To enforce the quota, declare the meter in the policy's meters option with a
value of 0:
Code
This does two things:
- Enforces the quota up front. At request time the policy checks the
recordsentitlement and returns403 Forbiddenwhen the balance has run out — before the request reaches your backend. - Avoids double-counting. The static
0contributes nothing to the total. Runtime values add to the static base (0 + n = n), soaddMetersreports the exact amount to bill.
The quota check runs at the start of each request and lets through any caller
who still has balance; the policy charges usage after the response. So a request
whose cost exceeds the remaining balance still completes, the balance goes
negative, and the policy blocks the next request. An increment of 1 enforces
the quota exactly — a caller overshoots only when a single request meters more
than 1 against a partial balance.
Putting it together
A complete setup for a metered, plan-gated, response-counted route:
Code
Code
The request flows through the monetization policy (authenticates, checks the
records quota, blocks if the quota has run out), then the plan gate (allows
the operation only on qualifying plans), then your handler, then the outbound
policy (counts the records and reports them with addMeters).
Next steps
- Reading Subscription Data — the full subscription object you can read in code.
- Dynamic Metering — the full
setMeters/addMeters/getMetersAPI and how static and runtime values merge. - Monetization Policy Reference — every configuration option.
- Meters — defining the meters your policies increment.