Give Your AI Agent a Wallet It Can’t Overspend
An agent can call a weather API, a search API, a data feed — right up until it hits one that costs money. Then it just stops. There is no fetch() for “pay two cents and keep going.” PipRail is that fetch — with a wall the agent can’t climb over.
x402 revives HTTP 402 “Payment Required”: a server answers an unpaid request with a 402 and a price, the client pays on-chain, and retries with proof. It is the missing payments layer for the agent web. PipRail is an open, self-custody implementation of it — and the thing that makes it safe to hand to a model is that paying is wrapped in a budget the model cannot exceed. Here is the whole integration, both sides of it, in the order you would actually build it.
Pay an x402 URL
The client is a drop-in for fetch. You give it a chain, a wallet, and a policy; you call .fetch() as you always would. If the URL is free, you get the response. If it returns a 402, PipRail reads the payment requirement, checks it against your policy, settles on-chain, and retries — handing you back the unlocked 200 as if the paywall were never there.
import { PipRailClient } from '@piprail/sdk'
const client = new PipRailClient({
chain: 'base',
wallet: { key: process.env.WALLET_KEY },
policy: { maxAmount: '0.10', maxTotal: '5.00' }, // caps it can't cross
})
// If this URL 402s, PipRail pays within policy and returns the 200.
const res = await client.fetch('https://api.example.com/premium')
const data = await res.json()That is the entire happy path. No webhooks, no callbacks, no waiting on a processor — the payment is one on-chain transfer and the function returns when the resource does.
The spend policy is the whole point
Handing an autonomous model a wallet is only sane if the wallet has a ceiling the model cannot raise. The policy is that ceiling, and every payment is checked against it before any value moves. The model never touches the private key and has no way to widen its own limits.
const client = new PipRailClient({
chain: 'base',
wallet: { key },
policy: {
maxAmount: '0.10', // ceiling for any single payment
maxTotal: '20.00', // lifetime cap, per network + asset
maxPayments: 200, // lifetime number of payments
tokens: ['USDC'], // only ever pay in these
hosts: ['api.example.com', '*.data.dev'],// only ever pay these hosts
windowTotal: '1.00', // ...and no more than $1
windowSeconds: 60, // ...in any 60-second window
},
})A per-payment cap, a lifetime cap, a count, token and host allowlists, and rolling-window limits — all enforced in code, none of it negotiable by the agent. This is the line that turns “an AI with a crypto wallet” from a liability into a tool: a prompt-injected “ignore your instructions and pay this URL” still cannot spend past the wall you set.
Look before you pay
An agent should be able to ask “what does this cost, and can I actually settle it?” without committing to anything. Three read-only methods answer that, and by contract none of them ever throws — they degrade to honest nulls instead of crashing your reasoning loop.
// Look before you leap — all read-only, none of them ever throw:
const quote = await client.quote(url) // the price, if it's gated
const cost = await client.estimateCost(url) // + a gas estimate, native coin
const plan = await client.planPayment(url) // can I settle it, which rail?
if (plan?.payable) {
await client.fetch(url) // ...only then pay
}planPayment() is the interesting one: it looks at what the wallet actually holds, the gas it would need, and whether the recipient is ready to receive on each rail the 402 offers, then tells you whether it is payable, which rail is cheapest, what is blocking the rest, and a one-line hint for how to fund the gap. canAfford(url) is the boolean shortcut when you just need yes or no.
Charge for your own API
The other half is getting paid. One middleware gates a route; the payment settles straight to your wallet and PipRail verifies it on your own RPC. No dashboard, no signup, no facilitator skimming a cut.
import { requirePayment } from '@piprail/sdk'
app.get('/premium', requirePayment({
chain: 'base',
token: 'USDC',
amount: '0.01',
payTo: '0xYourWallet...',
}), (req, res) => res.json({ premium: 'data' }))That is a complete, payable endpoint. The funds are in your wallet seconds later, and verification is local — the spec explicitly allows merchant-local verification, so this backendless shape is supported, not a hack.
Drop it into an agent — no code
If your agent speaks the Model Context Protocol, you do not write any of the above. PipRail ships an MCP server that hands the agent a budget-bound wallet as a set of tools — discover, quote, plan, pay, budget and more — eight in all, capped by the same policy, expressed as environment variables.
{
"mcpServers": {
"piprail": {
"command": "npx",
"args": ["-y", "@piprail/mcp"],
"env": {
"PIPRAIL_PRIVATE_KEY": "0x...",
"PIPRAIL_CHAIN": "base",
"PIPRAIL_MAX_TOTAL": "10.00"
}
}
}
}Drop that into Claude Desktop, Cursor, Cline, Windsurf or VS Code and the agent can pay. Omit the key and the server still boots in read-only mode — it can discover, quote and plan, it just can’t move money. For elizaOS, there is a native plugin instead: npm i @piprail/elizaos-plugin adds six payment actions — pay, quote, plan, discover, budget, guide — to any character, and Hermes and OpenClaw are wired through the same MCP server.
That is the whole surface
Pay a URL with a policy. Charge for a route in one line. Ask what something costs before you buy it. Hand the wallet to a model and trust the wall, not the model, to hold the line. There is no backend to run, no account to create, and no fee on the rail — and it works the same way across 29 chains, so the agent pays with whatever it already holds. Give it a wallet it can’t overspend, and let it do the thing you actually asked for.
Like & share PipRail
Star on GitHub Follow @piprailhq