Prepaid credits vs postpaid invoicing
Prepaid credits make your balance a hard ceiling: at zero the API returns 429 with code insufficient_credits and the refused request is not charged, so a runaway agent loop cannot generate a bill you did not fund. OpenRouter's prepaid credits carry a published 5.5% purchase fee with a $0.80 minimum (5% via crypto), DeepInfra bills postpaid with tiered invoicing starting at a $20 threshold, and we charge no fee on top-ups, which run on a fixed ladder of $30 / $50 / $100 / $200 / $500.
Three billing models, and what each one exposes you to
Every provider in this market picks one of three arrangements, and the choice determines what happens on your worst day rather than your average one.
Prepaid with a fee is the most common gateway model: you buy credits, a percentage is taken at purchase, and spend draws down the balance. Postpaid is the classic cloud arrangement: you consume, and an invoice arrives. Prepaid with no fee is what we run -- a dollar loaded is a dollar of inference, and the business makes its margin on the per-token rate rather than on the transaction.
Only one of the three gives you a hard spending ceiling that does not depend on you configuring anything.
| Arrangement | Who runs it | Published terms | Ceiling on a runaway loop |
|---|---|---|---|
| Prepaid credits with a purchase fee | OpenRouter | 5.5% on credit top-up with a $0.80 minimum via Stripe; 5% via crypto | Yes -- the balance |
| Prepaid credits with no fee | AI Token Router | No fee on top-ups; fixed ladder from $30 to $500 | Yes -- the balance |
| Postpaid, invoiced in arrears | DeepInfra, Fireworks AI | Tiered invoicing thresholds beginning at $20 (DeepInfra); $1 in free credits for new accounts (Fireworks) | No -- whatever ran, you owe |
What the fee costs, at each rung of the ladder
A percentage on credit purchase is a real, published platform tax, and it applies to every dollar loaded -- including dollars spent on open-weight models the platform is passing through at cost. It is worth computing rather than dismissing as small.
The minimum matters more than the percentage for small accounts. At OpenRouter's published $0.80 floor, a $10 top-up carries an 8% effective rate rather than 5.5%, because the floor binds before the percentage does.
| Top-up | Fee at 5.5% with a $0.80 minimum | Effective rate | Our fee |
|---|---|---|---|
| $30 | $1.65 | 5.5% | $0.00 |
| $50 | $2.75 | 5.5% | $0.00 |
| $100 | $5.50 | 5.5% | $0.00 |
| $200 | $11.00 | 5.5% | $0.00 |
| $500 | $27.50 | 5.5% | $0.00 |
What a hard ceiling actually buys you
The scenario prepaid credit protects against is specific: an agent in a loop. A misconfigured retry, a tool that returns an error the planner reads as a reason to try again, a recursion that never terminates. On a per-token API this can consume a lot of money in a short time, and on a postpaid arrangement the first anyone knows about it is the invoice.
On a prepaid balance the loop stops when the balance does. The API returns 429 with code insufficient_credits, and the refused request is not charged -- the balance is a ceiling, not an overdraft. That is stated in the error message rather than left for the customer to work out from a statement.
The status code is 429 rather than 402 on purpose, and it is worth understanding before you write the handler. 402 is what a billing-aware API should return, and it is the wrong answer for a drop-in replacement, because the platform being replaced returns 429 for an exhausted balance -- so a client that special-cases 402 would stop noticing. The cost of honouring that is that 429 no longer identifies its own cause, so every 429 carries a code. Branch on the code, never on the status alone.
# HTTP 429
# {
# "error": {
# "message": "Your credit balance is exhausted. Add credit from the dashboard
# to keep making requests. Your balance is a hard ceiling, so
# nothing was charged for this request.",
# "type": "insufficient_quota",
# "param": null,
# "code": "insufficient_credits"
# }
# }
Whole dollars only, and why the ladder is fixed
Top-ups are a fixed ladder of whole dollars -- $30, $50, $100, $200, $500 -- rather than an amount you type. That is a product decision and also the technically correct one: card amounts are integer minor units, so a fixed ladder of whole dollars never encounters a rounding question, and there is exactly one place in the codebase where a denomination is written down. A second copy is how a pricing page ends up advertising an amount that checkout will not honour.
There is no metered settlement and no invoicing in arrears anywhere in the system, and the payments integration is collection-only -- no payouts, no transfers, no disbursement surface at all. That is a smaller attack surface than a platform that has to be able to send money as well as receive it.
Auto-recharge, and the guards that make it safe
A hard ceiling is only useful if it does not stop legitimate work at 3am, so there is an automatic top-up: when the balance falls below $10, charge $50 to a saved card. The charge itself is three lines of code. Everything else is the difference between a convenience and an unbounded standing instruction against a card, so the guards are the feature.
The defaults are calibrated above what the category ships. OpenRouter defaults to a $25 reload at a $2 threshold, and Replicate to $15 at a $5 threshold; a $10 trigger with a $50 reload sits deliberately above both, because the failure this exists to prevent is an agent loop stopping mid-run rather than a balance sitting slightly too high.
| Guard | Value | What it prevents |
|---|---|---|
| Trigger threshold | Balance below $10 | A run stopping mid-flight |
| Recharge amount | $50 | Repeated small charges |
| Daily cap | 3 charges per rolling UTC day | An agent loop draining a card without an upper bound |
| Cooldown | 5 minutes between charges | A burst of triggers stacking charges within seconds |
| Attempt lock | One unique row per user-minute | Two concurrent triggers both charging; survives a process dying mid-charge |
| Failure circuit | Disabled after 3 consecutive declines | Issuer fraud flags, and past a threshold merchant-account risk |
| Authentication latch | Disabled until the customer re-authenticates | Retrying a strong-authentication decline, which retrying cannot ever clear |
The charge and the credit are two different things
Auto-recharge moves money and nothing else. It does not add credit. The payment webhook credits the account, exactly as it does for a manual top-up, so there is one crediting path and one place where idempotency has to be correct rather than two that have to agree.
The ledger behind it is append-only. There is no function to set a balance, no function to update one, and no way to edit or delete a row -- a correction is a new compensating entry, so the history always explains the current number. That is the property you want the first time a customer asks why their balance is what it is.
The two integer grids underneath a balance
Money is never a float below the interface. Our ledger stores integer micros, where one micro is $0.000001. The gateway that meters inference stores its own integer quota unit, where 500,000 quota is one dollar -- so one quota unit is $0.000002.
The coarser grid is the one that decides what actually moves, which makes $0.000002 the smallest amount this system can charge or refund. At DeepSeek V4 Flash's $0.09 per million input tokens, that is about 23 tokens. It is also why a balance is never rendered as $0.00 unless it is genuinely zero: at these unit prices, a real remaining balance can be smaller than two decimal places can express, and telling somebody they have nothing left when they have almost nothing left leads to a different action.
What prepaid costs you, honestly
There is no net-30, no purchase order, no consolidated monthly invoice and no credit line. If your finance function requires an invoice before payment, prepaid credits are a procurement conversation you will lose, and a postpaid provider is genuinely the better fit -- DeepInfra's tiered invoicing exists precisely for buyers who need that.
There is also a real operational cost to a ceiling. It stops runaway spend, and it stops legitimate spend the same way. If a burst of production traffic exhausts the balance at a bad moment, the API returns 429 until somebody tops up, which is why auto-recharge exists and why its daily cap is a cap rather than an absence.
The trade is straightforward. You give up the ability to spend money you have not yet allocated, and you get the guarantee that no amount of code failure produces a bill you did not fund. For a solo developer or a small team running agents, that trade is usually the right one. For an enterprise with a procurement process, it usually is not.
Watching spend without waiting for a statement
Every response carries usage.cost_usd -- the actual charge for that request, not an estimate against a rate card. That is the fastest way to catch a cost regression: log it per request and alert on the shape of the distribution rather than on a monthly total.
The full rate card is public, key-free and CORS-open, so a budget check against current prices does not require a credential or a scrape.
curl https://router.xark.io/api/v1/pricing | jq '.data[] | {id, input: .pricing.input, output: .pricing.output}'
AI Token Router is an OpenAI-compatible gateway for open-weight models. Every rate on the pricing page is printed next to the model’s official rate, so the numbers in this post are checkable rather than claimed.
Get an API keyRelated
- What it costs to run an evaluation suite
One pass over a 1,000-item benchmark is $1.68 on GLM-5.2. The suite you actually run is forty-five passes, and the judge nearly doubles it.
- Embeddings: dimensions and corpus cost
Matryoshka truncation is a free quarter of your storage bill; changing model is not. Worked corpus costs, and the storage table nobody prints.
- Rate limits, concurrency and backoff
Five independent per-endpoint buckets, a fixed window that allows 120 requests in two seconds, and the field that says whether retrying will help.