Billing

The prepaid wallet, request-time credit reservations, metered usage, and video billing.

Prepaid wallet

Every organisation has a prepaid wallet. Usage is metered per model (SKU) from the provider's own reported usage — never estimated — and priced at the catalogue rate for that model at nano-USD precision.

How reservations work

Before calling the provider, the gateway reserves an estimated cost against balance minus open reservations:

  1. The estimate is sized from max_tokens (falling back to a platform default when omitted), priced at the model's rate.
  2. The reservation is held for the life of the request.
  3. Once usage is metered, the reservation is settled to the real cost (or released, if the request failed).

Because the check is against balance minus open reservations, concurrent requests cannot collectively overspend a small balance. This reservation gate applies to prepaid wallets — postpaid orgs are capped by a monthly budget instead (a counter cap, not a reservation).

Why 402 is not 429

If the wallet cannot cover the reservation you get HTTP 402:

{
  "error": {
    "type": "insufficient_quota",
    "message": "Insufficient credit balance — top up to continue",
    "code": "insufficient_funds",
    "param": null,
    "request_id": "req_01J8EXAMPLE"
  }
}

A funds denial is deliberately not a 429:

  • It is not congestion — SDK retry/backoff does not help.
  • No Retry-After is sent.
  • Retrying without topping up will keep failing.

Top up in Billing (Stripe) and retry.

StatusCodeTrigger
402insufficient_fundsWallet cannot cover the reservation.
402key_spend_cap_reachedPer-key USD spend cap reached.
402project_quota_exceededProject monthly cost ceiling reached.
429quota_exceeded / project_quota_exceededToken quota windows (not funds).

Cached tokens

Provider-reported prompt-cache tokens are surfaced, never estimated:

  • OpenAI-dialect bodies: usage.prompt_tokens_details.cached_tokens / .cache_write_tokens
  • Anthropic-dialect bodies: usage.cache_read_input_tokens / usage.cache_creation_input_tokens
  • Every body: provider_metadata.cache.read_tokens / .write_tokens

On OpenAI-dialect chat/embeddings responses these prompt_tokens_details fields are always present (0 when the backend didn't report caching) — see Normalized usage shape. The billed amount always matches what's displayed, including the cache discount: the same cache figures the client sees are what's metered, never a separately-computed number.

Cached tokens are priced at the model's cached rate when the catalogue defines one, and the standard rate otherwise.

Video billing

Video jobs are billed only on confirmed completion:

Job statebilling.stateCharged?
queued / processingpendingNo — but see the reservation above
completedchargedYes
failedvoidNo
cancelledvoidNo

The billed unit is the requested duration (seconds). A job that expires past its retention window keeps its already-settled charge; nothing further is billed.

Inspecting spend

  • Portal → Billing: wallet balance, top-ups, invoices.
  • Portal → Analytics: token/cost breakdown per model and per key.
  • Every response's usage block shows exactly what was metered for that request.