Skip to content

Metered usage

A usage component prices a subscription on what the customer used, not on a fixed quantity. You post events; Paylera aggregates them at period close; the result becomes the line item on the invoice.

The lifecycle

your service ──► POST /v1/usage ──► aggregator ──► invoice line item
  1. Your application emits a usage event when something happens worth metering (an API call completes, a job runs, a seat is provisioned).
  2. The event is persisted with (subscription_id, meter, quantity, timestamp, idempotency_key).
  3. At period close, the aggregator sums events per (subscription, meter) and feeds the total to the pricing model on the matching component.

Posting an event

POST /v1/usage
Idempotency-Key: <uuid>
Content-Type: application/json
{
"subscription_id": "sub_…",
"meter": "api_calls",
"quantity": "1",
"timestamp": "2026-05-06T12:34:56Z",
"external_id": "req_8f4a…"
}

external_id is yours — your request ID, your job ID, anything that deduplicates events within your system. If two events arrive with the same (subscription_id, meter, external_id), the second is dropped silently and the response is the same as the first. This is your safety net for retries.

Quantities are decimals

quantity is a decimal string. You can send fractional units ("0.001") for things measured in milli-anything. Negative quantities are allowed (-1) for emitting corrections — useful if you over-counted.

Meters

A meter is an arbitrary string you and Paylera agree on. The meter value on a usage component must match the meter on the events you post.

By convention, lower-snake-case: api_calls, compute_seconds, bytes_egress, model_tokens.

Aggregations

Each usage component declares an aggregation:

AggregationWhat it computes
sum (default)Total quantity across all events in the period.
maxMaximum single-event quantity in the period.
last_during_periodThe quantity of the most recent event. Useful for “current seat count.”
unique_countNumber of distinct external_id values (deduped).

Late events

Events whose timestamp falls in a closed period are late. Two behaviours:

Component settingBehaviour
late_events: next_period (default)Late events apply to the next open period. Simple, predictable.
late_events: rebillThe closed period’s invoice is voided and re-issued with the late events included. A credit note is automatically posted for the void; the new invoice replaces it.

rebill only applies if the original invoice has not yet been paid; once paid, late events go to the next period regardless.

The 24-hour window after period close is the practical deadline for rebill. Configure on the plan component.

Inspecting

Read the running totals for the current period:

GET /v1/subscriptions/{id}/usage?period=current
{
"period": { "start": "2026-05-01T00:00:00Z", "end": "2026-06-01T00:00:00Z" },
"meters": [
{ "meter": "api_calls", "quantity": "84219", "events": 84219 },
{ "meter": "compute_seconds", "quantity": "12.7", "events": 18 }
]
}

Use period=closed&closed_at=2026-04-30 to get a closed period’s totals.

Best practices

  • Post one event per countable action when feasible. The aggregator is cheap; sending one event with quantity: 1000 works but loses the audit trail per action.
  • Always send an external_id. Retries are routine.
  • Don’t rely on event order. Aggregations are commutative; out-of-order delivery doesn’t change the total.
  • Use last_during_period for state, not for counts. “Current seat count” is state. “Number of seat changes” is a count — use sum with delta events.

Where to next