Run this notebook in Google Colab
Every step below as an executable notebook. It runs without a funded wallet and stops at the payment wall, so you can see the whole flow before spending anything.
How It Works
Four moving parts, three of which are just HTTP:
Inference itself is the ordinary
/chat/completions call. The only difference is which header you send.
What It Costs to Start
Two numbers matter and they are not the same number. The minimum top-up is five dollars. That is the smallest amount/x402/top-up will settle, and it is returned in the discovery response rather than hardcoded anywhere, so read it rather than trusting this page.
The minimum balance to make a call is ten cents. A wallet holding less than that gets a 402 back from inference even though it holds money.
So five dollars is the smallest wallet worth funding, and five dollars is what this guide gives the agent. Worth knowing what that buys: a short question to qwen3-5-9b costs about twenty seven input tokens and twenty six output tokens, which at that model’s prices is roughly seven millionths of a dollar. Five dollars is on the order of three quarters of a million questions. The budget here is not a tight constraint, it is a blast radius.
Setting Up
The x402 SDK does the payment signing. Do not hand-roll it: the transfer authorization is EIP-712 typed data and a reused nonce fails verification in ways that are tedious to debug.The x402 Python SDK requires Python 3.10 or newer. Colab is fine. A system Python that shipped with macOS may not be.
agent.py with the configuration. BUDGET_USD is the ceiling the agent enforces on itself, set here to the whole wallet. Lower it and the agent stops before the money does, which is the only knob you are likely to change.
A Wallet the Agent Owns
The agent needs a keypair. In production this is a wallet you funded deliberately and whose key lives in a secret manager. While you are building, generating a throwaway is the right move, because a wallet with no money cannot do anything expensive by accident.userdata.get("WALLET_KEY").
Signing In Instead of Authenticating
There is no key to send, so each request carries a proof that the wallet owner made it. The proof is an EIP-4361 message, signed, then base64 encoded into theSIGN-IN-WITH-X header.
The message format is exact. Venice rebuilds these bytes on its side and verifies your signature against them, so a stray blank line means a rejected signature rather than a helpful error.
Issued At. Each nonce is single use for about five and a half minutes. And the signer must match the wallet in the path, so one wallet cannot inspect another and gets a 403 for trying.
The practical consequence is that you sign a fresh header per request rather than caching one. Signing is local and free, so this costs nothing.
canConsume is the field to branch on. It accounts for the ten cent floor, so you do not have to.
Putting Money In
Topping up is two requests. The first asks what Venice accepts and is unauthenticated, because there is nothing to authenticate yet. The second carries a signed transfer authorization.amount is in base units, and USDC has six decimals, so 5000000 is five dollars and not five million of anything. On the Solana rail, extra.feePayer is a Venice operated account that covers the transaction fee, which is what lets a wallet pay without holding SOL.
Settling from a wallet with no USDC returns a 400 with PAYMENT_VERIFICATION_FAILED. That is the expected shape of failure: the signature was fine and the transfer was not.
Paying Per Call
With a balance in place, inference is a normal request that happens to carry a signature. Turning off the Venice system prompt matters more than it looks: it is worth about seventeen hundred input tokens per call, which is two orders of magnitude more than the question itself.402 as a normal outcome rather than an exception is the whole design. An agent paying its own way will run out of money eventually, and running out of money is not a crash.
Reading What It Spent
The ledger is authoritative. Rather than estimating from token counts, ask what was actually charged.TOP_UP and REFUND rows appear here too, with positive amounts. Filtering to CHARGE gives you spend.
The Budgeted Run
Now the loop. Before each call the agent checks what it has spent, and it declines to start work it cannot pay for.Where This Leaves You
The agent holds its own money, proves its identity with a signature, and cannot exceed a limit you set, all without an account existing anywhere. For a scheduled job, a serverless function, or anything you would rather not hand a long-lived key to, that is a materially different security posture. Some things worth doing next:Cap it in the protocol
Spend controls in the SDK are per payment, not per session. Pair them with the budget loop above so a bug in one cannot defeat the other.
Refill on empty
Catch the
402, top up, and retry. This is what venice-x402-client does for you on the TypeScript side.Pay on Solana
Same flow, different rail. Sign Ed25519 and set the returned
feePayer so the wallet needs no SOL.Give it real work
Swap the task list for a tool-calling loop and the ledger starts showing you what each decision cost.