Billing
The gateway is prepaid: you top up credits, every request settles against them per token, and every number is auditable per request. This page is the exact billing policy — the same rules the billing engine enforces.
What a request costs
Each model prices three per-token dimensions — input, cached_input and output — published as USD per million tokens on the models page and in GET /v1/models. The cost of a request is:
billable_input = prompt_tokens - cached_tokens
cost = billable_input x input_price
+ cached_tokens x cached_input_price (falls back to input_price)
+ completion_tokens x output_price
+ request_fee (0 on all current models)- Prompt cache is automatic: input tokens the upstream recognizes from a recent identical prefix come back as
prompt_tokens_details.cached_tokensand are billed at the cheapercached_inputprice. - A model without a published
cached_inputprice (currentlyglm-4.7-flash) bills the whole prompt at theinputprice —cached_tokensis still reported for transparency, it just carries no discount, because we get none upstream either. - Reasoning is never billed separately.
reasoning_tokensis a subset ofcompletion_tokens, which is already billed in full at the output price — the count is shown so you can explain long answers, not charged twice.
The usage block of every response carries all the inputs to that formula:
"usage": {
"prompt_tokens": 12907,
"completion_tokens": 300,
"total_tokens": 13207,
"prompt_tokens_details": {"cached_tokens": 12864},
"completion_tokens_details": {"reasoning_tokens": 0}
}Costs are computed in integer nano-USD (10⁻⁹ USD) — no floats, no per-request rounding. A full exact-cache hit (identical request, response served from our cache) is billed at 10% of the normal price of that response and shows x-gw-cache: hit.
Holds and the 402
Before calling the model, the gateway places a temporary hold on your available balance: the estimated prompt cost plus output priced up to min(max_tokens, 4096) tokens. The hold is released the moment the request settles for its real cost — holds exist for seconds, and are capped so a large context window never freezes dollars per request. If your available balance cannot cover the hold:
HTTP/1.1 402 Payment Required
{
"error": {
"message": "Insufficient credits. Available: $0.0041. This request requires an estimated hold of $0.0269. Top up at https://app.clfaigateway.dev/billing/topup",
"type": "insufficient_credits",
"code": "insufficient_credits",
"param": null,
"metadata": {
"available_nano": 4100000,
"required_estimate_nano": 26927600,
"topup_url": "https://app.clfaigateway.dev/billing/topup"
}
}
}The available amount and the estimate are in the message for humans and in metadata for machines. SDKs do not auto-retry a 402 — top up, then retry.
Zero-completion insurance
The exact rule
If a request ends with completion_tokens = 0 AND finish_reason is null or "error", it costs $0 — including the prompt tokens the upstream already billed us for. We absorb that cost.
In plain terms: a model failure that produced nothing costs you nothing, prompt included.
The insurance does NOT apply when finish_reason is "stop" or "length" with zero completion tokens — for example a request sent with max_tokens: 0. The model completed normally and chose or was told to stop, so the prompt is billed as usual. Without this carve-out, max_tokens: 0 would be a way to have prompts processed for free.
Disconnects and broken streams
| Case | What you pay |
|---|---|
| You disconnect mid-stream | The tokens already delivered, counted exactly from per-chunk usage — generation does not stop retroactively. The request settles as success. |
| The upstream fails mid-stream | Only the tokens delivered before the failure; you receive finish_reason: "error" and the request settles as partial. |
| Failure before any output | $0 under zero-completion insurance (conditions above). |
Cap your worst case with max_tokens
Disconnecting does not cancel what was already generated, so max_tokens is your spending cap per request. If you omit it, the gateway applies a default of 4096 output tokens.
Where you see every cost
Non-streaming responses (and cache hits) carry the settled cost in the x-gw-cost-nano header:
x-request-id: req_01j9zx6d2fk8v3q7w1m4e5t8ha x-gw-model: kimi-k2.6 x-gw-cache: miss x-gw-cost-nano: 1979454 x-ratelimit-limit: 60 x-ratelimit-remaining: 57 x-ratelimit-reset: 1774694460
Streams cannot carry it — headers are sent before the cost exists. For any request, GET /v1/generation is the authoritative per-request record (tokens, cost, cache layer, latency, status), available a few seconds after settlement:
curl "https://api.clfaigateway.dev/v1/generation?id=req_01j9zx6d2fk8v3q7w1m4e5t8ha" \ -H "Authorization: Bearer sk-gw-..."
Aggregates are in GET /v1/usage and on the dashboard. The three surfaces show the same settled numbers.
Display lag is not billing lag
Dashboard and aggregate numbers usually appear within seconds of settlement, but can lag a few minutes under heavy load. The charge itself is settled exactly once per request in the ledger — what you eventually see is always the settled amount, never an estimate.
Top-ups and credits
- Top up from the dashboard: Vietnamese bank transfer via VietQR (confirmed automatically, typically within seconds) or international card. Credits are denominated in USD.
- Promotional credits with an expiry are spent before purchased credits, so nothing expires while paid balance is consumed first.
- Your balance, active grants and their expiry dates are visible in
GET /v1/creditsand on the dashboard.