A request is paid for in six steps:
Everything below is a consequence of one fact: an LLM’s cost is not known until after generation, and the settlement scheme needs a price up front.

The quote is deliberately high

Before the model runs, the router prices the part that is predictable — your prompt and your max_tokens — and prices it as the worst case. Input tokens are estimated at about 3 characters per token rather than the usual 4, and about 90 tokens are added for system instructions the router injects that you never see but the upstream bills for. Output is priced at the full max_tokens you asked for, whether or not the model uses it. Over-quoting is refunded. Under-quoting has to be collected from a later request. Erring high is the cheaper direction to be wrong in, so that is the direction it errs.
This is why max_tokens matters more here than on a metered-monthly API. The quote is priced at that number, and it is held against your balance until the request settles. Ask for 64,000 tokens on a one-line answer and you have locked up 64,000 tokens’ worth of balance for the duration.

The hold, and the signature

The quote is held against your Circle Gateway balance, and the router signs an EIP-3009 transfer authorization on your behalf using your own embedded wallet. You submit nothing and you hold no native gas — on Arc, USDC is the gas token, and the router pays it. Authorizations are settled in batches rather than one transaction per request, which is what makes a fraction-of-a-cent request economic at all.

The meter, and the refund

When the last token lands, the router meters what the request actually used: real input tokens, real output tokens, and whatever the web search provider billed. Quote minus charge is refunded to credit. Not to your wallet — to a credit balance that is netted into your next quote. So the first request on an account is charged the worst case and refunded; from the second onward you are charged approximately your true cost. Credit is withdrawable.

When a turn costs more than its quote

Tool spend is the case the quote cannot cover. The router can search the web on the model’s behalf, and nothing knows whether it will until it does. A turn that lands above its quote books the difference as credit debt. It is collected on that payer’s next request, and until it is collected, it is held back from what you can withdraw. Nothing is written off.
The gap can be large. A production request quoted 0.0024andsettledat0.0024** and settled at **0.0614 — a 25× overrun, two thirds of it input tokens, because every tool round re-sends the whole conversation so far. If you are running on a tight balance, disable search with "web_search": false.

Reading the bill

Every response carries x-nanorouter-request-id. A non-streaming response also carries x-nanorouter-charged-usdc — a streamed one cannot, because the figure is not known until long after the headers went out. Read it back by id instead:
chargedUsd, refundedUsd, llmUsd and searchUsd are null until the request settles — an in-flight row has not been metered yet, and reporting zero there would claim a request was free when it has not finished. llmUsd and searchUsd always sum to chargedUsd exactly. They are split server-side so a row and the total above it can never round differently.
This endpoint authenticates with a dashboard session, not an API key — an nr_ key there is a 401.stream: false returns x-nanorouter-charged-usdc on a fast request, but it is dropped once a response takes longer than 45 seconds (the keepalive commits the headers first). There is currently no dependable key-authenticated way to read a settled cost.

Why a request can be refused

429 is the exposure guard: a payer may have at most $1.00 of quoted, unsettled requests in flight at once. It clears as requests settle, so a retry after a moment usually succeeds. It is a solvency guard, not a rate limit — concurrency is bounded by money at risk, not by requests per second.

All error codes

Full list, with which are worth retrying.

A failed request is not billed

If a request fails before the model produces anything, the whole quote is refunded — zero usage means zero charge. You still pay in latency, but not in USDC. A request you cancel mid-stream is different: the tokens generated before you disconnected were really generated, and you are billed for them. The partial answer is kept.