What you will add
A pay-per-call paywall on an existing HTTP API, so callers, agents or anything that speaks x402, pay in USDC on Base before a priced route runs. You do not rebuild the API. You mount one adapter in front of the routes you choose to price, and everything else stays as it is. By the end, a request to a priced route returns 402 until it is paid, and your handler runs only on a verified payment.
This is the generic-API version. If your API is specifically an MCP server, how-to-add-payments-to-mcp-server is shaped for that; if you are charging for an agent's services, how-to-charge-for-ai-agent-services covers the pricing structure. The payment API product page is the broader reference.
When x402 fits an API
x402 is the right addition when your callers are programs, especially agents, and the payments are small and frequent. An agent calling your API hundreds of times cannot fill in a checkout form or hold a subscription you provisioned, but it can pay a 402 automatically. If that is your traffic, x402 turns your API into something an agent can pay per call with no onboarding.
It fits less well when your callers are humans buying occasionally, or when you sell access as a negotiated contract. A human checkout is better served by a card, and a B2B contract by an invoice. The honest test: if a meaningful share of your future callers will be agents or machine clients making many small calls, x402 is worth adding now, because it is the only rail that prices that traffic. If your API is purely human-facing today, you can add it later when machine demand shows up, and gate just the routes that demand reaches.
There is also a hybrid worth knowing about: you can run x402 for the agent-driven path and keep a traditional checkout for the human-driven one, because the two live on different routes and do not interfere. An API does not have to choose one rail for everything. The natural shape is to add x402 to the endpoints agents actually call, leave human-facing flows on whatever they use today, and let each kind of caller pay the way that fits it. That keeps the addition low-risk: you are extending the API to a new kind of payer, not migrating your existing one.
Prerequisites
- A Blockchain0x account with an agent created, so you have a wallet to receive into and a
payToAddress. - A
sk_test_API key and apaymentRequestIdfor each priced route. - An existing Fastify or Express API on Node 18+. The SDK targets
>=18.
export B0X_API_KEY=sk_test_...
export B0X_PAYTO_ADDRESS=0x...Mount the adapter
Add the adapter to your existing app and list the routes you want paid. Here is Fastify:
import { createClient } from "@blockchain0x/node";
import { createX402Plugin } from "@blockchain0x/x402/server/fastify";
const sdk = createClient({ apiKey: process.env.B0X_API_KEY! });
await app.register(createX402Plugin, {
sdk,
defaultNetwork: "testnet",
pricing: {
"POST /v1/enrich": { amountUsdc: "0.01", payToAddress: process.env.B0X_PAYTO_ADDRESS!, paymentRequestId: "pr_enrich" },
},
});
// Your existing route is unchanged; it just runs only once paid now.
app.post("/v1/enrich", existingEnrichHandler);Express is the same shape with createX402Middleware({ sdk, defaultNetwork, pricing }) passed to app.use. You did not touch existingEnrichHandler; you wrapped its route.
What changes for existing clients
This is the part to plan, because adding a paywall changes a route's contract. A route you move into the pricing table starts returning 402 to callers that do not pay, including any existing client that was calling it for free. So sequence it deliberately.
The safe path is to gate new or clearly-premium routes first and leave your current free routes alone, so existing clients see no change. When you do want to charge for an established route, give current callers notice, and consider exposing the paid version on a new path while the old one is deprecated, rather than flipping a live endpoint to 402 under them. Agents that speak x402 will adapt automatically, since a 402 is just a price to them, but any non-x402 client calling that route will start failing, so treat moving an existing route into the pricing table as a breaking change and roll it out like one.
Other frameworks
The shipped adapters are Fastify and Express, but x402 is just HTTP, so you are not stuck if your API runs on something else. There are two clean options.
The first is to front the priced routes with a thin Fastify or Express layer that mounts the adapter and proxies to your real service. This is the least code and keeps you on the supported path; the adapter does the 402 and verification, and your existing service runs unchanged behind it. For many stacks, a small gateway in front of the paid routes is the pragmatic answer.
The second is to implement the handshake yourself using the wire helpers in @blockchain0x/x402: return the 402 body in the right shape, read the X-Payment header on the retry, and verify it. This is more work, covered in the payment API reference, but it lets a Koa, Hono, Django, or raw-http server speak x402 natively without a sidecar. Reach for the wire helpers when a gateway is not acceptable; reach for the gateway when it is, which is most of the time.
Verify and price
The adapter verifies payment for you. On the retry it reads the X-Payment header and calls paymentRequests.settle to confirm the on-chain transfer matches the quoted requirement, then runs your handler. A missing or mismatched payment is rejected with a fresh 402 and a reason you can log (header_missing, requirement_mismatch, settle_rejected, and a few others).
Pricing is per route, in USDC decimals. Start from your real per-call cost plus a margin, the same cost-plus approach as any paid API, and put each distinct service on its own route so you can price them separately. Leave anything that supports discovery, a capabilities or health route, out of the pricing table so callers can evaluate the API for free before paying.
Test on Base Sepolia
Run the whole loop on testnet before going live. With defaultNetwork: "testnet" and a sk_test_ key, call a priced route with no X-Payment header and confirm the 402 quotes the right amount; then pay it from a test wallet (the pay side is createX402Client) and confirm your handler runs. Confirm your unpriced routes still return normally. When the paid and free paths both behave, set defaultNetwork to mainnet and swap to a sk_live_ key for Base.
Common pitfalls
Three traps.
Flipping a live route to 402 without notice. Moving an existing endpoint into the pricing table breaks non-x402 clients calling it. Treat it as a breaking change: new path, deprecation, notice.
Gating discovery. Keep capabilities and health routes out of the pricing table so callers can evaluate the API without paying. Charging to discover loses callers.
One price for different work. The table keys on route, so put services that should cost differently on different paths rather than forcing one price on a shared route.
What to ship today
Mount the adapter, price one new route, and confirm an unpaid call gets the right 402 while a paid call runs and your existing routes are untouched. Then decide which established routes, if any, to migrate behind the paywall, and roll those out as breaking changes. For the MCP-specific version see how-to-add-payments-to-mcp-server; for pricing structure see how-to-charge-for-ai-agent-services. Pricing is on the pricing page.