Meters
A meter answers one question: given all the usage events in this billing period, what is the billable quantity?
It names the events it cares about, how to combine them, and how often the count resets. Bind it to a usage-based product and that product finally has something to bill.
The four required fields
key, name, metric_key and function. Everything else is optional.
metric_key is the join: it must match the metric_key on the events you send.
key is the meter's own org-unique slug.
How events are combined
function is one of eight:
| Function | Billable quantity |
|---|---|
SUM | Every event's quantity added up. The usual choice |
COUNT | How many events arrived, ignoring quantity |
MAX / MIN | The largest or smallest single value seen |
AVG | The mean across events |
LAST | The most recent value. For gauges: seats in use, storage held |
UNIQUE_COUNT | Distinct values. Active users, distinct devices |
P95 | The 95th percentile. For bandwidth billed on burst |
SUM and LAST cover most cases, and they are opposites. Metering API calls is
SUM, because each call is a separate thing consumed. Metering storage is
LAST, because 100 GB held all month is 100 GB, not 3,000 GB-days.
When the count resets
window is the reset cadence, and it has exactly one field:
Code
duration is in nanoseconds, between one minute and one year. Omit window
entirely and the meter aggregates over the whole period, which is what most
meters want.
When a duration is set, the billing period is tiled into consecutive windows of that size, covering the period exactly, and each tile becomes its own invoice line.
There is no `kind` field, whatever older examples show
window once carried a six-value kind discriminator. Five of those values
could not produce a correct billable number for a billing period, and the sixth
then carried no information, so the whole discriminator was removed in migration
208 along with session_gap. The request schema rejects unknown properties, so a
meter body containing kind is refused outright.
Narrowing what counts
| Field | What it does |
|---|---|
filter_tree | A predicate tree; only matching events are aggregated |
dimensions | Event metadata fields exposed for group-by |
event_schema | A JSON Schema that ingested events must satisfy |
dedup_key_path | JSON path to the field used for deduplication |
negative_allowed | Whether the aggregate may go below zero |
composed_of | Defines a derived meter computed from other meters |
Events that arrive late
late_event_policy decides what happens to an event stamped inside a period that
has already been billed:
| Policy | Behaviour |
|---|---|
DROP | Ignore it. Simple and safe |
CLAMP_TO_PERIOD | Count it in the current open period instead |
REBILL_PRIOR | Reopen the earlier period and re-bill it |
DROP is the conservative default choice. REBILL_PRIOR is honest but produces
corrections on invoices customers have already seen, so choose it deliberately.
Binding a meter to a product
A meter on its own aggregates nothing billable. POST /v1/meters/{id}/bindings
attaches it to a product, and only then does a usage-based product produce a
line. The dashboard shows an unbound product with a Needs meter binding
badge.
GET /v1/meters/unmetered-keys lists metric keys that are arriving with no meter
to receive them, which is the fastest way to find a typo in metric_key.
Reference
| Topic | When you need it |
|---|---|
| Usage | Recording the events a meter reads |
| Products | Usage-based products and their bindings |
| Prices | Turning the aggregated quantity into money |
| Meters API | Every field, plus breaches, bindings and test-event |