Control
Usage
How usage is metered and billed: micro-USD accounting, reservations, settlement and rate limits.
Usage is prepaid and metered exactly. Every inference request and sandbox execution follows the same lifecycle: reserve the most it could cost, execute, charge what it actually cost, and release the rest.
Units
All money is integer micro-USD (µUSD): 1 USD = 1,000,000 µUSD. Balances, prices, costs, reservations and budgets are integers end to end; floating point is never used. In JSON, µUSD amounts are decimal strings such as "4466" so they survive parsers that lose precision on large numbers.
| µUSD | USD |
|---|---|
| 1 | 0.000001 |
| 1,000 | 0.001 |
| 10,000 | 0.01 |
| 1,000,000 | 1.00 |
Token costs
Model prices are µUSD per one million tokens (see Models). Input and output costs are each rounded up to the next whole µUSD:
cost = ceil(input_tokens × input_price / 1,000,000) + ceil(output_tokens × output_price / 1,000,000)Request lifecycle
- Checks. Scope, model, allowlists and rate limits are checked. Nothing is reserved yet.
- Reserve. Inside a transaction that locks the project balance, the gateway computes the estimated maximum cost, checks it against the key's monthly limit and the project budget, and moves it from
availabletoreserved. If the available balance is too low, the request fails withinsufficient_balance(HTTP 402). - Execute. The request is sent to the provider (or the sandbox node).
- Meter. Token usage reported by the provider is priced exactly.
- Settle. The actual cost is debited from the reservation and the unused remainder is released back to
available. - Receipt. A signed receipt records the operation and its cost.
The reservation for inference is:
estimated_input_tokens = ceil((content_bytes + 32 per message + tool_definition_bytes) / 2) + 16
max_output = min(max_completion_tokens or 4,096, model max_output_tokens)
reservation = ceil(estimated_input_tokens × input_price / 1,000,000)
+ ceil(max_output × output_price / 1,000,000)The input estimate assumes one token per two UTF-8 bytes. Real tokenizers average closer to four bytes per token for English, so the estimate deliberately over-reserves; the excess is released at settlement.
Worked example
A request with two messages totalling 2,000 bytes and max_completion_tokens: 1024, on a model priced at 1,100,000 µUSD (input) and 5,500,000 µUSD (output) per million tokens:
| Step | Calculation | µUSD |
|---|---|---|
| Estimated input tokens | ceil((2,000 + 2 × 32) / 2) + 16 = 1,048 | |
| Reserve input | ceil(1,048 × 1.1) | 1,153 |
| Reserve output | 1,024 × 5.5 | 5,632 |
| Reservation | 6,785 | |
| Actual input (provider: 480 tokens) | 480 × 1.1 | 528 |
| Actual output (provider: 310 tokens) | 310 × 5.5 | 1,705 |
| Debited | 2,233 | |
| Released | 6,785 − 2,233 | 4,552 |
During execution the project's available balance was 6,785 µUSD lower. Afterwards it is exactly 2,233 µUSD ($0.002233) lower.
Estimated usage
Some upstream responses do not include token counts. In that case the gateway estimates usage and sets billing.usage_estimated to true:
- input tokens: half of the conservative reservation estimate,
- output tokens: one token per four UTF-8 bytes of generated text and tool-call arguments.
Streaming and partial output
- A completed stream is billed like a non-streaming request.
- If a stream fails or the client disconnects after output was delivered, the delivered portion is metered (estimated when no usage was reported) and receipted with status
failed. - If it fails before any output, the whole reservation is released and no receipt is issued.
- A non-streaming request that fails upstream is never charged.
Sandbox usage
Sandbox executions reserve the cost of their full timeout and are charged per started second of wall-clock execution. See Sandboxes for rates. If the sandbox node cannot run the code at all, the reservation is released and no receipt is issued.
Billing fields
Inference responses include a billing object with request_id, cost_micro_usd, cost_usd, usage_estimated and fingerprint_salt. Sandbox responses include cost_micro_usd, cost_usd and fingerprint_salt. The same cost appears as customer_cost in the signed receipt. Every request is also recorded with its status, token counts, cost and receipt ID and is visible in the console.
Rate limits
Two fixed one-minute windows apply to every inference request and sandbox execution. Both must have room.
| Limit | Default | Configured in |
|---|---|---|
| Per API key | 60 / min | The key's requests-per-minute setting (1–10,000). |
| Per project | 120 / min | The project policy. Applies across all keys, console usage and agent runs. |
Windows align to the clock minute. Every request that reaches the check counts, including requests later rejected for budget or balance. GET /v1/models and receipt lookups are not rate limited. When a limit is hit, the response carries a retry-after header and retry_after_seconds in the body:
HTTP/1.1 429 Too Many Requests
retry-after: 23
content-type: application/json; charset=utf-8
{
"error": {
"type": "rate_limit_exceeded",
"message": "This API key has exceeded its request rate limit.",
"request_id": "req_01K58ZV2Q8R4N6C1XT3M5B7H9E",
"retry_after_seconds": 23
}
}Ledger
Each project balance has two parts, available and reserved. Every change is an append-only ledger entry with an idempotency key, so a retried settlement or a re-processed payment cannot apply twice.
| Entry | Effect | Used for |
|---|---|---|
| credit | available += a | Confirmed USDG credit purchases. |
| reserve | available −= a, reserved += a | Holding the estimated maximum before execution. |
| debit | reserved −= a | Charging the actual cost from a reservation. |
| release | available += a, reserved −= a | Returning unused reservation. |
| adjustment | available += a | Development credit grants and operator corrections. |
Reconciliation
The ledger can always reproduce the stored balance: available equals credits plus adjustments minus reserves plus releases, and reserved equals reserves minus releases minus debits.