Skip to content

Usage Events

A usage event is the smallest unit of usage Meterry accepts. Your backend or gateway sends a JSON envelope to the ingest API; Meterry stores it as a raw event, applies the published extractor rule set, builds normalized usage events, expands charge items, and rates them when pricing is available.

This page is a field-by-field tour of the event envelope. For the full request and response schema, see the Ingest Usage Event and Batch Ingest Usage Events API pages.

A single ingest call carries one envelope. The shape below shows every supported top-level field; you only send the fields your workflow needs.

{
"source": "openai-gateway",
"external_event_id": "chatcmpl_123",
"idempotency_key": "openai-gateway:chatcmpl_123",
"subject_type": "organization",
"subject_id": "org_001",
"occurred_at": 1781222400,
"raw_json": {
"type": "response",
"provider": "openai",
"usage": {
"model": "gpt-4.1-mini",
"prompt_tokens": 1200,
"output_tokens": 300
},
"meta": {
"org_id": "org_001",
"user_id": "user_123",
"api_key_id": "key_001"
}
},
"x-billing": {
"items": [
{ "metric": "tool_call.web_search", "quantity": 1, "unit": "call" }
],
"pricing_hints": {
"tool_call.web_search": { "unit_price": 0.1, "pricing_unit": 1, "currency": "USD" }
}
},
"x-usage-control": {
"budget_lease_id": "ble_..."
},
"metadata": {
"gateway_region": "us-east-1"
}
}
Field Required Purpose
source Yes Stable event-source name, for example openai-gateway, agent-runtime, or workflow-engine. Use it to group events by producer in analytics and to filter for support.
external_event_id No The upstream event or request ID. Carries through to the processed usage event so support and reconciliation can join Meterry data back to your system.
idempotency_key Strongly recommended A stable retry key. Reusing the same key in the same tenant produces the same raw_event_id; processing then deduplicates and never writes the raw event fact twice. Use the upstream request ID when one exists.
subject_type Conditionally Explicit subject type for this event. Must match [a-z][a-z0-9_]{0,63} and must be supplied together with subject_id.
subject_id Conditionally Explicit subject ID for this event. Must be supplied together with subject_type.
occurred_at No Event occurrence time as Unix seconds. Defaults to the server receive time. Use this to keep backfills and out-of-order deliveries routed to the correct window.
raw_json Yes The original usage JSON. Its shape is yours to design; the extractor rule set decides which fields become subject, dimensions, and charge items.
x-billing No Dynamic billing extension. Use it for sparse request-level items, pricing hints, and discount hints. See Dynamic Billing below.
x-usage-control No Usage-control extension. Set budget_lease_id to count this event against a one-time Budget Lease. See Budget Lease integration below.
metadata No Ingest-side metadata for audit and operations. Keep it small and non-sensitive. Categorical values automatically become dimensions on the rated usage event (a value that is pure digits is treated as an identifier and is skipped).

source, external_event_id, and idempotency_key are the trio that makes the event traceable and replayable. subject_type / subject_id, occurred_at, and raw_json are the trio that drives normalization and rating. The x-* extensions and metadata add request-level context without changing the underlying extractors.

The subject is the entity that produced the usage. It determines which billing account owns the event and which usage-control limits apply. Meterry resolves it in this order:

  1. Explicit subject on the envelope. When both subject_type and subject_id are present at the top level, Meterry uses that pair and does not run the extractor’s subject paths. Supplying only one of the two is invalid.
  2. Path-based subject in the extractor. Otherwise Meterry runs the precompiled subject.type_path and subject.id_path accessors against raw_json. Each path value wins over its matching default_type or default_id.
  3. Required check. If the rule set marks the subject as required and the result is still incomplete, normalization fails and the event is recorded as unconsumed. If it is optional, an incomplete subject pair is discarded and the event continues without a billing owner.

A dynamic subject type that comes from a path or default must still match [a-z][a-z0-9_]{0,63}. A wrong JSON type or an invalid subject type is rejected rather than silently substituted by a default.

raw_json is your own JSON. Meterry does not require any specific shape; the extractor rule set tells the runtime which fields to read.

A typical LLM event looks like:

{
"type": "response",
"provider": "openai",
"usage": {
"model": "gpt-4.1-mini",
"prompt_tokens": 1200,
"output_tokens": 300
},
"meta": {
"user_id": "u_01"
}
}

The rule set then maps that shape onto the normalized model:

  • meta.user_id becomes the subject_id, with the rule’s default_type filling in subject_type.
  • provider and usage.model become dimensions you can group by in analytics.
  • usage.prompt_tokens and usage.output_tokens become stable charge items with attached pricing.

The subject block, dimensions block, and charge_item_extractors block in the rule set are how you tell Meterry where to read each piece. See Create Rules and the LLM Gateway use case for end-to-end examples.

x-billing sits next to metadata at the top level of the request body. It carries three optional maps:

  • items — sparse request-level charge items that the extractor cannot know about, such as optional tool calls or one-off add-ons.
  • pricing_hints — per-metric overrides for unit price, pricing unit, and currency. Useful when the gateway picks the price dynamically.
  • discount_hints — per-metric discount adjustments layered on top of the rated price.

When the same metric is produced by both the extractor and x-billing.items, the reported x-billing item wins for that metric. See the full contract on the Ingest Usage Event API page and learn the runtime order in How Extraction Runs.

For agent runs that need a one-time hard cap, set x-usage-control.budget_lease_id on the envelope. Meterry:

  1. Snapshots the lease ID on the normalized usage event for audit.
  2. Debits the underlying billing account normally.
  3. Accumulates the rated amount against the lease window atomically.
  4. Emits budget_lease.exhausted only when a new rated version pushes the lease at or above its cap.

Replays of the same rated version are deduplicated, so retries do not double-charge the lease. See Create Budget Lease for the full request contract.

Use a project API key from API keys.

Authorization: Bearer <secret>
Content-Type: application/json

Do not send ingestion secrets from browser code. The ingest API is intended for trusted backends, gateways, and server-side SDKs.

After ingestion, Meterry returns a normalized usage event. Listing endpoints surface that normalized shape, with one row per event:

{
"tenant_id": "t_001",
"project_id": "proj_gateway",
"event_date": "2026-06-12",
"occurred_at": 1781222400,
"usage_event_id": "usage_evt_01",
"raw_event_id": "raw_evt_01",
"source": "llm_gateway",
"external_event_id": "chatcmpl_123",
"subject_type": "user",
"subject_id": "user_123",
"billing_account_id": "acct_xxx",
"labels": {
"provider": "openai",
"model": "gpt-4.1-mini"
},
"metrics": {
"input_tokens": { "value": "1200", "unit": "token", "currency": "USD", "amount": "0.00024", "unit_price": "0.0000002" },
"output_tokens": { "value": "300", "unit": "token", "currency": "USD", "amount": "0.00024", "unit_price": "0.0000008" }
},
"usage_version": 42,
"created_at": 1781222400
}
Field Purpose
usage_event_id Stable ID for the normalized usage event. Use this to join against downstream charge item rows.
raw_event_id Stable ID for the underlying raw event. It is also the idempotency_key you passed in, so you can trace a processed event back to your original request.
subject_type / subject_id The resolved subject after the explicit / path / default resolution above.
billing_account_id The account that owns this usage for fund debit. It is the persisted subject-route snapshot, not a label you can override.
event_date The event’s calendar date in the project’s reporting timezone, derived from occurred_at. Use it for daily aggregation.
occurred_at The event occurrence time in Unix seconds. This is the same value you sent on the envelope (or the server receive time when omitted).
source The ingest source name you provided.
external_event_id The upstream ID you provided, echoed back so you can join to your system.
labels The resolved dimensions for the event, keyed by dimension name.
metrics A flat map keyed by metric. Each entry carries the rated value, unit, currency, amount, and unit_price. Nested physical paths are surfaced as dotted logical metric names such as tool_call.web_search.
usage_version Monotonic version assigned to the event after rating. Use it to deduplicate replays when comparing two readings of the same event.
created_at When Meterry finished processing the event.

For the full query contract and filter parameters, see List Usage Events. When you also need the per-charge-item breakdown, use List Usage Event Details with the usage_event_id.

Open Usage explorer.

  1. Choose a time window.
  2. Add label filters such as provider=openai; model=gpt_4o_mini when needed.
  3. Choose breakdown dimensions such as metric, model, or provider.
  4. Select Show usage.

Use Live to refresh recent activity every few seconds. Advanced filters support subject type, subject ID, metrics, breakdown dimensions, and row limits.