How it works
Introduction
Section titled “Introduction”PipRail’s whole design follows from one constraint: no backend. No server PipRail runs sits between you and your money. That sounds like a limitation; it’s the opposite — it’s what lets payments settle straight to your wallet, with nothing to sign up for and no fee to skim.
The round-trip
Section titled “The round-trip”A payment is a four-step HTTP exchange:
- Challenge. The client requests a gated resource. The server answers
402 Payment Requiredwith an x402 challenge describing what it will accept (chain, asset, amount, recipient, a one-time nonce). - Pay. The client picks an acceptable rail, broadcasts the transfer on-chain from its own wallet, and re-requests the resource — this time carrying a proof of payment.
- Verify. The server re-derives every field it cares about from its own trusted challenge (never the client’s echo), then checks the proof on-chain against its own RPC.
- Deliver. If the proof is valid, recent, and unused, the server returns
200with the goods.
client ──GET /report──────────────▶ serverclient ◀──402 + challenge────────── serverclient ──(pay on-chain)──▶ blockchainclient ──GET /report + proof──────▶ server ──(verify on-chain)──▶ its own RPCclient ◀──200 + the goods────────── serverVerification is local — there’s no facilitator
Section titled “Verification is local — there’s no facilitator”A “facilitator” is the third party most x402 stacks use to verify and settle payments. PipRail has none. The server verifies the proof itself, on-chain, against the RPC you give it, plus an in-memory used-proof set and a recency window to stop replays.
Proof binding — so a payment can’t be forged or replayed
Section titled “Proof binding — so a payment can’t be forged or replayed”A proof must be cryptographically bound to the specific challenge it answers. PipRail uses two templates, picked per family:
- Template A — memo/nonce-bound (Stellar, XRPL, NEAR, Algorand, TON): the challenge nonce
rides in a memo/note/comment, and
verify()matches it on the merchant’s own account. - Template B — digest-bound (EVM, Solana, Tron, Sui, Aptos, and every native coin): the proof is the transaction hash/digest, verified by reading the transaction plus a recency window and a single-use proof set.
Either way, verify() re-derives every checked field from the trusted challenge, so a
forged echo can’t redirect it. The details per family live in Proof
binding.
One driver per family
Section titled “One driver per family”Under the hood, each chain family is a self-contained driver (evm, solana, ton, …)
implementing one contract. The protocol layer — the parts that issue challenges, parse
envelopes, and run the client — depends only on that contract, never on viem or any chain
library. That’s what makes non-EVM families lazy-load on demand: a pure-EVM install never
pulls in Solana or TON code.
Read more in The PaymentDriver architecture.
Why backendless is allowed
Section titled “Why backendless is allowed”The x402 v2 spec (§7) explicitly permits merchant-local verification — “resource servers MAY… host the endpoints themselves.” So PipRail’s shape isn’t a clever workaround; it’s the spec-blessed path, just taken all the way.