@piprail/sdk · TypeScript · MIT
Accept and make payments, in one line.
PipRail is an open-source x402 SDK: 28 chains, 10 families, 0 protocol fee, no backend — payments settle straight to your wallet, verified locally against your own RPC. Gate a route to charge for itself, or point an agent at a paid URL and it pays itself.
Accept — charge for any endpoint.
requirePayment is the Express one-liner;
createPaymentGate is the framework-agnostic core for everything
else (Next.js, Hono, Fastify, Cloudflare Workers, Bun, Deno). Build a gate, switch on verify().
Express — one middleware
import { requirePayment } from '@piprail/sdk'
app.get('/report',
requirePayment({
chain: 'solana',
token: 'USDC',
amount: '0.05',
payTo,
}),
(req, res) => res.json({ data }),
) Everything else — the gate
import { createPaymentGate, toInvalidBody } from '@piprail/sdk'
const gate = createPaymentGate({
chain: 'base', token: 'USDC',
amount: '0.05', payTo,
})
// in your handler — the proof rides in a header
const r = await gate.verify(sig)
if (r.kind === 'paid') return ok(data, r.receiptHeader)
if (r.kind === 'challenge') return res402(r.challenge)
return res402(toInvalidBody(r)) // wrong amount / expired / replayed paidchallengeinvalidPay — let an agent pay for itself.
Wrap the agent's calls with PipRailClient. On a 402 it reads the
challenge, pays on-chain, waits for confirmation, and retries with proof — you just get the 200 back.
Runs anywhere JavaScript does: Node, edge, or the browser.
import { PipRailClient } from '@piprail/sdk'
const client = new PipRailClient({
chain: 'arbitrum',
wallet: { privateKey: process.env.KEY },
})
// On a 402: pays, then retries.
const res = await client.fetch(url) quote(url) prices it without paying;
estimateCost(url) adds the native-coin gas; and an opt-in
policy refuses anything out of bounds before a token moves.
Prefer no code? Use the MCP server →
One word picks the chain.
Switch networks by changing a single string — from Ethereum to Solana to TON. Same line, same wallet. Or offer several at once and let the agent pay with whatever it holds.
Name the chain
requirePayment({
chain: 'hyperevm', // ← any of 28 chains
token: 'USDC',
amount: '0.05',
payTo,
}) Or take several in one challenge
requirePayment({
accept: [
{ chain: 'arbitrum', token: 'USDC', amount: '0.05', payTo: evm },
{ chain: 'solana', token: 'USDC', amount: '0.05', payTo: sol },
],
}) One nonce, several rails — no per-chain routes to wire up.
Agent-safe by default.
Hand an autonomous agent a wallet without losing sleep. Set a budget, and PipRail refuses anything outside it before a single token moves — the safety lives in code, not a prompt.
const client = new PipRailClient({
chain: 'monad', wallet,
policy: {
maxAmount: '0.10', // per call
maxTotal: '5.00', // lifetime
tokens: ['USDC'], // only USDC
},
})
// Price it — without paying.
const q = await client.quote(url)
// …and the gas to send it (native coin).
const { cost } = await client.estimateCost(url)
// Over budget? Refused before any send.
await client.fetch(url) - Spend limits — per-call + lifetime caps, enforced on the token’s true decimals
- Quote first — learn the exact price without paying it
- Estimate the gas — native-coin network fee before you pay — on every chain
- Approve each pay — a final yes/no hook before any funds move
- Spend ledger — read back exactly what was spent, per token
- One wallet, an LLM tool — drop into MCP or the AI SDK — budget rides along
Plan before you pay.
One read-only call checks a 402 against your own wallet — balance, native gas, and whether the recipient can receive — and tells you the rail to use, or exactly what to top up. Then one line pays it.
// Will this 402 go through — and on which rail?
const plan = await client.planPayment(url)
if (plan.payable) {
// pays plan.best — cheapest rail you can settle
await client.fetch(url, { autoRoute: true })
} else {
console.log(plan.fundingHint)
// "Have the USDC, need ~0.00002 ETH for gas."
// "Recipient must opt into the USDC ASA first."
} - Enough token? — your live balance of the exact payment token, per rail
- Enough gas? — the native coin to send it — you can hold USDC but no ETH
- Can they receive? — trustline / ATA / storage_deposit / ASA opt-in — before you broadcast
- Within budget? — your spend policy, all checked in one read-only call
quote() tells you the price,
estimateCost() the gas, and
planPayment() whether you can actually settle it — all on your own RPC,
with no facilitator, oracle, or bridge.
How it works.
A four-step round trip over plain HTTP. No facilitator, no custody.
Agent calls your route
It gets back a 402 quote — price, token, payTo, and chain.
Agent pays on-chain
One transfer, straight to your wallet. PipRail never touches the funds.
You verify locally
Your server checks the tx against your own RPC: succeeded, recent, right amount and recipient.
You return the data
200 OK, the gated content flows, and the same proof can never be spent twice.
x402 v2 (§7) explicitly endorses merchant-local verification — no facilitator required. Self-custody throughout: the payer signs and broadcasts their own transfer; PipRail never holds funds.
Backendless by design.
How PipRail differs from a typical facilitator-based x402 stack — all of it a consequence of one choice: the payer broadcasts their own transfer and you verify it yourself.
| PipRail | Facilitator-based x402 (typical) | |
|---|---|---|
| Backend to run | None — it’s an npm package | A hosted facilitator service |
| Protocol fee | 0 — payments settle wallet-to-wallet | Often a per-transaction cut |
| Custody | Self-custody; keys never leave your process | Funds routed via the facilitator |
| Verification | Local, against your own RPC | Delegated to the facilitator |
| Chain coverage | 28 chains, 10 families | Commonly one or two chains |
| Lock-in | None — MIT, runs headless or in the browser | Tied to the provider |
Runs everywhere, documented everywhere.
Pure TypeScript with a single viem peer dep; non-EVM libs are
optional, lazy-loaded peers. Headless or in the browser.
Glossary.
The terms PipRail sits on — defined plainly, for humans and answer engines.
- x402
- An open payment protocol that revives the HTTP 402 "Payment Required" status code. A server answers a request with 402 plus a machine-readable challenge (price, token, chain, pay-to address); the caller pays on-chain and retries with proof, and the request goes through — letting an HTTP endpoint charge for itself with no API keys, accounts, or invoices.
- HTTP 402 Payment Required402
- A status code reserved in the original HTTP specification for payment, long left unused. x402 turns it into a working protocol: a 402 response carries a payment challenge a client can satisfy programmatically.
- Facilitator
- A third-party service that, in many x402 stacks, settles or verifies the payment in the middle of the flow. PipRail is backendless: there is no facilitator — the payer broadcasts their own transfer and the merchant verifies it locally against their own RPC. The x402 v2 spec (§7) explicitly permits this merchant-local model.
- Model Context ProtocolMCP
- An open standard for connecting AI agents (Claude Desktop, Cursor, Claude Code, Windsurf, VS Code, Cline) to external tools. @piprail/mcp is an MCP server that hands any MCP client a budget-bound wallet so it can pay x402 URLs autonomously, capped by a local spend policy.
- Agentic commerce
- Economic activity in which autonomous AI agents — not humans clicking checkout — discover, price, and pay for data, compute, and services. x402 is the HTTP-native payment rail for it; PipRail is the drop-in SDK that makes it one line.
- onchain-proof scheme
- PipRail’s default x402 settlement scheme: the payer sends a real on-chain transfer and the proof is the transaction itself, which the merchant verifies on its own RPC (the right amount of the right token to the right address, recent, and not already used). Self-custodial end-to-end, with no facilitator.
- Stablecoin (USDC / USDT)
- A token pegged to a fiat currency, used for predictable pricing. PipRail ships canonical stablecoins per chain — USDC almost everywhere, USDT on most, plus EURC and RLUSD where they are native — and the chain’s native coin is always a valid payment asset too. Any other token works by address.
- Self-custody
- You hold your own keys and funds; no service ever takes possession. PipRail never custodies money: payments settle wallet-to-wallet, keys never leave your process, and there is no PipRail backend in the path.
SDK FAQ.
For the developers — and agents — wiring PipRail in.
What is x402?
x402 revives the dormant HTTP 402 "Payment Required" status code as a real payment protocol. A server answers a request with 402 plus a machine-readable challenge (price, token, chain, pay-to address); the caller pays on-chain and retries with proof, and the request goes through. It lets an HTTP endpoint charge for itself — no API keys, accounts, or invoices — which is exactly what AI agents need to pay for data and compute autonomously.
How do I accept crypto payments in Next.js (or any framework)?
Install @piprail/sdk and viem, then in a Route Handler build a gate once with createPaymentGate({ chain: 'base', token: 'USDC', amount: '0.05', payTo }) and call gate.verify(req.headers.get('payment-signature')) inside GET. If the result is 'paid', return the resource + receipt header; if 'challenge', return it with status 402; otherwise return toInvalidBody(result) with 402. No backend or database — verification runs locally against your own RPC. The same createPaymentGate pattern covers Hono, Fastify, Workers, Bun, and Deno; Express gets the requirePayment one-liner.
How do AI agents pay for APIs with PipRail?
Wrap the agent's HTTP calls with PipRailClient. Give it a wallet and a chain, then call client.fetch(url): on a 402 it reads the challenge, sends the payment on-chain, waits for confirmation, and retries with proof — automatically. Use client.quote(url) to learn a price without paying, client.estimateCost(url) to budget gas, and an opt-in spend policy (maxAmount, maxTotal, chains, tokens, hosts) that refuses out-of-bounds calls before any send. paymentTools(client) hands the same to an LLM via MCP, the Vercel AI SDK, or function-calling — budget-bound so it can't overspend.
How does an agent know if it can actually pay before paying?
Call client.planPayment(url). It's a read-only call that surveys the 402 across every rail it offers on your chain and checks each against your own wallet: token balance, native-coin gas, and whether the recipient can even receive (trustline / associated token account / storage_deposit / ASA opt-in / account activation). It returns payable plus the best rail to use, per-rail blockers (INSUFFICIENT_TOKEN, INSUFFICIENT_GAS, RECIPIENT_NOT_READY, OUTSIDE_POLICY), and a one-sentence fundingHint telling you exactly what to top up. It never throws for a transient RPC failure (that rail comes back as state: 'unknown'), and returns null when the URL isn't payment-gated. Turn on autoRoute and client.fetch pays the cheapest settleable rail automatically; planAcross(clients, url) plans across several chains at once.
How do agents discover my x402 endpoint, and how do I get listed?
Discovery is built in and backendless — PipRail builds on the open x402 indexes that already exist (402 Index, the CDP Bazaar read API, x402scan) and hosts none of its own. To be found, call client.register(url): one POST to 402 Index, no auth and no signature, searchable in seconds (optionally also x402scan via one wallet signature, Base/Solana only). To find resources to pay, call client.discover({ query }), which reads those open indexes for free and returns candidates you then quote and pay as usual. You can also emit a static discovery file from your gate's config with buildOpenApi / buildWellKnownX402 / buildX402DnsTxt (fed by gate.describe()) and serve it on your own origin. For an LLM/MCP it's two tools: piprail_discover and piprail_register. No registry, no database, no fee.
Is there a fee to use PipRail?
No. PipRail charges no fee and takes no cut. It's an open-source (MIT) npm package, not a platform or hosted service. Payments settle straight into your own wallet — there's no PipRail backend, facilitator, or middleman in the path. You pay only normal network gas on whichever chain you choose.
Does PipRail need a backend, database, or account?
None. PipRail is backendless and self-custodial: no server to run, no database, no auth, no sign-up. Payment proofs are verified locally on-chain against your own RPC, with an in-memory replay guard (pluggable to Redis for multi-instance). The x402 v2 spec explicitly lets resource servers host verification themselves, so this shape is spec-supported, not a workaround.
Can the same app both take and make payments?
Yes — that's the design. Use requirePayment (Express) or createPaymentGate (everything else) to charge for a route, and PipRailClient to pay for calls the same app makes outbound. Install the one package, add a wallet, and you can monetize and pay in the same process. It's pure TypeScript and runs headless or in the browser.
Get paid by agents in the next five minutes.
One install. One line. Straight to your wallet, on every chain that matters.