Meter
Usage metering for billable or quota-managed events: admins define metrics (unit, dimensions, quota, graduated pricing), producers ingest idempotent usage events into time buckets, and callers query totals, top consumers, forecasts, cost estimates, and durable reports. Budget enforcement - preflight checks, reserve-then-commit, quota alarms - has its own page: Budgets and quotas. Every example on this page was executed against a live server.
When to reach for it: LLM token accounting with budget cutoff, daily billable totals for API calls or storage, per-user quotas with soft/hard limits, top-K consumers, usage forecasts.
When not to: limiting request rate is the platform rate limiter or a custom Throttle policy - Meter counts cumulative usage against budgets, not requests per window. Virtual currency with transfers and holds belongs to Treasury.
Concepts
- A metric declares a usage stream: name (
llm.tokens), unit, aggregation (sum,max,min,unique,last,top_k) into time buckets, declared dimensions, quota, pricing, retention. Creating one requires an admin orbilling_admintoken; create is an upsert by name - themet_...id is derived from the name and re-creating bumpsversion. - Events are increments, not rows - each event adds
valueto the current bucket. Individual events are not stored or queryable. - Idempotency keys are required on every event, so retries never double-count.
- Dimensions (
model=gpt-5-mini) attribute usage for top-K breakdowns. Declaredrequireddimensions are enforced at ingest. - Everything is scoped per user. Events, usage, quotas, and
reservations default to the caller; naming another
user_idrequires admin orbilling_admin, otherwise403 insufficient_permissions("cannot act on another user" - verified). - Reports are durable rollups - generated snapshots of totals, top consumers, quota status, and estimated cost, listable later.
Define a metric
snug meter metrics create --file ./llm-tokens.json # admin or billing_admin
snug meter metrics list -q docs4
snug meter metrics get --metric docs4.tokensThe file is a CreateMetricRequest; only name and unit are required:
{
"name": "docs4.tokens",
"unit": "token",
"aggregation": { "kind": "sum", "bucket": "minute", "rollups": ["hour", "day"] },
"dimensions": [ { "name": "model", "required": true, "cardinality": "medium" } ],
"quota": { "enabled": true, "soft_limit": 1000, "hard_limit": 2000, "period": "day" },
"pricing": { "currency": "USD", "tiers": [
{ "up_to": 1000, "unit_price": 0.002 },
{ "up_to": null, "unit_price": 0.001 } ] }
}With a regular token, create fails with 403 insufficient_permissions;
listing and reading metrics is open to any caller. Listing speaks the
shared search grammar - verified:
--filter "unit:eq:call" narrows to metrics with that unit. There is no
delete endpoint - retire a metric by ceasing to ingest it.
Record usage
snug meter log @me tokens:500 --metric docs4.tokens \
--dimension model=gpt-5-mini --idempotency-key req-789
snug meter batch-log --file events.json # JSON array of event objectsOver HTTP, single and batch ingest are the same endpoint:
curl -X POST -H "Authorization: Bearer $SNUG_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"events":[{"metric":"docs4.tokens","value":120,"idempotency_key":"req-790",
"dimensions":{"model":"gpt-5-mini","feature":"chat"}}]}' \
http://localhost:4000/api/v1/meter/events{
"status": 202,
"msg": "Accepted",
"data": {
"accepted": 1,
"duplicates": 0,
"rejected": 0,
"results": [
{ "idempotency_key": "req-790", "status": "accepted",
"bucket": "2026-08-28T12:46:00+00:00" }
]
}
}Per-event status is accepted, duplicate, rejected_quota, or
rejected_schema. Verified behaviors:
- Replaying the same key with the same payload returns
duplicateand adds nothing - safe to retry. - The same key with a different payload is
409 idempotency_conflict. - Omitting a required dimension is
400 schema_rejected(missing required dimension: model). - A rejected event does not fail the request - the batch still returns
202and the CLI exits 0. Checkrejectedandresults[].status.
Query usage
snug meter usage @me --metric docs4.tokens --period day
snug meter top --metric docs4.tokens --dimension model --period today
snug meter forecast --metric docs4.tokensusage returns time buckets plus a total; --period selects the
resolution (minute, hour, billing_cycle, anything else means day)
with a lookback of 60 minutes, 48 hours, or 35 days respectively. top
ranks dimension values by usage (gpt-5-mini: 720.0), and forecast
projects end-of-period usage from current velocity with a confidence
score - all captured live.
Pricing and reports
estimate prices units through the graduated tiers - verified: 1500 units
against the tiers above is 1000 x 0.002 + 500 x 0.001 = 2.5 USD:
snug meter estimate --metric docs4.tokens --units 1500
snug meter generate-report --metric docs4.tokens --period day # admin or billing_admin
snug meter reports --metric docs4.tokensA report snapshots total, unique_count, estimated_cost, quota status,
and top_consumers at generation time. Generating requires admin or
billing_admin (verified 403 otherwise); listing existing reports is
open to any caller.
Budgets, reservations, and alarms
Preflight checks, the reserve-then-commit arc, over-budget refusals, and quota alarms are on the Budgets and quotas page.
Limits and configuration
Batches up to 1000 events, 12 dimensions per event, 35-day idempotency and
hot-bucket retention, and 1-hour reservation TTL by default - all tunable
via the METER_* variables in the
Meter CONFIG reference.
Reference
- Meter API - every endpoint, callable
- Related: Rate limits and Throttle for request-rate control, Treasury for virtual currency, Surge Pricing for demand-driven price multipliers