Monetization Policy
The Monetization policy allows you to track and monetize the usage of your API resources, declaratively and programmatically.
Follow our official documentation API Monetization with Zuplo to get started.
Configuration
The configuration shows how to configure the policy in the 'policies.json' document.
Code
Policy Configuration
name<string>- The name of your policy instance. This is used as a reference in your routes.policyType<string>- The identifier of the policy. This is used by the Zuplo UI. Value should bemonetization-inbound.handler.export<string>- The name of the exported type. Value should beMonetizationInboundPolicy.handler.module<string>- The module containing the policy. Value should be$import(@zuplo/runtime).handler.options<object>- The options for this policy. See Policy Options below.
Policy Options
The options for this policy are specified below. All properties are optional unless specifically marked as required.
meters<object>- The meters to be used by the policy against the subscription quota.requiredEntitlements<string[]>- A list of entitlement keys that the subscription must have access to (hasAccess=true) for the request to be allowed. If any required entitlement is missing or does not have access, the request will be rejected with a 403 Forbidden.authHeader<string>- The name of the header with the key. Defaults to"Authorization".authScheme<string>- The scheme used on the header. Defaults to"Bearer".cacheTtlSeconds<number>- The time to cache authentication results for a particular key. Higher values will decrease latency. Cached results will be valid until the cache expires even in the event the key is deleted, etc. Defaults to60.meterOnStatusCodes<undefined>- A list of successful status codes and ranges "200-299, 304" that should trigger a metering call. Defaults to"200-299".
Using the Policy
Monetization Metering Policy
The Monetization policy validates subscriptions and records usage. Meter usage is sent in a final response hook after status-code filtering.
Configuration
meters(optional): static meter increments applied on metered responses.meterOnStatusCodes: status codes/ranges that trigger metering.- auth/cache settings:
authHeader,authScheme,cacheTtlSeconds.
Static meter configuration
Code
Runtime meter updates
You can set or update meter increments at different points in a request lifecycle (for example in an inbound policy, handler, or outbound policy). The monetization policy reads the latest values in its final hook before sending usage.
Set (replace) request meter increments
Code
Add (accumulate) request meter increments
Code
Read current request meter increments
Code
Flush (send) runtime meters mid-request
Use flushMeters to send accumulated runtime meters immediately and reset their
counts. This is useful for long-running requests where you want to report
partial usage before the response is sent (for example, after each chunk of work
in a streaming handler).
Code
Static options.meters are not included in flushMeters; they are still sent
in the final response hook.
Note: flushMeters performs entitlement validation and will throw if called
before the monetization policy runs on the request or if you send meters that
aren’t present/accessible on the subscription. Wrap in try/catch if you want
to continue the request when a flush fails.
Subscription data (for customization)
The monetization policy validates the API key and attaches the subscription to the request context. You can read it later in your pipeline/handler to customize behavior (limits, feature flags, plan-based behavior, etc.).
Read subscription data
Code
Common fields you’ll likely use
- Identity:
subscription.id,subscription.customerId,subscription.name - Plan:
subscription.plan.key,subscription.plan.version - Status & dates:
subscription.status,subscription.activeFrom,subscription.activeTo,subscription.nextBillingDate - Entitlements:
subscription.entitlements[meterName]→{ balance, usage, overage, hasAccess } - Payment (when present):
subscription.paymentStatus.status,subscription.paymentStatus.isFirstPayment
Example: gate a feature by plan
Code
Example: check entitlement access or remaining balance
Code
Example: customize response headers
Code
Meter merge behavior
- The final hook merges
options.metersand request meter increments fromsetMeters/addMeters. setMetersreplaces the current runtime meter map and overrides matching keys fromoptions.meters.addMetersaccumulates into the current runtime meter map and then merges additively withoptions.meters.- If both are empty, metering is skipped.
For a meter key like api with options.meters.api = 1:
setMeters(context, { api: 50 })sendsapi: 50.addMeters(context, { api: 50 })sendsapi: 51.
Prerequisites
monetization-inboundis enabled in your route/pipeline.- Meter names match entitlements on the subscription.
- Meter quantities are finite positive numbers.
Notes
setMetersreplaces current request meter increments.addMetersaccumulates values across multiple calls.flushMeterssends runtime meters immediately, clears them before the backend send (to avoid duplicate sends if the final hook runs concurrently), and restores them if the send fails.- Entitlements are validated before usage is sent.
Read more about how policies work