x402 + ERC-8004 · seller side, from scratchBase settlement ~200ms · free tier 1,000 tx/motonight: your endpoint earns testnet USDC
Ray (60s):
Welcome to VCN #37, Settlement. Builder night. Talks first, then you wire it yourself.
The whole point in one line: by 10pm one agent pays another, on chain, no human in the loop.
Co-hosts in the room: Michalis, Eric, Devinder. Flag one of us if you stall. We circle.
If you read the Luma copy and saw X-PAYMENT, hold that thought. The API renamed. I will show you the current one so your code actually runs.
The pivot
HTTP402waited since1996.
402 Payment Required was reserved in the spec and left empty for thirty years.
The web billed humans with redirects and forms. An agent cannot fill a form.
x402 finally gives 402 a job. The web that billed humans is over.
Ray (45s):
402 is the only HTTP status code that shipped reserved and stayed empty. It was waiting for a payer that is not a person.
Agents do not have a credit card form. They have a wallet and a header. That is the whole shift.
Context
x402 is a market you can bill.
Protocol
Coinbase incubated. Revives HTTP 402. Open spec.
Rails
Base, Polygon, Arbitrum, World, Solana. USDC, EURC via EIP-3009 or Permit2.
Settlement
Base clears in ~200ms. Free tier 1,000 tx/mo, then $0.001 each.
Surface
One header in. 402 or 200 out. No SDK lock in.
Reference lives at the x402 Foundation repo. The CDP facilitator does the verify so you write the price, not the crypto.
Ray (75s):
Four blocks. Do not go deep on chains here. The takeaway is the surface: a header in, a 402 or a 200 out.
The facilitator is the part that checks the payment on chain. You do not touch a private key as the seller.
USDC on Base is the default. We will come back to why on the footguns slide.
Why now
Thisstopped beingademo.
Feb 2026
Stripe shipped x402 on Base for agent USDC · purl CLI
May 2026
AWS Bedrock AgentCore Payments launched on it · 4 regions
0
Payments in year one · ~$48M volume · ~95% on Base
0
Free transactions / month · then $0.001 each
~200ms
USDC settlement on Base
~6k
Stars on the x402 repo · 3 SDKs · TS, Python, Go
And almost nobody at a meetup has wired the seller side from scratch. That is tonight.
Ray (60s):
This is the slide that says the window is now. Stripe in February. AWS in May. Both built on x402.
169 million payments in the first year, about 48 million dollars of volume, almost all on Base. This is not a testnet toy at the protocol level.
But the seller side, the thing that actually bills, almost no one here has written from scratch. So we do.
The seam
x402 is the money. ERC-8004 is the trust.
Two stacks, one seam. The EIP says it plainly. Payments are orthogonal to this protocol. Keep them separate on purpose.
Ray (60s):
This is the mental model for the whole night. Money on the left. Trust on the right. A dotted line between them, not an arrow.
x402 answers did they pay. ERC-8004 answers who are they and can I trust the wallet. Different questions, different standards.
The mistake people make is welding them together. We keep the seam. You can ship the paywall tonight without touching identity at all.
The build
Tonight,fouracts.
1Paywall thirty lines of Express
2Pay from a testnet wallet
3Identity who is calling
4Loop thirty seconds, no human
By 10pm your endpoint earns USDC from an agent. Hosts circle. Pair up if you are new to crypto.
Ray (40s):
Four acts. We do act one together on stage, then you run it. Two, three, four you build at your seat while we circle.
You can stop after act one and still walk out with a working paywall. Each act is a checkpoint, not a prerequisite for the next.
Act 1 / 4
Thirty lines. 402 or 200.
// the seller. paid GET /weather, current @x402/* packagesimport express from"express";
import { paymentMiddleware, x402ResourceServer } from"@x402/express";
import { ExactEvmScheme } from"@x402/evm/exact/server";
import { HTTPFacilitatorClient } from"@x402/core/server";
const facilitator = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" });
const server = new x402ResourceServer(facilitator)
.register("eip155:84532", new ExactEvmScheme()); // Base Sepolia
app.use(paymentMiddleware({
"GET /weather": { accepts: [{ scheme: "exact", price: "$0.001", network: "eip155:84532", payTo }] },
}, server));
app.get("/weather", (_req, res) => res.json({ weather: "sunny", tempF: 70 }));
Run it. Hit /weather. It 402s you. The header was X-PAYMENT in v1, it is PAYMENT-SIGNATURE now. Pin @x402/*@2.15.0. Price "$0" for the soft launch.
Ray (90s):
This is the whole seller. The middleware does the 402. You declare one route and a price.
Heads up, and this is the one that bites: the package renamed. Old Luma copy says x402-express and X-PAYMENT. Current is the scoped at-x402 packages and PAYMENT-SIGNATURE. Use what is on the screen.
Network is the CAIP-2 id eip155:84532, that is Base Sepolia. The string base-sepolia was the old API.
Set price to dollar zero and you have a paywall that lets everyone through. Flip the meter later with one config line.
Act 2 / 4
Base Sepolia gives you free USDC.
# 1) unpaid request -> 402. current x402 carries requirements in a header
$ curl -i http://localhost:4021/weather
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: <base64: [{ scheme:"exact", network:"eip155:84532", price:"$0.001" }]>// 2) the signed retry comes from the client, not by handimport { x402Client, wrapFetchWithPayment } from"@x402/fetch";
const pay = wrapFetchWithPayment(fetch, client); // client holds your funded signerconst res = await pay("http://localhost:4021/weather"); // 402 -> sign -> retry -> 200
The faucet drips testnet USDC. The wrapper signs and retries for you, so the round trip is one call.
Testnet keys still leak. Never commit the secret. Never log it.
Ray (75s):
Two halves. The curl shows the raw 402 so you see the protocol. You cannot hand sign a real payment in a shell, so the second half is the client.
wrapFetchWithPayment is the magic. It catches the 402, signs with your funded testnet key, retries, and hands you the 200. One call from your code.
Base Sepolia faucet gives you the USDC for free. Real signature, real settlement, fake money. The bytes are real.
Say it with me. Never commit the key. Testnet or not.
Act 3 / 4
Register who is calling.
// ERC-8004 Identity registry is an ERC-721. register() mints an agent NFT.const identityRegistryAbi = [{
type: "function", name: "register", stateMutability: "nonpayable",
inputs: [{ name: "agentURI", type: "string" }],
outputs: [{ name: "agentId", type: "uint256" }], // the ERC-721 tokenId
}] as const;
const agentId = await wallet.writeContract({
abi: identityRegistryAbi,
address: "0xIdentityRegistry", // PLACEHOLDER, pull the live Base Sepolia deploy on the night
functionName: "register",
args: ["https://my-agent.example/agent.json"],
});
Now your paywall can ask is this caller a wallet I can trust, separate from did they pay.
Reputation and Validation layer on later. Tonight, Identity only.
Ray (75s):
This is the right column from the seam slide. We are not billing here. We are minting an identity.
The Identity registry is just an ERC-721. register mints an NFT, the tokenId is the agentId. That is the agent's on chain handle.
Honest caveat: ERC-8004 is a draft EIP. The deployed registry address is a placeholder on this slide. We pull the live Base Sepolia address on the night, it moves.
You do not need this to bill. It is the trust layer you add when who is calling starts to matter.
Act 4 / 4
Discover. Pay. Respond. No human.
With a human
The agent waits for your yes at every call. The loop stops on you.
Autonomous
Discover, pay, get the response. One loop. About thirty seconds.
const pay = wrapFetchWithPayment(fetch, client); // wallet can pay, autonomouslyconst endpoint = "http://localhost:4021/weather"; // or discover via the x402 Bazaarconst res = await pay(endpoint); // 402 -> sign -> retry -> 200. no prompt.
console.log("agent bought:", res.status, await res.json());
Ray (60s):
Same client as act two. The only change is no human in the loop. The agent decides, pays, and uses the answer.
Discover is shown as a known URL here. In the wild that is the x402 Bazaar, the discovery layer where agents find paid endpoints. I did not pin the exact Bazaar call, so we keep the honest version.
Point your loop at a neighbor's paywall and you have two agents paying each other. That is the show and tell.
Footguns
Hereiswhattripsyou.
Chain by gas
Picking a chain on gas price. USDC on Base is the default. Stripe, AWS, Coinbase all settle there.
Stripe webhooks
Rolling webhooks instead of x402. Pre agent economy. Use x402 at price $0 if you do not bill yet.
Open MCP
Shipping MCP endpoints with no paywall. Even free should pass the paywall so the meter is one line away.
Welded identity
Mixing ERC-8004 into x402. They are orthogonal on purpose. Keep the seam from slide five.
Ray (60s):
Four ways to lose the night. Chain by gas, you end up off the rails everyone settles on. Pick Base.
Stripe webhooks feel familiar and they are the old world. x402 at dollar zero gives you the new shape with no billing risk.
Paywall even your free endpoints. Then flipping the meter is one config change, not a rewrite.
And do not weld identity into payment. The whole design is that they are separate.
One honest slide
Freeze is not free.
Any non toy deployment needs KYC equivalent surfaces. Scaling on USDC rails in regulated settings needs safeguards that do not assume a human in the loop.
USDC's blacklist is enforced by ordinary on chain transactions, and competitive sequencers can race them. Enforcement has real limits.
One honest slide. Tonight is testnet, so you are clear. Production is a different conversation.
Ray (60s):
I put one slide in the deck that is not build forward. This is it.
The Compliance-Aware paper is clear. The minute this leaves a toy, you owe KYC equivalent surfaces. Do not skip that and call it shipped.
And freeze is not free. The Sanction-Evasion-MEV work shows the blacklist is enforced by transactions that can be raced. Real money moves before the freeze lands. Know the limit.
Tonight you are on testnet, so build freely. I just want the honest version in your head before you put real value on it.
What you ship
What you walk out with.
Your paywall
Thirty lines you wrote, earning testnet USDC from an agent.
Your identity
An ERC-8004 Identity registration, minted on chain.
Your buyer loop
The autonomous agent paying your own endpoint, no human.
Your read
x402 versus Stripe webhooks, and why the human web is over.
Ray (40s):
Four things in your hands at 10pm. A paywall, an identity, a buyer loop, and a real read on the space.
This is the durable part. Tomorrow morning your endpoint still bills. That is the point of building it from scratch.
Go further
Nowbillsomethingstrange.
Agent buys agent
Point your buyer loop at a neighbor's paywall. Pay each other.
Price discovery
Set price by demand. Raise it when an agent keeps coming back.
Paywall a tool
Wrap a real MCP tool behind x402 at $0, then flip the meter.
Bazaar buyer
Hit the x402 Bazaar, discover a paid endpoint, pay it autonomously.
Show and tell near 9. Best weird wins.
Ray (40s):
Once the loop works, get strange. The best demo last time was two agents trading payments in a circle until someone ran out of testnet USDC.
Pair up. The agent buys agent one is the most fun and the easiest to film for the recap.
Before you build
Bringthis.
Laptop. Node 20+. Claude Code or your editor of choice.
A Base Sepolia testnet wallet. We set one up at the door if you need it.
An endpoint you would be okay charging for.
Some crypto fluency helps. The demo flow does not require it.
Ray (30s):
If you are missing Node or a wallet, raise a hand now and a host will get you set up before we start act one.
No endpoint of your own? Use the weather one. The point is the meter, not the payload.
Ship it
By10pmyourendpoint earnsUSDC.
Testnet USDC. But the bytes are real.
x402.orgThe protocol
github.com/x402-foundation/x402The repo, 3 SDKs
Base Sepolia faucetFree testnet USDC
Hosts: ray · michalis · eric · devinder · show and tell near 21:00 · stay after for production talk
Ray (30s):
That is the talk. Three links on the screen. x402.org, the foundation repo, and the Base Sepolia faucet.
Hosts roam now. Build act one first, then get strange. Group photo near 8:30 for the VCN feed.