Billing
Prices, holds, charge caps, insufficient balance, and top-ups
One wallet, exact amounts
Each account has one prepaid USD wallet. available_usd can be spent; reserved_usd is held for runs in flight. All amounts in the API are decimal strings ("0.00035"), stored and settled exactly — never floating point.
Every hold, charge, release, refund and top-up is an entry in the wallet ledger and points at its run, top-up or dispute.
A usage reset returns the remaining charges from each account’s latest 100 calls at the campaign cutoff. Free, failed and previously refunded calls count toward the 100. Usage and Wallet show the original charge and its net amount on the same row. The transactions API returns the underlying ledger entries by default. Pass group_refunds=true to see refunds on the original charges.
How a price is set
describe shows the current terms in pricing:
- Base price. Either the cost the provider reports for the call (
basis: upstream_usd, for example AnyAPI’scostUsdor Exa’scostDollars.total), or the provider units the call used times a per-unit rate (basis: units, for example Search1API, Context.dev and Hunter credits). price_multiplier. One number applied to the base:"1"list price,"0.5"half price,"1.2"a 20% markup,"0"free. AgentRouter sets it per tool; clients never send it.pricing_version. An immutable snapshot of those terms. Invoke must send it, and a run keeps its snapshot even if prices change while it runs or when it is recovered later.
The receipt shows base_charge_usd (before the multiplier), price_multiplier and customer_charge_usd, plus the usage the charge is based on.
What is charged
A result that is valid but not useful for your task is charged; if a correct input returned wrong or unusable data, open a dispute. Your client timing out never cancels, refunds or re-runs a call.
Holds and max_cost_usd
Before running, AgentRouter moves the amount needed for the call from available to reserved balance. This hold is not a final charge; it prevents concurrent calls from spending the same funds. After the run settles, the actual charge is taken from the hold and the unused amount becomes available again.
How much is held?
The connector supplies a fixed or input-dependent usage bound. AgentRouter converts that bound to USD, applies the run’s locked price_multiplier, and rounds up to the ledger’s 12-decimal precision:
Hold = estimated provider cost bound × price multiplier. For a unit-billed tool, the provider cost bound is estimated units × the unit rate. describe shows max_per_call_usd or the estimation rule.
The provider supplies its prices; AgentRouter’s connector defines the bound used for reservation, including more expensive fallback routes where applicable. Some connectors use a fixed bound even for a small request, so the hold can be larger than the eventual charge.
max_cost_usd is your spending limit for the call, not the amount automatically held. Its default is "0.50". If the required hold is higher than the effective limit, the call is blocked with MAX_COST_EXCEEDED; AgentRouter does not take a smaller hold and run anyway. Budgets can lower that limit and also limit spend per day, week, month or in total.
Can the final charge exceed the hold?
No. Your final charge cannot exceed the hold accepted for that run, which is also bounded by its effective max_cost_usd. If actual provider usage would produce a larger charge, AgentRouter absorbs the excess and the receipt reports billing.reason: charged_capped. You are not charged an additional amount later for that excess.
For example, with a price multiplier of 1, a run that holds 0.02 charges you at most 0.0046, even if you allowed up to $0.50 when invoking it. These amounts illustrate the rule, not a fixed price for every tool.
Is releasing a hold a refund?
Releasing unused funds makes reserved balance available again; a refund returns money that was actually charged. For example, a 0.0006 charge releases 0.0006. The hold and the charge are not two separate debits.
What if my available balance cannot cover the hold?
The call is stopped before the provider is invoked. The API returns HTTP 402 with a Run whose status is BLOCKED, error.code is INSUFFICIENT_BALANCE, and billing.reason is blocked_before_execution. No funds are reserved or charged for that blocked call. A TOP_UP hint points to the payment-link flow.
The check uses available_usd: money already held by other runs is unavailable. For example, 0.0154 hold, even if similar calls previously settled for only $0.0006. Concurrent requests cannot reserve more than the available balance.
Add funds, or wait for other runs to release enough unused balance, then invoke again. The blocked run is terminal: it does not queue or automatically resume when funds arrive. If you used an Idempotency-Key, use a new key for this new attempt; reusing the original key returns the same blocked run. Creating a top-up link alone does not add funds, and AgentRouter never tops up automatically.
Free promotions
A tool with price_multiplier: "0" is free for the promotion’s period. Free still has limits: a daily number of free calls per account and a total promotion budget. When either runs out the call is blocked (FREE_CALL_QUOTA, PROMOTION_EXHAUSTED) — it never becomes a paid call by itself. When a promotion ends, invoking with the old pricing_version returns PRICING_CHANGED; describe again and decide with the new price.
Free tools work with an empty wallet.
Top-ups
- Add funds in Settings → Wallet, with
agentrouter topup --amount-usd 10, orPOST /v1/wallet/topups. - A 5% service fee is added: 10.50 total.
POST /v1/wallet/topups/quotereturns the exact fee for any amount. Multipliers and promotions never apply to top-ups. - Creating a top-up returns a payment link. Funds arrive only after payment completes; creating the link does not add money. An agent should give the link to the user and never pay it itself.
- AgentRouter never tops up automatically.
Spending authority
Connecting a host (OAuth) or creating an API key lets that caller spend from your wallet within its permissions and your budgets. Each run records which key or host made it. Revoke a key or host at any time in Settings → API.