Skip to main content
This guide explains how to connect Open Next Router (ONR) to Meterry for usage collection, asynchronous ingestion, dynamic pricing, and Usage Explorer queries. ONR uses asynchronous billing: it completes the model request first, appends a billing event to a local outbox, and lets a background worker deliver the event to Meterry. A temporary Meterry outage does not change a response that has already been returned to the client.

Architecture and responsibilities

ONR is responsible for:
  • extracting upstream usage according to the provider DSL;
  • estimating usage when the upstream does not return it;
  • calculating request-level prices from ONR pricing files;
  • mapping an access key to a Meterry subject;
  • persisting events in an outbox and retrying delivery.
Meterry is responsible for:
  • extractor rule-set field extraction;
  • charge-item metering and pricing;
  • accounts, wallets, subject routes, and usage limits;
  • usage events, billing, and aggregate queries.
ONR does not send prompts, Authorization headers, upstream API keys, or traffic dumps to Meterry.

1. Prepare the Meterry project

Use the correct API host

The portal and API use different hosts:
ONR_METERRY_BASE_URL must point to the API host:
Using https://meterry.com for ingest returns an HTML 404 page.

Create and publish an extractor rule set

Create an extractor rule set in the project’s Rules page and publish it before ingesting events. A draft rule returns extractor rule set is not published. ONR emits these normalized usage fields:
For OpenAI-compatible rules, ONR also emits these aliases:
A rule set should extract at least:
If you use Meterry’s OpenAI-compatible rule, charge-item metrics are normally prompt_tokens and completion_tokens; these are the metric names used by ONR’s x-billing.items.

Use a dynamic amount expression

Token charge items must calculate their amount from quantity and price. Do not leave amount_expr fixed at zero:
A fixed zero expression records token quantities but always produces an amount of zero.

Configure the subject

By default, ONR uses the access-key name as the billing subject:
For example:
The event contains:
Meterry account, wallet, and subject-route configuration must use the same subject type and ID.

2. Configure ONR

Keep credentials in .env or the deployment environment; do not commit them to Git:
Enable Meterry in onr.yaml:
only_billable_success: true reports only 2xx model requests. outbox_dir stores pending JSONL events, while the timeout and retry settings control delivery. fallback_subject_id is used for master-key requests or requests without a matching access key. Validate the configuration and start ONR:

3. Event shape

ONR sends events to:
An event is shaped like this:
x-billing.items makes the runtime token quantities the charge-item source of truth. x-billing.pricing_hints carries the provider/model/channel pricing calculated by ONR to Meterry.

4. Delivery, retries, and idempotency

The delivery flow is:
The idempotency key is onr:<request_id>. Failed events remain in the outbox and are retried, including after a process restart. Keep the same request ID on retries; generating a new one creates duplicate billing events.

5. Verify a real ingest

Use a fixed request ID for a smoke test:
Check the outbox:
After successful delivery, the file should be empty or absent. Query event details through the Meterry API:
Verify external_event_id, subject fields, token metrics, amount, unit price, raw_event_id, and usage_event_id.

6. User wallet balance enforcement

Meterry debits an account wallet when it processes a rated usage event. Keep account, wallet, credit, and subject-route management in the existing business backend:
  1. Create one Meterry account and USD wallet for each access key.
  2. Bind api_key/<access-key-name> to that account with a subject route.
  3. Credit the wallet through POST /v1/projects/:project_id/wallets/credit.
  4. Keep the ONR event subject unchanged so Meterry can resolve the payer wallet.
When enabled, ONR performs a best-effort request pre-check:
When the returned balance is zero or negative, ONR returns 402 Payment Required with an OpenAI-compatible error:
The pre-check does not reserve money. Meterry remains the only balance ledger and performs the final debit after asynchronous event processing. Concurrent requests can therefore briefly overspend a wallet. Balance lookup failures use failure_mode: "closed" by default and reject the request with 503. Set failure_mode: "open" to allow requests while Meterry is unavailable. Requests without a mapped access-key subject, including master-key requests, bypass balance enforcement unless they are explicitly assigned a fallback subject. Configure the webhook endpoint at POST /internal/meterry/webhook in ONR and register the same URL in Meterry. ONR verifies the HMAC-SHA256 signature, rejects stale timestamps, deduplicates webhook IDs, and persists subject state for wallet.insufficient_balance, wallet.balance_changed, wallet.available_balance.threshold_crossed, and usage_limit.exhausted. Store webhook_secret in the deployment environment rather than committing it to Git:

7. Usage Explorer queries

Summary queries grouped by metric require an explicit metric; otherwise Usage Explorer reports:
Use a filter such as:
The model value is gpt-4o-mini, not gpt_4o_mini. Use Events to inspect individual records and Summary with a metric to inspect aggregate amounts.

8. Troubleshooting

HTML 404 from the API

Set the base URL to https://api.meterry.com, not the portal URL.

extractor rule set is not published

Publish the extractor rule set from the project’s Rules page.

Event accepted but Usage Explorer is empty

Check that the rule is published, subject fields are present and routed, rule paths match raw_json, charge-item metrics match x-billing.items, the query specifies a metric, and the time range covers occurred_at.

Token quantity exists but amount is zero

Replace a fixed dec('0') amount expression with the dynamic quantity / pricing_unit * unit_price expression shown above.

Outbox never drains

Check the API host, project/API-key/rule-set consistency, published status, the API key’s usage:ingest scope, and network access from the ONR process.

Balance checks reject every request

Confirm the access key has a matching api_key/<name> subject route, the account has a USD wallet, the wallet balance is positive, and the configured project API key can read realtime wallet amounts.

Webhooks return 401

Check that the raw request body is signed, the timestamp is within timestamp_tolerance_s, and webhook_secret exactly matches the secret configured for the Meterry webhook endpoint.

9. Limitations

ONR does not create Meterry accounts, wallets, subject routes, or credits. The balance pre-check is not a reservation and cannot prevent all concurrent overspend. Payment collection and wallet top-ups remain the responsibility of the existing business backend.