Ir al contenido
↑↓Navigate↵SelectescClose

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/:

Terminal window
python3 derive_rates.py --days 31
python3 reconcile.py --window --days 31 # reconcile a prior window

Run 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:

Terminal window
cargo test -p nexus-registry-artifact
cargo test -p nexus-registry-generator
cargo test -p nexus-registry --test import_change_set_migration
python3 -m unittest discover -s test-suite/billing -p 'test_*.py'
python3 test-suite/billing/validate_pricing.py --provider both --bands both
python3 test-suite/billing/reconcile.py --sidecar test-suite/billing/reports/<run>.requests.json

The 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_item returns amount + quantity per line item, and the line_item string itself encodes:

    • token type (input / output / cached input),
    • context band (a , long context suffix), and
    • service tier (a <tier> | prefix, e.g. priority | gpt-5.3-codex, input).

    So amount / quantity yields the exact per-token rate per band and tier. Observed: gpt-5.5 input $5.00/1M vs input, long context $10.00/1M; output $30/1M vs output, long context $45/1M; priority | gpt-5.3-codex input $3.50/1M. There is no priority ... long context line, 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/batch group-bys remain useful for token attribution.)

  • Anthropic /v1/organizations/cost_report?group_by[]=description splits amount by model x service_tier (standard|batch) x context_window (0-200k|200k-1M) x token_type, and /v1/organizations/usage_report/messages returns matching token counts, so the rate is cost_amount / usage_tokens per dimension. Observed: claude-haiku-4-5 uncached_input $1.00/1M, output $5.00/1M.

  • 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.