Billing reconciliation
Reconcile Nexus metering and billed costs against provider usage
Esta página aún no está disponible en tu idioma.
Opt-in, admin-key tooling that treats each provider’s billing as the ground truth for pricing and cost. Two scripts:
derive_rates.py: derive a rate card from the admin usage + cost APIs (rate = billed_amount / billed_tokens) and inspect how deterministically each band/tier rate can be recovered.reconcile.py: drive a tier x band request matrix through nexus and reconcile nexus’s recorded cost against the provider-billed dollars, plus a “reconcile a prior window” mode for the daily bucket settle.
All scripts read credentials from the environment or the repo-root .env.
They use only the Python standard library.
Run these from test-suite/billing/:
python3 derive_rates.py --days 31python3 reconcile.py --window --days 31 # reconcile a prior windowRun validation directly from nexus/. This is the authoritative command list
for these gates. docs/dev/testing.md and
docs/ops/provider-pricing.md repeat it
for convenience; if a flag here and in one of those ever disagrees, this file
wins:
cargo test -p nexus-registry-artifactcargo test -p nexus-registry-generatorcargo test -p nexus-registry --test import_change_set_migrationpython3 -m unittest discover -s test-suite/billing -p 'test_*.py'python3 test-suite/billing/validate_pricing.py --provider both --bands bothpython3 test-suite/billing/reconcile.py --sidecar test-suite/billing/reports/<run>.requests.jsonThe Rust tests have no provider spend. They validate the canonical manifest/JSONL contract, deterministic conversion of copied provider fixtures, and the persisted import schema. Artifact generation is the only provider catalog collection path; the runtime registry test suite does not fetch provider documents or APIs.
The gateway test (validate_pricing.py) requires a healthy stack and query
credentials (NEXUS_QUERY_TOKEN or NEXUS_SERVICE_TOKEN).
It routes live requests through Nexus API keys supplied by the environment:
NEXUS_API_KEY by default, or NEXUS_ISO_OPENAI_API_KEY /
NEXUS_ISO_ANTHROPIC_API_KEY with --isolated so each provider’s spend is
attributable to its isolated project or workspace.
The org id comes from NEXUS_RECONCILE_ORG_ID (or NEXUS_ISO_ORG_ID with
--isolated) or is resolved from the API-key prefix via the dev Postgres
container.
Expected rates and exact context thresholds come from the curated contracts,
never from the registry under test.
The supported-pricing manifest limits live Chat/Messages cells to
request-observable modes: OpenAI standard, flex, and priority where the model
publishes that tier, and Anthropic Messages standard.
Each inventory key records its request surface, and only explicit
live_probe_priority models that are present in the gateway’s authenticated
/v1/models catalog can enter the paid matrix.
Response-only pro models, source-only aliases, and inactive catalog entries are
covered by deterministic contract/rejection tests instead.
Provider Batch API rate cards remain source-validated, but batch never enters
the Chat or Messages matrix because both Batch APIs are explicit unsupported
request modes.
The OpenAI Responses path matrix sends identical cache-eligible requests in
sequence and requires the expected cache-write then cache-read meters.
Chat and streaming Chat remain exact rate/band checks; they do not claim a
deterministic cache read when the supported live model does not report one.
Settlement (reconcile.py --sidecar, opt-in via NEXUS_BILLING_RECONCILE=1)
returns a machine-readable process state; a failure outranks a pending
provider, which outranks missing configuration:
0: every configured provider passed.1: at least one configured provider failed.2: provider reporting is pending.3: provider admin or isolation configuration is absent.
Sidecars keep Nexus totals separated by provider.
Provider admin totals are selected only from the configured isolated OpenAI
project or Anthropic workspace.
Run the same sidecar after the first and second daily settlement boundaries;
an unresolved pending state remains distinct from both failure and missing
configuration.
Rate-derivation findings (run live 2026-06)
Section titled “Rate-derivation findings (run live 2026-06)”Both providers expose enough granularity to recover per-(tier, band, token-type) rates for any model the org has actually used, and the derived rates matched the reviewed registry artifact exactly:
-
OpenAI
/v1/organization/costs?group_by[]=line_itemreturnsamount+quantityper line item, and theline_itemstring itself encodes:- token type (
input/output/cached input), - context band (a
, long contextsuffix), and - service tier (a
<tier> |prefix, e.g.priority | gpt-5.3-codex, input).
So
amount / quantityyields the exact per-token rate per band and tier. Observed:gpt-5.5 input$5.00/1M vsinput, long context$10.00/1M;output$30/1M vsoutput, long context$45/1M;priority | gpt-5.3-codex input$3.50/1M. There is nopriority ... long contextline, which corroborates the reviewed artifact evidence that OpenAI priority is flat.This is stronger than the API reference implied: the costs line item, not just the usage report, carries the context band. (The usage
service_tier/batchgroup-bys remain useful for token attribution.) - token type (
-
Anthropic
/v1/organizations/cost_report?group_by[]=descriptionsplitsamountbymodel x service_tier (standard|batch) x context_window (0-200k|200k-1M) x token_type, and/v1/organizations/usage_report/messagesreturns matching token counts, so the rate iscost_amount / usage_tokensper dimension. Observed:claude-haiku-4-5uncached_input$1.00/1M,output$5.00/1M.
Limits
Section titled “Limits”- Coverage is scoped to models/dimensions the org was actually billed for — not a full catalog. So admin-derived rates are a validation/calibration layer over routed models, not a replacement for the generated and reviewed artifact that enumerates every model.
- Daily (
1d) buckets, 31-bucket page cap (pagination is a future extension).
OpenAI admin Costs calibrate the band and tier matrix for models used by the isolated project. Anthropic admin cost and usage reports calibrate used models in the isolated workspace. Curated provider contracts remain the complete expected catalog because admin reports contain only dimensions that incurred usage.
