Skip to main content

Charging for Consumption

Usage-based billing charges customers based on consumption rather than a fixed price. Common use cases:
  • API calls
  • Storage (GB)
  • Compute hours
  • Active users
  • Transactions processed

How It Works

Metered billing is three pieces:
  1. A billable metric — a named meter that reduces raw usage events to one quantity per period (eight aggregations, from count to a sandboxed custom expression).
  2. A charge — a pricing model (per_unit, graduated, volume, package, percentage, graduated_percentage, or dynamic) attaching that metric to a plan.
  3. Rating — at period close, Recurso aggregates the elapsed period’s events per metric, prices them, and adds the result to the renewal invoice as its own tax-resolved line item (billed in arrears).
Flat plan prices are untouched: a plan holding both a price and charges is hybrid — flat fee billed in advance, usage billed in arrears, on the same invoice.

1. Define a Billable Metric

The metric’s code doubles as the event dimension it aggregates, so any events you already report keep working.

Aggregations

A unique metric needs the property to count; percentile puts the percentile in field_name:
A weighted_sum metric time-weights a running level built from signed deltas — ideal for per-second resources like seats or provisioned units. Report +5 when five seats are added and -2 when two are removed; the metric bills the average level held over the period (5 seats for 15 days + 10 for 15 days → 7.5). The starting level carries forward, so a resource active before the period counts from day one. A custom metric evaluates an expression against every event and sums the results, so you can price on arithmetic over event fields without a bespoke aggregation:
The custom expression is sandboxed: it reads only quantity and numeric properties.*, has no functions or external access, is bounded in time and memory, and must return a number. It is validated when the metric is created, so an invalid expression is rejected up front — never at invoice time.

2. Attach Charges to a Plan

PUT /v1/plans/{id}/charges replaces the plan’s full charge set (same semantics as entitlements). Rates are decimal strings in major currency units — sub-paise pricing like ₹0.0035/call is first-class — while flat and package amounts are integers in minor units.

Report Usage

Report usage events throughout the billing period. The POST /v1/usage/events endpoint accepts:
string
required
The subscription to report usage for. Must belong to your tenant (404 otherwise).
string
required
The subscription’s customer (400 if it doesn’t match).
string
required
Usage dimension/meter name, e.g. api_calls — matches a billable metric’s code.
integer
required
Amount of usage to record. Must be greater than zero.
object
Optional string attributes (max 20; keys ≤100 chars, values ≤255) — unique metrics count distinct values of one of them.
string
Your idempotency key for this event (≤255 chars) — retries collapse to the original event instead of double-counting.
Recording is ownership-checked: the subscription must belong to your tenant (404 otherwise) and customer_id must match the subscription’s customer (400 otherwise). See the Record Usage Event reference.

Idempotent ingestion

Add a transaction_id (your own unique key, ≤255 chars) and retries can never double-count: a duplicate (subscription, transaction_id) collapses to the original event — the API answers 200 with "status": "duplicate" and the original event_id.

Batch ingestion

POST /v1/usage/events/batch accepts up to 500 events with per-item results — one bad event never fails the batch:

Charge Models

The same 7,000-call month prices very differently depending on the model — switch the tabs to compare:
Every unit at one rate.
1,500 calls × ₹0.0035 = ₹5.25. Sub-paise rates are computed exactly (big-rational arithmetic) and rounded half-up once per line.
Tier rules: bounds are strictly ascending; the last tier must leave up_to null (unbounded); a tier’s optional flat_amount (minor units) is added once when any unit lands in it. Amounts are validated at PUT time with the same code path that rates invoices, so a config that saves cannot fail at billing time.

What the Invoice Looks Like

At period close the renewal invoice carries the flat fee (in advance, as today) plus one line per charge with usage (in arrears). Zero-usage charges add no line. Each metered line is taxed through the normal per-line GST/HSN resolution — the charge’s hsn_code wins, falling back to the plan’s, then the tenant SAC. Rated windows are recorded in a usage_ratings claim keyed by (subscription, charge, period_start), so a retried invoice generation can never bill the same window twice. Immediate cancellation generates a final usage-only invoice for the partial elapsed window.

Bill in advance (per event)

By default usage bills in arrears at period close. Set pay_in_advance on a charge to bill each event’s usage the moment it’s reported — captured as a pending charge that folds onto the next invoice. Only non-cumulative models qualify (per_unit, percentage, dynamic), since a graduated/volume price depends on the whole period’s total.

Dimensional pricing (charge filters)

Price distinct values of one event property differently under a single charge. Set filter_key to the property and give per-value amounts; events matching no value fall to the charge’s base amounts.
Each value bills as its own invoice line, all under one rating claim. (Filters aren’t combined with the custom/weighted_sum aggregations or the dynamic model, which compute their quantity a different way.)

Progressive billing (interim invoices)

For high-usage customers you can bill before period close. Set a progressive_billing_threshold (minor units) on the subscription: once accrued usage crosses it, an interim invoice bills the delta since the last one, and the renewal invoice settles the remainder. A per-charge watermark guarantees every unit is billed exactly once — interim bills + close always sum to the same total as pure arrears, no double-billing across retries or concurrent runs. A background sweep triggers interim invoices automatically; you can also force one with POST /v1/subscriptions/{id}/bill-usage.

Simulate a price before you ship it

POST /v1/pricing/simulate rates a proposed charge set against sample or real usage without persisting anything — compare pricing options, see the rated lines and a balanced GL preview, and catch a mistake before it reaches an invoice.

Preview the Current Period

GET /v1/subscriptions/{id}/usage-amount prices the running period as of now — what the customer would owe if invoiced this second:
Hybrid billing works well for plans where you want a minimum commitment (the flat price) while still charging for heavy usage. Customers who stay inside a free first tier only pay the flat fee.

Query Usage Over Time

GET /v1/usage aggregates events into time buckets (day or month) over an arbitrary window — the endpoint behind usage charts. Scope by subscription_id, customer_id, or both, and optionally filter to one dimension. The window defaults to the last 30 days.
To discover which dimensions your services have been reporting, list the tenant’s dimension catalog:

Show Customers Their Usage

GET /v1/subscriptions/{id}/usage answers the question every usage-based product has to put on a dashboard: “you’ve used 4,231 of 10,000 API calls this month.” It returns each dimension’s total inside the current billing period plus its lifetime total — and here is the wiring that makes the “of 10,000” part work: when the customer holds an entitlement limit whose feature_key equals the dimension name, the effective limit_value and remaining headroom are joined into the row automatically.
Dimensions without a matching entitlement limit report limit_value: null and remaining: null; remaining goes negative when the customer is over their limit — a natural trigger for an upgrade prompt. See the Entitlements guide for how limits resolve across multiple subscriptions.

Best Practices

Use Idempotency

Always include idempotency keys to prevent duplicate charges. See the Idempotency guide.

Report Often

Report usage frequently (hourly) rather than in one batch

Show Estimates

Display current usage to customers in real-time

Set Alerts

Notify customers when approaching usage limits