Selling as a Coinbase Business? You can accept x402 payments without running your own server or facilitator — checkouts created with the Business Checkouts API return an
x402_url that agents can pay directly. See Accept agentic payments with x402.This quickstart begins with testnet configuration for safe testing. When
you’re ready for production, see Running on Mainnet for
the simple changes needed to accept real payments on Base (EVM), Polygon,
Arbitrum, World, and Solana networks.
Need help? Join the x402 Discord for the latest
updates.
Facilitator URLs
We recommend the CDP facilitator for both testnet and mainnet—it supports all networks with a generous free tier. The examples below use the x402.org facilitator for a signup-free quick start; see Running on Mainnet to switch to CDP.
Prerequisites
Before you begin, ensure you have:- A crypto wallet to receive funds (any EVM-compatible wallet, e.g., CDP Wallet)
- A Coinbase Developer Platform (CDP) account and API keys (recommended for production; examples below use x402.org for signup-free testing)
- Node.js and npm, Go, or Python and pip installed
- An existing API or server
- For testnet: Base Sepolia ETH for gas and testnet USDC for payments. Get funds from the CDP Faucet
We have pre-configured examples available in our repo for both
Node.js
and Go. We
also have an advanced
example
that shows how to use the x402 SDKs to build a more complex payment flow.
1. Install Dependencies
- Node.js
- Go
- Python
- Express
- Next.js
- Hono
Install the CDP SDK with the x402 peer packages and the Express middleware:
The
@x402/* packages are optional peer dependencies of @coinbase/cdp-sdk, so you
install them explicitly. See x402 in the CDP SDK.2. Add Payment Middleware
Integrate the payment middleware into your application. You will need to provide:- The Facilitator URL or facilitator client. We recommend CDP for both testnet and mainnet (see Running on Mainnet). The examples below use
https://x402.org/facilitatorfor a quick test without signup. - The routes you want to protect
- Your receiving wallet address
- Node.js
- Go
- Python
The tabs below use the CDP SDK:
createX402Server provisions a
receiver wallet, wires the CDP hosted facilitator, and registers schemes and extensions in one
call, so you don’t manage a facilitator URL, a payTo address, or scheme registration by hand.
Set CDP_API_KEY_ID, CDP_API_KEY_SECRET, and CDP_WALLET_SECRET in your environment first.
Already have an x402ResourceServer? Drop in createCdpFacilitatorClient() instead. See
Already have an x402 server? below.- Express
- Next.js
- Hono
Full example in the repo here.
Ready to accept real payments? See Running on Mainnet
for production setup.
Route Configuration Interface
Route configs are defined as a map where each key is a route pattern string (e.g.,"GET /weather", "GET /articles/:slug", "GET /api/*") and the value is a RouteConfig object:
Already have an x402 server?
If you already run anx402ResourceServer (or call a framework’s paymentMiddleware manually) and just want CDP settlement, drop in the CDP facilitator — createCdpFacilitatorClient() returns a standard HTTPFacilitatorClient, so it’s a one-line swap with no other changes. It only needs CDP_API_KEY_ID and CDP_API_KEY_SECRET. Full example in the repo here (run with APPROACH=1).
Dynamic Route Patterns
Route keys support dynamic path segments, letting a single route configuration match multiple URLs. Three pattern styles are supported:
If no HTTP method is specified in the key, the route matches all HTTP methods.
- Node.js (Express)
- Next.js
- Go (Gin)
- Python (FastAPI)
- Python (Flask)
Route consolidation for high-cardinality path segments: Bazaar automatically normalizes route URLs where a path segment consists entirely of a UUID, Ethereum address, Ethereum transaction hash, Solana address, or Solana transaction hash. Those segments are replaced with a generic route template parameter, and all matching URLs are consolidated into a single Bazaar entry — for example,
/data/0xabc...def/report and /data/0x123...456/report appear as one entry instead of two.To keep each URL as a distinct Bazaar entry, prefix or suffix the path segment so it is not a bare identifier. For example, use /user-<uuid> or /<uuid>-report instead of /<uuid>.Payment Schemes: Exact, Upto, and Batch-Settlement
x402 supports three payment schemes that control how charges are calculated:exact (default) — The client pays the exact advertised price. This is the simplest scheme and works across all networks (EVM, SVM) and all SDKs (TypeScript, Go, Python). Best for fixed-price endpoints where the cost is known upfront.
upto — The client authorizes a maximum amount, but the server settles only what was actually used. This enables usage-based billing where the final charge depends on work performed (LLM token count, compute time, bytes served, etc.). Currently available on EVM networks only, in TypeScript, Go, and Python SDKs.
batch-settlement — The client opens an on-chain payment channel with an initial deposit; subsequent requests are settled as signed off-chain vouchers with no on-chain transaction per request. The server’s ChannelManager periodically batches voucher claims into a single on-chain settlement, minimizing gas costs. Best for high-frequency sessions or streaming use cases where clients make many requests — the on-chain cost amortizes across the whole session. Like upto, the server can settle a fraction of the authorized amount per request. Currently available on EVM networks only.
The examples in step 2 above all use the exact scheme. To use upto instead, there are two key differences:
- Set
scheme: "upto"in your route config, wherepricebecomes the maximum the client authorizes - Call
setSettlementOverridesin your handler to specify the actual amount to charge
With the CDP SDK, set
scheme: "upto" on a createX402Server route —
it registers exact + upto for EVM automatically. setSettlementOverrides (shown below) works the
same on the returned X402Server since it extends x402HTTPResourceServer. createX402Server does
not offer batch-settlement; use the vanilla resource server shown below to gate a route with it. See
the Express upto example
(the GET /usage route, run with APPROACH=2).- Node.js (Express)
- Go (Gin)
- Python (FastAPI)
- Python (Flask)
setSettlementOverrides amount supports three formats:
- Raw atomic units — e.g.,
"1000"settles exactly 1,000 atomic units of the token (for USDC with 6 decimals,"1000"= $0.001) - Percentage of authorized maximum — e.g.,
"50%"settles 50% of the authorized amount. Supports up to two decimal places (e.g.,"33.33%"). The result is floored to the nearest atomic unit. - Dollar price — e.g.,
"$0.05"converts a USD-denominated price to atomic units. This format works when you configured your route with$-prefixed pricing (e.g.,price: "$0.10").
"0", no on-chain transaction occurs and the client is not charged.
The
upto scheme is currently available on EVM networks only, in the TypeScript, Go, and Python SDKs.batch-settlement
Unlike exact and upto — where each request results in an on-chain transaction — batch-settlement uses payment channels. The client makes one on-chain deposit upfront; every subsequent request in the session is a signed off-chain voucher. The server’s ChannelManager periodically batches those vouchers into a single on-chain claim and settlement, so gas costs are amortized across the whole session.
To use batch-settlement, there are three key differences from exact or upto:
- Set
scheme: "batch-settlement"in your route config - Initialize and start a
ChannelManagerto run background claim, settle, and refund cycles - Optionally call
setSettlementOverridesto bill a fraction of the authorized amount per request (same formats asupto: raw atomic units, percentages, or$-prefixed prices)
- Node.js (Express)
- Go (Gin)
- Python (FastAPI)
The
batch-settlement scheme is currently available on EVM networks only, in the TypeScript, Go, and Python SDKs. The client’s first request opens a payment channel with an on-chain deposit; subsequent requests in the same session are gasless off-chain vouchers. Clients can cooperatively refund any unused channel balance at any time.3. Test Your Integration
To verify:- Make a request to your endpoint (e.g.,
curl http://localhost:4021/weather). - The server responds with a 402 Payment Required, including payment instructions in the
PAYMENT-REQUIREDheader. - Complete the payment using a compatible client, wallet, or automated agent. This typically involves signing a payment payload, which is handled by the client SDK detailed in the Quickstart for Buyers.
- Retry the request, this time including the
PAYMENT-SIGNATUREheader containing the cryptographic proof of payment. - The server verifies the payment via the facilitator and, if valid, returns your actual API response (e.g.,
{ "data": "Your paid API response." }).
4. Enhance Discovery with Metadata (Recommended)
When using the CDP facilitator, your endpoints can be listed in the x402 Bazaar, our discovery layer that helps buyers and AI agents find services. To enable discovery and improve visibility:How Bazaar indexes your resource: When the CDP Bazaar crawls your endpoint
for discovery, it sends a request with the input defined by your Bazaar extension,
falling back to an empty request if the input isn’t defined or fails to parse.
Your server must respond with a
402 Payment Required status to this request,
confirming the resource is x402-enabled. If your server returns any other status
code (e.g. 400 Bad Request), the resource will not be indexed and will
not appear in Bazaar search results. It is best practice to ensure bazaar.info.input
is populated with a correctly configured request, avoiding common high-level
checks for empty requests. Other discovery layers or bazaars may use a different
indexing mechanism.After a buyer pays, the payment payload your server sends to the CDP facilitator
must include paymentPayload.resource for this endpoint. Bazaar uses that value
to associate the successful settlement with the resource to index.createX402Server auto-injects a bazaar extension on every route, so your endpoints are discoverable by default. To supply richer metadata, build the override with declareDiscoveryExtension from @x402/extensions/bazaar and spread it into the route’s extensions:
x402ResourceServer):
5. Integrate Base Builder Codes (Optional)
If you’re building on Base, integrate a Base Builder Code to get attributed for x402 transactions your endpoint serves. Paste this into Claude Code, Cursor, Codex, or any coding agent:6. Accept Any ERC-20 Token with Permit2 (Optional, EVM)
By default, the quickstart above uses USDC via EIP-3009 (Transfer With Authorization), which requires no on-chain approval from buyers. To accept any ERC-20 token, you can use Permit2 as the transfer method.The official TypeScript, Go, and Python SDKs all have built-in support for both EIP-3009 and Permit2.
How It Works
- Set
extra.assetTransferMethod: "permit2"in your route’s price configuration - Optionally declare a gas sponsorship extension so the facilitator can sponsor the buyer’s one-time Permit2 approval on-chain (no gas cost to the buyer)
- Without gas sponsorship, buyers must manually approve the Permit2 contract before their first payment
Gas Sponsorship Extensions
Gas sponsorship extensions require facilitator support. Before declaring a gas sponsorship extension on your endpoint, verify that your facilitator supports it by calling its/supported endpoint and inspecting the extensions property in the response. Look for:
eip2612-gas-sponsoring— indicates EIP-2612 gas sponsorship supporterc20-approval-gas-sponsoring— indicates ERC-20 approval gas sponsorship support
With the CDP SDK,
createX402Server auto-injects both gas-sponsoring
extensions on every EVM route (the CDP facilitator supports them), so you don’t declare them by hand.
The manual declarations below apply when you build an x402ResourceServer yourself.Example: Permit2 with EIP-2612 Gas Sponsoring (e.g., USDC)
For tokens that support EIP-2612 (like USDC), declare the EIP-2612 gas sponsoring extension. The facilitator uses a signedpermit() to approve Permit2 on the buyer’s behalf — fully gasless for the buyer.
- Node.js
- Go
- Python
Example: Permit2 with ERC-20 Gas Sponsoring (Generic Token)
For tokens that do not support EIP-2612, use the ERC-20 approval gas sponsoring extension. The facilitator broadcasts a pre-signedapprove() transaction on the buyer’s behalf.
- Node.js
- Go
- Python
For full details on EVM transfer methods and gas sponsorship, see Network Support.
7. Error Handling
- If you run into trouble, check out the examples in the repo for more context and full code.
- Run
npm installorgo mod tidyto install dependencies
Running on Mainnet
Once you’ve tested your integration on testnet, you’re ready to accept real payments on mainnet.Setting Up CDP Facilitator for Production
CDP’s facilitator provides enterprise-grade payment processing with compliance features:1. Set up CDP API Keys
To use the mainnet facilitator, you’ll need a Coinbase Developer Platform account:- Sign up at cdp.coinbase.com
- Create a new project
- Generate API credentials
- Set the following environment variables:
2. Update Your Code
Replace the testnet configuration with mainnet settings:- Node.js
- Go
- Python (FastAPI)
- Python (Flask)
With the CDP SDK, drop
environment: "development" (production is the default: Base mainnet +
Solana mainnet, settled through the CDP facilitator). To restrict a route to specific networks,
set networks with CAIP-2 identifiers. This is the same createX402Server call as the
Express example
(run with APPROACH=2), which already defaults to these networks:3. Update Your Wallet
Make sure your receiving wallet address is a real mainnet address where you want to receive USDC payments.4. Test with Real Payments
Before going live:- Test with small amounts first
- Verify payments are arriving in your wallet
- Monitor the facilitator for any issues
Using Different Networks
CDP facilitator supports multiple networks. Simply change the network parameter using CAIP-2 format:- Base Network
- Polygon Network
- Solana Network
- Multi-Network
Need support for additional networks like Avalanche? You can run your own
facilitator or contact CDP support to request new network additions.
Network Identifiers (CAIP-2)
x402 v2 uses CAIP-2 format for network identifiers:
See Network Support for the full list.
Next Steps
- Learn what the CDP SDK adds for TypeScript in x402 in the CDP SDK
- Looking for something more advanced? Check out the Advanced Example
- Get started as a buyer
- Learn about the Bazaar discovery layer
Summary
This quickstart covered:- Installing the x402 SDK and relevant middleware
- Adding payment middleware to your API and configuring it with static and dynamic route patterns
- Choosing between
exact(fixed-price),upto(usage-based), andbatch-settlement(payment channels for high-frequency sessions) payment schemes - Testing your integration
- Deploying to mainnet with CAIP-2 network identifiers