Repository navigation
Buying at Volume
An agent that buys hundreds or thousands of calls in a burst, over x402 or MPP, needs four things: a price it can check before it pays, a retry that never pays twice, a ceiling on spend, and limits it can plan around. This page names each mechanism and the file that enforces it. The live figures, rendered from that code, are on the guide: agent402.tools/guides/buying-at-volume.
-
/api/pricinglists every route, its list price, the chains it takes (networks) and, on a route that runs as a job, itsasyncblock. Chains with a settlement premium or a price floor are listed underpayment.premiumUsdByNetworkandpayment.minPriceUsdByNetwork. - The 402 is the quote for the request in hand. On the metered model routes it is computed from the body, and the paid retry is priced again from its own body (
acceptsForIteminsrc/payments.js), so the paid retry carries the body that was quoted. - Price changes are on the changelog. Read
/api/pricingat the start of each burst.
There is no per-wallet rate limit on paid calls. Every limit below answers before any payment is taken; the default column says how long to wait.
| What is counted | Default | Source |
|---|---|---|
| Unpaid price checks to priced catalog routes, per client address | 3,000 an hour; 30,000 an hour for the rest of the clock hour once that address settles a payment, and for 10 minutes after each paid call |
src/unpaid-quote-budget.js (PAID_CLIENT_QUOTE_MULTIPLIER) |
Unpaid quotes on /v1/metered, per client address |
60 a minute, 1,200 an hour (429, Retry-After: 60, with a guide link); past that, 2 more for each paid /v1/metered call from that address (METERED_QUOTE_CREDITS_PER_CALL), used within 10 minutes, up to 600 a minute and 12,000 an hour. Retry-After: 60 is the minute window; past the hourly figure the wait runs until the oldest quote in the last hour ages out |
METERED_UNPAID_QUOTES_PER_MIN / _PER_HOUR and PAID_CLIENT_METERED_QUOTES_PER_MIN / _PER_HOUR in src/unpaid-quote-budget.js, enforced in src/server.js
|
Refused payment credentials on /v1/metered
|
the same figures, counted once a credential is refused | src/server.js |
| Payments that verified and then failed to settle for a reason about the payment itself (its balance, its signature, or an authorization already used or expired), per wallet and per network (a signed EVM payer is counted on the network each payment named; a Tempo sender, a credits key or an address is one key) | refused on that network at 3 in 15 minutes (9 for failures whose cause the settlement did not name, refused in words that blame no one) while failures are more than half of the wallet's outcomes there, or 40 whatever it settled. The 429 names the network and when it lifts (refusedNetwork, retryAfterSeconds, retry: "other-network"), and the same wallet can pay on another network the route offers at once |
src/gateway-settle-breaker.js |
| Report and media runs that failed to settle or failed after the run, per buyer (signed payer, verified Tempo sender, credits key, else address) | blocked for 30 minutes (429, no Retry-After) at 3 in 15 minutes while failures are more than half of the buyer's outcomes, or at 10 whatever it settled |
COMPOSITE_GUARD_* in src/composite-spend-guard.js
|
| Unpaid requests with a body over 100 KB to a route that reads its price from the body, per client address | 60 a minute, 1,200 an hour (429, Retry-After: 60); no raise once the address has paid |
src/large-body-gate.js, limiter in src/server.js
|
| Paid calls in flight, per wallet, on every paid route that is not free through proof-of-work | the wallet's balance of the paying token on the paying chain must cover every call it has in flight plus the new one. On routes other than the report and media routes the balance is read inside about a second, and a wallet whose balance covers its calls can send any number at once: all are started at once, there is no other limit on calls at once, and no call waits for another call's payment to settle. A call the balance does not cover answers 429 with Retry-After: 30; a call that arrives while another call from the wallet is still settling, and whose cover cannot be confirmed yet, answers 429 with Retry-After: 5. When the balance cannot be read right now on those routes, the call is started if the last balance this server read for that wallet within the past 15 minutes, less what the wallet's payments have taken and its calls in progress hold since, covers it. Otherwise, and for a wallet this server has not read in the past 15 minutes, the wallet runs up to 4 calls at once (16 for a wallet with a payment on record) while its balance cannot be read, and a call past that answers 429 with Retry-After: 5. The report and media routes are the exception: the balance read is given up to five seconds, a call the balance does not cover answers 429 with Retry-After: 30, and while the balance cannot be read a wallet runs up to 4 calls at once there, whatever its record. Each of these 429s comes before anything runs; x402, the MPP evm method and a Tempo pull credential are not charged for it. Applies to x402 on EVM, Solana, Algorand and Stellar, the MPP evm method, a Tempo pull credential and a Circle Gateway batched payment |
src/inflight-cover.js (INFLIGHT_COVER_UNREAD_MAX, INFLIGHT_COVER_UNREAD_PAID_MAX) |
| Jobs per client address | 4 at once (429, Retry-After: 30) |
ASYNC_JOBS_PER_CLIENT in src/async-jobs.js
|
On the two failed-settlement rows a buyer's failures count against that buyer alone. On the first, a settlement that could not complete on this server's side or the facilitator's (a timeout, a connection error, an HTTP error, a billing limit on this server's own account) is never counted against the wallet; a run of those is an operator alarm. A burst of them across many buyers is an operator alarm (settleFailures for /v1, unsettledReports for report and media runs, each ok or burst on /api/gateway-status) and is not a refusal.
An IPv6 /64 is one address. A stock x402 client sends one unpaid read and one paid retry per call, and only the unpaid read is counted. Once an address has paid, its unpaid price checks read against 10 times the figure for 10 minutes after each paid call (a final 200 that settled on any rail, or a credits debit; PAID_QUOTE_TRUST_MINUTES in src/paid-quote-trust.js, PAID_CLIENT_QUOTE_MULTIPLIER in src/unpaid-quote-budget.js). A /v1/metered quote past its plain figure needs a credit that a paid /v1/metered call earned, so a steady buyer is paced by its own paid calls and one cheap paid call raises the limit by only a few quotes. A payment credential that is refused still counts.
-
Idempotency-Key: the same key with the same credential, route, query and body returns the first 200 (X-Idempotent-Replay: true) with no second run and no second settlement; a copy that arrives while the first runs gets 409idempotent_request_in_flightwithRetry-After: 2(src/idempotency.js, store insrc/idempotency-store.js). -
Implicit replay on EVM payments: the signed payment (network, payer, nonce) is the key, so a re-sent payment returns the first answer marked
X-Replayed-Answer: 1, except on identity-bound routes, routes with a lasting effect and streamed calls. -
Solana: no implicit key; send
Idempotency-Keywith the exact payment header that went out the first time. - On x402 a response of 400 or above is not settled, so a retry after one costs nothing extra. Read
PAYMENT-RESPONSEon each answer to see whether it settled.
A route with an async block takes Prefer: respond-async: 202 and a Location job link at once, GET /api/jobs/{id} (free) until status is completed or failed, payment settled only on the delivered result (src/async-jobs.js, src/slow-routes.js). agent402-client and agent402-mcp switch to jobs on their own.
| Package | Per call | Across calls | Source |
|---|---|---|---|
| agent402-client | maxPerCallUsd |
dailyLimitUsd, maxPerHostUsd (rolling 24 hours, per instance) |
client/index.js |
| agent402-mcp |
AGENT402_MAX_PER_CALL (on by default, off removes it) |
AGENT402_BUDGET (whole session, opt-in) |
mcp/index.js |
| agent402-openclaw |
maxPerCallUsd or AGENT402_MAX_PER_CALL_USD (defaults to the metered per-call cap) |
none | openclaw/index.js |
Every cap is checked before a payment is signed. All three packages refuse an accept asking for a signing validity longer than a day (MAX_VALIDITY_SECONDS in each known-assets.js). AGENT402_NETWORKS (agent402-mcp) restricts and orders the chains a wallet pays on.
| Rail | Settles | When the call fails |
|---|---|---|
| x402 exact, EVM chain | after the tool answers, only under 400 | not charged |
| x402 exact, Solana | after the tool answers, only under 400 | not charged |
| x402 exact, Stellar | after the tool answers, only under 400 | not charged |
| x402 exact, Algorand | after the tool answers, only under 400 | not charged |
| x402 exact, Gateway batched (where offered; paid from a Circle Gateway deposit) | settled off chain by Circle Gateway after the tool answers, only under 400 | not charged |
MPP evm charge |
the same x402 settlement | not charged |
| MPP Tempo pull | broadcast after the tool answers, only under 400 | not charged |
| MPP Tempo push | final before the call runs | booked as a refund owed, repaid after on-chain proof |
On the EVM chains and Tempo pull, a settlement whose outcome is not known when the call is answered is read on chain again; one that lands after a failed answer is booked as a refund owed and repaid after on-chain proof.
The long routes (report products, video, the slow media tiers) take x402 exact on EVM chains only, and Tempo is not offered on identity-bound or long-running routes. A Solana payment embeds a recent blockhash that lives about a minute, so sign each one right before it is sent. A Solana payment refused for a missing or underfunded USDC account answers retry: "fund-wallet" with Retry-After (src/svm-funding-refusal.js).
- Model ids:
GET /v1/models. An unlisted id is refused before payment withsuggestionsand ahowToCallretried with the first. - Input size: each model's cap is
x402.meteredMaxInputCharson/v1/models(maxInputCharsForinsrc/tools/llm-gateway-kit.js); over it,input_too_largebefore payment, withsuggestionsof models whose window takes it. - Every wire: both refusals are answered before payment on
/v1/metered/chat/completions,/v1/metered/messages,/v1/metered/responsesand/v1/metered/geminialike (src/gateway-prepayment.js), each in the error object its SDK reads, with the same fields beside it. - Per-call cap: a body quoting above
METERED_MAX_QUOTE_USDis refused with a 400 before any upstream call. - Set a client timeout of at least 120 s: the answer is generated and the payment settled before the response is sent, which takes a few seconds on most calls and longer for long answers, and a client that disconnects after the payment settles is charged without the answer (the charge is recorded as owed and reviewed for a refund).
- 400, 422: input refused; the body carries
howToCall(method, URL, ready body). Not charged on x402. - 402: the first-contact body carries the offer,
howToCalland, on a job route,async. - 409: the same keyed call is still running; resend after
Retry-After. - 429, 503: a limit or a busy route; wait
Retry-After. image-ocr answers 503large-image-busywhile it reads another large image. - 422 with
attribution: "caller"or"upstream-access": a URL you supplied answered with a 4xx, or refused this server's access. - 502, 503 with
attribution: "upstream": a source the tool reads answered with a failure (its own status rides inupstreamStatus), not the input; retry later or pick another source. - 502, 503, 504 with
attribution: "ours": our side: our time limit passed (hint: "our-deadline"or"budget-spent"), our DNS lookup failed ("our-egress"), the source refused our own key ("our-key"), our own allowance or pacing ("our-allowance","our-pacing"), or a defect in our own code ("internal");hint: "smaller-input"means an input this long outlasts the limit. Retry the same call, or send a shorter input when the hint says so. - 502, 503 with
attribution: "unknown"andhint: "connect-failed": the connection to a source failed before any answer (refused, reset or unreachable), and nothing shows which side failed; retry the same call later. - 504 with
hint: "source-timeout"or"source-unreachable"(attribution: "unknown"): a URL you supplied did not answer within our limit, or could not be connected to; check the URL, or retry.
See also: Paying with x402, Paying with MPP, LLM Gateway (OpenAI /v1), Agentic Finance.
agent402.tools - the applied layer of Agentic Finance: 500+ pay-per-call tools for AI agents over x402 and MPP (Paying with x402 · Paying with MPP · Glossary) · synced from wiki/ in the main repo - edit there, not here.
For agents and buyers
- Getting Started
- Agentic Finance
- Why Pay Here
- Reports and Monitors
- Paying with x402
- Paying with MPP
- Robinhood Chain (USDG)
- Arc (USDC)
- Ink (USDC)
- Circle Gateway (batched USDC)
- Paying with Compute
- Buying at Volume
- Content Pipeline
- MCP Connector
- Adapters
- AWS Bedrock AgentCore
- Decide - describe a job, get a plan
- Tool Catalog
- Skill Packs
- x402 Index and Router
- x402 Leaderboard
- LLM Gateway (OpenAI /v1)
- LLM Proxy Gateway
- Image Generation Gateway
- Code Execution Sandbox
- Text-to-Speech
- Speech-to-Text
- Text Embeddings
- Payments and x402
- Memory and Coordination
Tollbooth (for site owners)
- Pay-per-crawl - what it is, install, modes
- Pay-per-crawl Walkthrough - 5-min hands-on
- Tollbooth for Agencies - many-site playbook
Website & Developer
- Reports · Monitors - by card
- Quickstart - first call in 60 seconds
- Playground - try tools in your browser
- SDK REPL - live code editor
- API Explorer - browse OpenAPI
- Adapter Docs - per-framework guides
- Workflows - chaining patterns
- Blog · Changelog
Under the hood