Source: https://docs.x402.org/core-concepts/bazaar-discovery-layer
The x402 Bazaar is the discovery layer for the x402 ecosystem - a machine-readable catalog that helps developers and AI agents find and integrate with x402-compatible API endpoints.
Think of it as a search index for payable APIs, enabling the autonomous discovery and consumption of services.
The x402 Bazaar is in early development. While our vision is to build the "Google for agentic endpoints," we're currently more like "Yahoo search" - functional but evolving. Features and APIs may change as we gather feedback and expand capabilities.
The Bazaar solves a critical problem in the x402 ecosystem: discoverability. Without it, x402-compatible endpoints are like hidden stalls in a vast market. The Bazaar provides:
- For Buyers (API Consumers): Programmatically discover available x402-enabled services, understand their capabilities, pricing, and schemas
- For Sellers (API Providers): Automatic visibility for your x402-enabled services to a global audience of developers and AI agents
- For AI Agents: Dynamic service discovery without pre-baked integrations - query, find, pay, and use
The Bazaar currently provides a simple /list endpoint that returns all x402-compatible services
registered with the CDP facilitator. Services are automatically opted-in when they use the CDP
facilitator and enable the bazaar extension, making discovery frictionless for sellers.
Note: While a discovery layer is live today for the CDP Facilitator, the spec for the marketplace items is open and part of the x402 scheme, meaning any facilitator can create their own discovery layer.
- Discovery: Clients query the
/listendpoint to find available services - Selection: Choose a service based on price, capabilities, and requirements
- Execution: Use x402 to pay for and access the selected service
- No Manual Setup: No API keys, no account creation, just discover and pay
Retrieve all available x402-compatible endpoints:
GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/resourcesNote: The recommended way to use this endpoint is to use the useFacilitator hook as described
below.
Response Schema
Each endpoint in the list contains the following fields:
{
"accepts": [
{
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"description": "",
"extra": {
"name": "USD Coin",
"version": "2"
},
"maxAmountRequired": "200",
"maxTimeoutSeconds": 60,
"mimeType": "",
"network": "eip155:8453",
"outputSchema": {
"input": {
"method": "GET",
"type": "http"
},
"output": null
},
"payTo": "0xa2477E16dCB42E2AD80f03FE97D7F1a1646cd1c0",
"resource": "https://api.example.com/x402/weather",
"scheme": "exact"
}
],
"lastUpdated": "2025-08-09T01:07:04.005Z",
"metadata": {},
"resource": "https://api.example.com/x402/weather",
"type": "http",
"x402Version": 2
}See the full example here for Python and Node.js.
Fetch the list of available x402 services using the facilitator client:
```typescript theme={null} import { HTTPFacilitatorClient } from "@x402/core/http"; import { withBazaar } from "@x402/extensions";const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const client = withBazaar(facilitatorClient);
const response = await client.extensions.discovery.listResources({ type: "http" });
// Filter services under $0.10
const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals)
const affordableServices = response.items.filter(item =>
item.accepts.find(paymentRequirements =>
paymentRequirements.asset === usdcAsset &&
Number(paymentRequirements.maxAmountRequired) < maxPrice
)
);
```
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)
response = await facilitator.list_resources(type="http")
# Filter services under $0.10
usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
max_price = 100000 # $0.10 in USDC atomic units (6 decimals)
affordable_services = [
item
for item in response.items
if any(
payment_req.asset == usdc_asset
and int(payment_req.max_amount_required) < max_price
for payment_req in item.accepts
)
]
```
Once you've found a suitable service, use an x402 client to call it:
```typescript theme={null} import { wrapAxiosWithPayment, x402Client } from "@x402/axios"; import { registerExactEvmScheme } from "@x402/evm/exact/client"; import axios from "axios"; import { privateKeyToAccount } from "viem/accounts";// Set up your payment account
const account = privateKeyToAccount("0xYourPrivateKey");
const client = new x402Client();
registerExactEvmScheme(client, { signer: account });
// Select a service from discovery
const selectedService = affordableServices[0];
// Create a payment-enabled client for that service
const api = wrapAxiosWithPayment(
axios.create({ baseURL: selectedService.resource }),
client
);
// Select the payment method of your choice
const selectedPaymentRequirements = selectedService.accepts[0];
const inputSchema = selectedPaymentRequirements.outputSchema.input;
// Build the request using the service's schema
const response = await api.request({
method: inputSchema.method,
url: inputSchema.resource,
params: { location: "San Francisco" } // Based on inputSchema
});
console.log("Response data:", response.data);
```
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
async def main() -> None:
account = Account.from_key("0xYourPrivateKey")
client = x402Client()
register_exact_evm_client(client, EthAccountSigner(account))
# Select a service from discovery (from Step 1)
selected_service = affordable_services[0]
# Select the payment method of your choice
selected_payment_requirements = selected_service.accepts[0]
input_schema = selected_payment_requirements.output_schema.input
# Make the request using httpx client
async with x402HttpxClient(client) as http:
response = await http.request(
method=input_schema.method,
url=input_schema.resource,
params={"location": "San Francisco"} # Based on input_schema
)
await response.aread()
print(f"Response data: {response.json()}")
asyncio.run(main())
```
If your API uses the CDP facilitator for x402 payments, it's automatically listed in the bazaar
when you enable the bazaar extension with discoverable: true.
To enhance your listing with descriptions and schemas, include them when setting up your x402 middleware. You should include descriptions for each parameter to make it clear for agents to call your endpoints:
```typescript theme={null} import { paymentMiddleware } from "@x402/express"; import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { registerExactEvmScheme } from "@x402/evm/exact/server"; import { bazaarResourceServerExtension } from "@x402/extensions";const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
const routes = {
"GET /weather": {
price: "$0.001",
network: "eip155:8453",
resource: "0xYourAddress",
description: "Get current weather data for any location",
extensions: {
bazaar: {
discoverable: true,
inputSchema: {
queryParams: {
location: {
type: "string",
description: "City name or coordinates",
required: true
}
}
},
outputSchema: {
type: "object",
properties: {
temperature: { type: "number" },
conditions: { type: "string" },
humidity: { type: "number" }
}
}
}
}
}
};
app.use(paymentMiddleware(routes, server));
```
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer
app = FastAPI()
# Create facilitator client (CDP mainnet)
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)
# Create resource server and register EVM scheme
server = x402ResourceServer(facilitator)
server.register("eip155:8453", ExactEvmServerScheme())
# Define routes with Bazaar discovery metadata
routes: dict[str, RouteConfig] = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to="0xYourAddress",
price="$0.001",
network="eip155:8453",
),
],
mime_type="application/json",
description="Get current weather data for any location",
extensions={
"bazaar": {
"discoverable": True,
"inputSchema": {
"queryParams": {
"location": {
"type": "string",
"description": "City name or coordinates",
"required": True,
}
}
},
"outputSchema": {
"type": "object",
"properties": {
"temperature": {"type": "number"},
"conditions": {"type": "string"},
"humidity": {"type": "number"},
},
},
}
},
),
}
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
```
import (
x402 "github.com/coinbase/x402/go"
"github.com/coinbase/x402/go/extensions/bazaar"
"github.com/coinbase/x402/go/extensions/types"
x402http "github.com/coinbase/x402/go/http"
ginmw "github.com/coinbase/x402/go/http/gin"
evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "https://x402.org/facilitator",
})
// Create Bazaar Discovery Extension with input/output schemas
discoveryExtension, _ := bazaar.DeclareDiscoveryExtension(
bazaar.MethodGET,
map[string]interface{}{"location": "San Francisco"},
types.JSONSchema{
"properties": map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "City name or coordinates",
},
},
"required": []string{"location"},
},
"",
&types.OutputConfig{
Schema: types.JSONSchema{
"properties": map[string]interface{}{
"temperature": map[string]interface{}{"type": "number"},
"conditions": map[string]interface{}{"type": "string"},
"humidity": map[string]interface{}{"type": "number"},
},
},
},
)
routes := x402http.RoutesConfig{
"GET /weather": {
Accepts: x402http.PaymentOptions{{
Scheme: "exact",
PayTo: "0xYourAddress",
Price: "$0.001",
Network: x402.Network("eip155:8453"),
}},
Description: "Get current weather data for any location",
Extensions: map[string]interface{}{
types.BAZAAR: discoveryExtension,
},
},
}
r.Use(ginmw.X402Payment(ginmw.Config{
Routes: routes,
Facilitator: facilitatorClient,
Schemes: []ginmw.SchemeConfig{{
Network: x402.Network("eip155:8453"),
Server: evm.NewExactEvmScheme(),
}},
}))
r.GET("/weather", func(c *gin.Context) {
location := c.DefaultQuery("location", "San Francisco")
c.JSON(200, gin.H{
"location": location,
"temperature": 70,
"conditions": "sunny",
"humidity": 45,
})
})
r.Run(":4021")
}
```
The x402 Bazaar is rapidly evolving, and your feedback helps us prioritize features.
- GitHub: github.com/coinbase/x402
- Discord: Join #x402 channel
Q: How do I get my service listed? A: If you're using the CDP facilitator, your service is
listed once you enable the bazaar extension with discoverable: true.
Q: How can I make endpoint calls more accurate? A: Include descriptions clearly stating what each parameter does and how to call your endpoint, but do so as succinctly as possible.
Q: How does pricing work? A: Listing is free. Services set their own prices per API call, paid via x402.
Q: What networks are supported? A: Currently Base (eip155:8453) and Base Sepolia
(eip155:84532) with USDC payments.
Q: Can I list non-x402 services? A: No, only x402-compatible endpoints can be listed. See our Quickstart for Sellers to make your API x402-compatible.
Source: https://docs.x402.org/core-concepts/client-server
This page explains the roles and responsibilities of the client and server in the x402 protocol.
Understanding these roles is essential to designing, building, or integrating services that use x402 for programmatic payments.
Note
Client refers to the technical component making an HTTP request. In practice, this is often the
buyer of the resource.
Server refers to the technical component responding to the request. In practice, this is typically the seller of the resource
The client is the entity that initiates a request to access a paid resource.
Clients can include:
- Human-operated applications
- Autonomous agents
- Programmatic services acting on behalf of users or systems
- Initiate requests: Send an HTTP request to the resource server.
- Handle payment requirements: Read the
402 Payment Requiredresponse and extract payment details. - Prepare payment payload: Use the provided payment requirements to construct a valid payment payload.
- Resubmit request with payment: Retry the request with the
PAYMENT-SIGNATUREheader containing the signed payment payload.
Clients do not need to manage accounts, credentials, or session tokens beyond their crypto wallet. All interactions are stateless and occur over standard HTTP requests.
The server is the resource provider enforcing payment for access to its services.
Servers can include:
- API services
- Content providers
- Any HTTP-accessible resource requiring monetization
- Define payment requirements: Respond to unauthenticated requests with an HTTP
402 Payment Required, including all necessary payment details in the response body. - Verify payment payloads: Validate incoming payment payloads, either locally or by using a facilitator service.
- Settle transactions: Upon successful verification, submit the payment for settlement.
- Provide the resource: Once payment is confirmed, return the requested resource to the client.
Servers do not need to manage client identities or maintain session state. Verification and settlement are handled per request.
The typical flow between a client and a server in the x402 protocol is as follows:
- Client initiates request to the server for a paid resource.
- Server responds with
402 Payment Required, including the payment requirements in the response body. - Client prepares and submits a payment payload based on the provided requirements, including
it in the
PAYMENT-SIGNATUREheader (Base64-encoded). - Server verifies the payment payload, either locally or through a facilitator service.
- Server settles the payment and confirms transaction completion.
- Server responds with the requested resource, including a
PAYMENT-RESPONSEheader (Base64-encoded) with settlement confirmation, assuming payment was successful.
In the x402 protocol:
- The client requests resources and supplies the signed payment payload.
- The server enforces payment requirements, verifies transactions, and provides the resource upon successful payment.
This interaction is stateless, HTTP-native, and compatible with both human applications and automated agents.
Next, explore:
- Facilitator — how servers verify and settle payments
- HTTP 402 — how servers communicate payment requirements to clients
Source: https://docs.x402.org/core-concepts/facilitator
This page explains the role of the facilitator in the x402 protocol.
The facilitator is an optional but recommended service that simplifies the process of verifying and settling payments between clients (buyers) and servers (sellers).
The facilitator is a service that:
- Verifies payment payloads submitted by clients.
- Settles payments on the blockchain on behalf of servers.
By using a facilitator, servers do not need to maintain direct blockchain connectivity or implement payment verification logic themselves. This reduces operational complexity and ensures accurate, real-time validation of transactions.
- Verify payments: Confirm that the client's payment payload meets the server's declared payment requirements.
- Settle payments: Submit validated payments to the blockchain and monitor for confirmation.
- Provide responses: Return verification and settlement results to the server, allowing the server to decide whether to fulfill the client's request.
The facilitator does not hold funds or act as a custodian - it performs verification and execution of onchain transactions based on signed payloads provided by clients.
Using a facilitator provides:
- Reduced operational complexity: Servers do not need to interact directly with blockchain nodes.
- Protocol consistency: Standardized verification and settlement flows across services.
- Faster integration: Services can start accepting payments with minimal blockchain-specific development.
While it is possible to implement verification and settlement locally, using a facilitator accelerates adoption and ensures correct protocol behavior.
- Currently, CDP hosts a facilitator live on Base mainnet. For more information about getting started, see the CDP Docs.
- CDP's facilitator offers fee-free settlement on Base and Solana (any EIP-3009 token on Base; any SPL token on Solana, plus Token-2022 for v2)
- PayAI hosts a facilitator on Solana, Base, Polygon, and more. More info & docs at https://docs.payai.network/x402.
Clientmakes an HTTP request to aresource serverResource serverresponds with a402 Payment Requiredstatus and aPayment Required ResponseJSON object in the response body.Clientselects one of thepaymentDetailsreturned by theacceptsfield of the server response and creates aPayment Payloadbased on theschemeof thepaymentDetailsthey have selected.Clientsends the HTTP request with thePAYMENT-SIGNATUREheader containing thePayment Payload(Base64-encoded) to theresource serverResource serververifies thePayment Payloadis valid either via local verification or by POSTing thePayment PayloadandPayment Detailsto the/verifyendpoint of thefacilitator server.Facilitator serverperforms verification of the object based on theschemeandnetworkIdof thePayment Payloadand returns aVerification Response- If the
Verification Responseis valid, the resource server performs the work to fulfill the request. If theVerification Responseis invalid, the resource server returns a402 Payment Requiredstatus and aPayment Required ResponseJSON object in the response body. Resource servereither settles the payment by interacting with a blockchain directly, or by POSTing thePayment PayloadandPayment Detailsto the/settleendpoint of thefacilitator server.Facilitator serversubmits the payment to the blockchain based on theschemeandnetworkIdof thePayment Payload.Facilitator serverwaits for the payment to be confirmed on the blockchain.Facilitator serverreturns aPayment Execution Responseto the resource server.Resource serverreturns a200 OKresponse to theClientwith the resource they requested as the body of the HTTP response, and aPAYMENT-RESPONSEheader containing theSettlement Responseas Base64-encoded JSON if the payment was executed successfully.
The facilitator acts as an independent verification and settlement layer within the x402 protocol. It helps servers confirm payments and submit transactions onchain without requiring direct blockchain infrastructure.
Next, explore:
- Client / Server — understand the roles and responsibilities of clients and servers
- HTTP 402 — understand how payment requirements are communicated to clients
Source: https://docs.x402.org/core-concepts/http-402
For decades, HTTP 402 Payment Required has been reserved for future use. x402 unlocks it, and absolves the internet of its original sin.
HTTP 402 is a standard, but rarely used, HTTP response status code indicating that payment is required to access a resource.
In x402, this status code is activated to:
- Inform clients (buyers or agents) that payment is required.
- Communicate the details of the payment, such as amount, currency, and destination address.
- Provide the information necessary to complete the payment programmatically.
The primary purpose of HTTP 402 is to enable frictionless, API-native payments for accessing web resources, especially for:
- Machine-to-machine (M2M) payments (e.g., AI agents).
- Pay-per-use models such as API calls or paywalled content.
- Micropayments without account creation or traditional payment rails.
Using the 402 status code keeps x402 protocol natively web-compatible and easy to integrate into any HTTP-based service.
x402 V2 uses two standardized headers for payment communication:
PAYMENT-SIGNATURE: Contains the Base64-encoded payment payload from the client. This header is sent by the client when retrying a request after receiving a 402 response, proving they have authorized payment.PAYMENT-RESPONSE: Contains the Base64-encoded settlement response from the server. This header is returned by the server in the successful response, confirming the payment was verified and settled.
Both headers must contain valid Base64-encoded JSON strings. This encoding ensures compatibility across different HTTP implementations and prevents issues with special characters in JSON payloads.
HTTP 402 is the foundation of the x402 protocol, enabling services to declare payment requirements directly within HTTP responses. It:
- Signals payment is required
- Communicates necessary payment details
- Integrates seamlessly with standard HTTP workflows
Source: https://docs.x402.org/core-concepts/network-and-token-support
This page explains which blockchain networks and tokens are supported by x402, and how to extend support to additional networks.
x402 V2 uses CAIP-2 standard network identifiers for
unambiguous cross-chain support. This format follows the pattern namespace:reference.
| V1 Name | V2 CAIP-2 ID | Chain ID | Description |
|---|---|---|---|
base-sepolia |
eip155:84532 |
84532 | Base Sepolia testnet |
base |
eip155:8453 |
8453 | Base mainnet |
solana-devnet |
solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
- | Solana Devnet |
solana |
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
- | Solana Mainnet |
- EVM networks:
eip155:<chainId>where chainId is the numeric chain identifier - Solana:
solana:<genesisHash>where genesisHash is the first 32 bytes of the genesis block hash
x402 is designed to work across multiple blockchain networks, with different levels of support depending on the facilitator being used. The protocol itself is network-agnostic, but facilitators need to implement network-specific logic for payment verification and settlement.
Network support in x402 depends on which facilitator you use. Here are the currently available facilitators:
- Supports:
eip155:84532(Base Sepolia),solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1(Solana Devnet) - Notes: Recommended for testing and development. This is the default facilitator in the x402 packages and requires no setup.
- Supports:
eip155:8453(Base),eip155:84532(Base Sepolia),solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp(Solana),solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1(Solana Devnet) - Notes: Production-ready for mainnet payments with KYT/OFAC compliance checks. Can also be used for testing on Base Sepolia. Requires CDP API keys. Uses facilitator object instead of facilitator URL.
- Requirements: CDP account and API keys from cdp.coinbase.com, see Quickstart for Sellers: Running on Mainnet for more details.
- Supports:
eip155:84532(Base Sepolia),eip155:8453(Base), XDC Mainnet - Notes: Rust-based facilitator operated by the x402 community.
- URL: https://facilitator.x402.rs
- Supports: Solana, Base, Polygon, Avalanche, Sei, Peaq, Iotex and all of their testnets.
- Notes: Production-ready for mainnet payments. Supports all tokens on Solana, supports EIP-3009 tokens on EVM-Based chains.
- URL: https://facilitator.payai.network
- Supports: Any EVM network
- Notes: Run your own facilitator for full control and customization. Supports networks like Avalanche, Polygon, Arbitrum, and other EVM-compatible chains.
- Setup: See "Adding Support for New Networks" section below
Additional facilitators may be available from external providers. Check the x402 Discord community for the latest facilitator offerings.
x402 supports tokens on both EVM and Solana networks:
- EVM: Any ERC-20 token that implements the EIP-3009 standard
- Solana: Any SPL or token-2022 token
Important: Facilitators support networks, not specific tokens — any EIP-3009 compatible token works on EVM networks, and any SPL/token-2022 token works on Solana, for the facilitators that support those networks.
Tokens must implement the transferWithAuthorization function from the EIP-3009 standard. This
enables:
- Gasless transfers: The facilitator sponsors gas fees
- Signature-based authorization: Users sign transfer authorizations off-chain
- Secure payments: Transfers are authorized by cryptographic signatures
When configuring payment requirements, you have two options:
- Price String (e.g.,
"$0.01") - The system infers USDC as the token - TokenAmount - Specify exact atomic units of any EIP-3009 token
To use a custom EIP-3009 token, you need three key pieces of information:
- Token Address: The contract address of your EIP-3009 token
- EIP-712 Name: The token's name for EIP-712 signatures
- EIP-712 Version: The token's version for EIP-712 signatures
Finding Token Information on Basescan
You can retrieve the required EIP-712 values from any block explorer:
- Name: Read the
name()function - Example on Basescan - Version: Read the
version()function - Example on Basescan
These values are used in the eip712 nested object when configuring TokenAmount:
{
eip712: {
name: "USD Coin", // From name() function
version: "2" // From version() function
}
}On Solana, x402 supports all SPL tokens and Token 2022 tokens. When using facilitators that support Solana or Solana Devnet, payments can be made in any SPL/token-2022 token, including USDC (SPL). No EIP-712 configuration is required on Solana.
- Status: Supported by default across all networks
- Why: USDC implements EIP-3009 and is widely available
- Networks: Available on
eip155:8453(Base),eip155:84532(Base Sepolia), and all supported networks
The EIP-3009 standard is essential for x402 because it enables:
- Gas abstraction: Buyers don't need native tokens (ETH, MATIC, etc.) for gas
- One-step payments: No separate approval transactions required
- Universal facilitator support: Any EIP-3009 token works with any facilitator
| Facilitator | Networks Supported (CAIP-2) | Production Ready | Requirements |
|---|---|---|---|
| x402.org | eip155:84532, solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
Testnet only | None |
| CDP Facilitator | eip155:8453, eip155:84532, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp, solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
Yes | CDP API keys |
| x402.rs | eip155:84532, eip155:8453, xdc |
Yes | None |
| PayAI Facilitator | solana, solana-devnet, base, base-sepolia, polygon, polygon-amoy, avalanche, avalanche-fuji, sei, sei-testnet, peaq, iotex | Yes | None |
| Self-hosted | Any EVM network (CAIP-2 format) | Yes | Technical setup |
Note: On EVM networks, facilitators support any EIP-3009 compatible token; on Solana, facilitators support any SPL/Token-2022 token.
x402 V2 uses dynamic network registration - you can support any EVM network without modifying source files.
In V2, networks are supported through the registration pattern using CAIP-2 identifiers. No source code changes are required:
```typescript theme={null} import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { registerExactEvmScheme } from "@x402/evm/exact/server";const facilitatorClient = new HTTPFacilitatorClient({
url: "https://your-facilitator.com" // Facilitator that supports your network
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server); // Registers wildcard support for all EVM chains
// Now use any CAIP-2 network identifier in your routes:
const routes = {
"GET /api/data": {
accepts: [{
scheme: "exact",
price: "$0.001",
network: "eip155:43114", // Avalanche mainnet
payTo: "0xYourAddress",
}],
},
};
```
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "https://your-facilitator.com",
})
// Register EVM scheme - supports any CAIP-2 EVM network
schemes := []ginmw.SchemeConfig{
{Network: x402.Network("eip155:43114"), Server: evm.NewExactEvmScheme()}, // Avalanche
}
```
# Create facilitator client for your network
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://your-facilitator.com")
)
# Create server and register EVM scheme for your network
server = x402ResourceServer(facilitator)
server.register("eip155:43114", ExactEvmServerScheme()) # Avalanche mainnet
# Now use any CAIP-2 network identifier in your routes:
routes: dict[str, RouteConfig] = {
"GET /api/data": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
price="$0.001",
network="eip155:43114", # Avalanche mainnet
pay_to="0xYourAddress",
),
],
),
}
```
Key Points:
- Use CAIP-2 format:
eip155:<chainId>for any EVM network - The scheme implementation handles the network automatically
- You only need a facilitator that supports your target network (or run your own)
If you need immediate support or want to test before contributing, you can run your own facilitator.
Video Guide: Adding EVM Chains to x402
Prerequisites
- Access to an RPC endpoint for your target network
- A wallet with native tokens for gas sponsorship
- The x402 facilitator code
The x402 ecosystem is actively expanding network support. Planned additions include:
- Additional L2 networks
- Additional non-EVM chain support
- Cross-chain payment capabilities
For help with network integration:
- Join the x402 Discord community
- Check the x402 GitHub repository
x402's network support is designed to be extensible while maintaining security and reliability.
Whether you're using the default Base Sepolia (eip155:84532) setup for testing or running your own
facilitator for custom networks, the protocol provides flexibility for various use cases.
Key takeaways:
- Base (
eip155:8453) and Base Sepolia (eip155:84532) have the best out-of-the-box support - Any EVM network can be supported with a custom facilitator using CAIP-2 format
- Any EIP-3009 token (with
transferWithAuthorization) works on any facilitator - Use price strings for USDC or TokenAmount for custom tokens
- Network choice affects gas costs and payment economics
- V2 uses CAIP-2 network identifiers for unambiguous cross-chain support
Next, explore:
- Quickstart for Sellers — Start accepting payments on supported networks
- Core Concepts — Learn how x402 works under the hood
- Facilitator — Understand the role of facilitators
- MCP Server — Set up AI agents to use x402 payments
Source: https://docs.x402.org/core-concepts/wallet
This page explains the role of the wallet in the x402 protocol.
In x402, a wallet is both a payment mechanism and a form of unique identity for buyers and sellers. Wallet addresses are used to send, receive, and verify payments, while also serving as identifiers within the protocol.
Buyers use wallets to:
- Store USDC/crypto
- Sign payment payloads
- Authorize onchain payments programmatically
Wallets enable buyers, including AI agents, to transact without account creation or credential management.
Sellers use wallets to:
- Receive USDC/crypto payments
- Define their payment destination within server configurations
A seller's wallet address is included in the payment requirements provided to buyers.
CDP's Wallet API is our recommended option for programmatic payments and secure key management.
- Wallets enable programmatic, permissionless payments in x402.
- Buyers use wallets to pay for services.
- Sellers use wallets to receive payments.
- Wallet addresses also act as unique identifiers within the protocol.
Source: https://docs.x402.org/faq
x402 is an open‑source protocol that turns the dormant HTTP 402 Payment Required status code into
a fully‑featured, on‑chain payment layer for APIs, websites, and autonomous agents.
Is x402 a CDP Product?
No. While Coinbase Developer Platform provides tooling and are the creators of the standard, it is an open protocol (Apache-2.0 license) and you don't need any Coinbase products to use it. We look forward to further clarifying this distinction and making x402 a credibly neutral payment standard.
Traditional rails require credit‑card networks, user accounts, and multi‑step UI flows.
x402 removes those dependencies, enabling programmatic, HTTP-native payments (perfect for AI agents)
while dropping fees to near‑zero and settling in ~1 second.
No. Any web API or content provider—crypto or web2—can integrate x402 if it wants a lower‑cost, friction‑free payment path for small or usage‑based transactions.
Typescript, Python, and Go are reference implementations, but x402 is an open protocol.
Nothing prevents you from implementing the spec in Rust, Java, or other languages. If you're interested in building support for your favorite language, please open an issue and let us know, we'd be happy to help!
Coinbase Developer Platform operates the first production facilitator. The protocol, however, is permissionless—anyone can run a facilitator. Expect:
- Community‑run facilitators for other networks or assets.
- Private facilitators for enterprises that need custom KYT / KYC flows.
Every x402PaymentPayload is signed by the buyer and settles directly on‑chain.
A facilitator that tampers with the transaction will fail signature checks.
There is no single answer, but common patterns are:
- Flat per‑call (e.g.,
$0.001per request) - Tiered (
/basicvs/proendpoints with different prices) - Up‑to (work in progress): "pay‑up‑to" where the final cost equals usage (tokens, MB, etc.)
Yes. x402 handles the payment execution. You can still meter usage, aggregate calls, or issue prepaid credits in Metronome and only charge when limits are exceeded. Example glue code is coming soon.
| Network | CAIP-2 ID | Asset | Fees* | Status |
|---|---|---|---|---|
| Base | eip155:8453 |
Any EIP-3009 token | fee-free | Mainnet |
| Base Sepolia | eip155:84532 |
Any EIP-3009 token | fee-free | Testnet |
| Solana | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
Any SPL token; Token-2022 (v2 only) | fee-free | Mainnet |
| Solana Devnet | solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
Any SPL token; Token-2022 (v2 only) | fee-free | Testnet |
* Gas paid on chain; Coinbase's x402 facilitator adds zero facilitator fee.
Support for additional chains and assets is on the roadmap and community‑driven.
Not natively. However, facilitators or third‑party gateways can wrap x402 flows with on‑ and off‑ramps.
No. The recommended pattern is:
- Buyers (clients/agents) sign locally in their runtime (browser, serverless, agent VM). You can use CDP Wallet API to create a programmatic wallet.
- Sellers never hold the buyer's key; they only verify signatures.
The current exact scheme is a push payment—irreversible once executed. Two options:
- Business‑logic refunds: Seller sends a new USDC transfer back to the buyer.
- Escrow schemes: Future spec could add conditional transfers (e.g., HTLCs or hold invoices).
Agents follow the same flow as humans:
- Make a request.
- Parse the
PAYMENT-REQUIREDheader. - Choose a suitable requirement and sign a payload via the x402 client SDKs.
- Retry with the
PAYMENT-SIGNATUREheader.
Yes. Programmatic wallets (e.g., CDP Wallet API, viem, ethers‑v6 HD wallets) let agents
sign EIP‑712 payloads without exposing seed phrases.
Tracked in public GitHub issues + community RFCs. Major themes:
- Multi‑asset support
- Additional schemes (
upto,stream,permit2) - Discovery layer for service search & reputation
Why is x402 hosted in the Coinbase GitHub?
We acknowledge that the repo is primarily under Coinbase ownership today. This is primarily to leverage our best-in-house security and auditing team to ensure the spec is safe and nobody accidentally creates legally ambiguous payment flows. We intend to eventually transfer ownership of the repo to a steering group or open-source committee.
- Signature is invalid (wrong chain ID or payload fields).
- Payment amount is less than the required
amountin the payment requirements. - Address has insufficient USDC or was flagged by KYT.
Check theerrorfield in the server's JSON response for details.
- Ensure you set
network: "eip155:8453"(Base mainnet) instead of"eip155:84532"(Base Sepolia). - Confirm your wallet has mainnet USDC.
- Gas fees are higher on mainnet; fund the wallet with a small amount of ETH for gas.
• Reach out in the Discord channel
• Open a GitHub Discussion or Issue in the x402 repo
Source: https://docs.x402.org/getting-started/quickstart-for-buyers
This guide walks you through how to use x402 to interact with services that require payment. By the end of this guide, you will be able to programmatically discover payment requirements, complete a payment, and access a paid resource.
Before you begin, ensure you have:
- A crypto wallet with USDC (any EVM-compatible wallet)
- Node.js and npm, Go, or Python and pip
- A service that requires payment via x402
Note
We have pre-configured
examples available in our repo, including
examples for fetch, Axios, Go, and MCP.
```bash theme={null}
# For fetch-based clients
npm install @x402/fetch @x402/evm
# For axios-based clients
npm install @x402/axios @x402/evm
# For Solana support, also add:
npm install @x402/svm
```
```bash theme={null}
go get github.com/coinbase/x402/go
```
```bash theme={null}
# For httpx (async) - recommended
pip install "x402[httpx]"
# For requests (sync)
pip install "x402[requests]"
# For Solana support, also add:
pip install "x402[svm]"
```
```bash theme={null}
npm install viem
```
Then instantiate the wallet signer:
```typescript theme={null}
import { privateKeyToAccount } from "viem/accounts";
// Create a signer from private key (use environment variable)
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
```
// Load private key from environment
evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY"))
if err != nil {
log.Fatal(err)
}
```
```bash theme={null}
pip install eth_account
```
Then instantiate the wallet signer:
```python theme={null}
import os
from eth_account import Account
from x402.mechanisms.evm import EthAccountSigner
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
signer = EthAccountSigner(account)
```
Use SolanaKit to instantiate a signer:
import { createKeyPairSignerFromBytes } from '@solana/kit';
import { base58 } from '@scure/base';
// 64-byte base58 secret key (private + public)
const svmSigner = await createKeyPairSignerFromBytes(
base58.decode(process.env.SOLANA_PRIVATE_KEY!)
);```typescript theme={null}
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client, x402HTTPClient } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// Create signer
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
// Create x402 client and register EVM scheme
const client = new x402Client();
registerExactEvmScheme(client, { signer });
// Wrap fetch with payment handling
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// Make request - payment is handled automatically
const response = await fetchWithPayment("https://api.example.com/paid-endpoint", {
method: "GET",
});
const data = await response.json();
console.log("Response:", data);
// Get payment receipt from response headers
if (response.ok) {
const httpClient = new x402HTTPClient(client);
const paymentResponse = httpClient.getPaymentSettleResponse(
(name) => response.headers.get(name)
);
console.log("Payment settled:", paymentResponse);
}
```
```typescript theme={null}
import { x402Client, wrapAxiosWithPayment, x402HTTPClient } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import axios from "axios";
// Create signer
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
// Create x402 client and register EVM scheme
const client = new x402Client();
registerExactEvmScheme(client, { signer });
// Create an Axios instance with payment handling
const api = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.example.com" }),
client,
);
// Make request - payment is handled automatically
const response = await api.get("/paid-endpoint");
console.log("Response:", response.data);
// Get payment receipt
const httpClient = new x402HTTPClient(client);
const paymentResponse = httpClient.getPaymentSettleResponse(
(name) => response.headers[name.toLowerCase()]
);
console.log("Payment settled:", paymentResponse);
```
```go theme={null}
package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
x402 "github.com/coinbase/x402/go"
x402http "github.com/coinbase/x402/go/http"
evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client"
evmsigners "github.com/coinbase/x402/go/signers/evm"
)
func main() {
url := "http://localhost:4021/weather"
// Create EVM signer
evmSigner, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY"))
// Create x402 client and register EVM scheme
x402Client := x402.Newx402Client().
Register("eip155:*", evm.NewExactEvmScheme(evmSigner))
// Wrap HTTP client with payment handling
httpClient := x402http.WrapHTTPClientWithPayment(
http.DefaultClient,
x402http.Newx402HTTPClient(x402Client),
)
// Make request - payment is handled automatically
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := httpClient.Do(req)
if err != nil {
fmt.Printf("Request failed: %v\n", err)
return
}
defer resp.Body.Close()
// Read response
var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)
fmt.Printf("Response: %+v\n", data)
// Check payment response header
paymentHeader := resp.Header.Get("PAYMENT-RESPONSE")
if paymentHeader != "" {
fmt.Println("Payment settled successfully!")
}
}
```
[Full HTTPX example](https://github.com/coinbase/x402/tree/main/examples/python/clients/httpx) | [Full Requests example](https://github.com/coinbase/x402/tree/main/examples/python/clients/requests)
```python theme={null}
import asyncio
import os
from eth_account import Account
from x402 import x402Client
from x402.http import x402HTTPClient
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
async def main() -> None:
client = x402Client()
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
http_client = x402HTTPClient(client)
async with x402HttpxClient(client) as http:
response = await http.get("https://api.example.com/paid-endpoint")
await response.aread()
print(f"Response: {response.text}")
if response.is_success:
settle_response = http_client.get_payment_settle_response(
lambda name: response.headers.get(name)
)
print(f"Payment settled: {settle_response}")
asyncio.run(main())
```
[Full Requests example](https://github.com/coinbase/x402/tree/main/examples/python/clients/requests)
```python theme={null}
import os
from eth_account import Account
from x402 import x402ClientSync
from x402.http import x402HTTPClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
def main() -> None:
client = x402ClientSync()
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
http_client = x402HTTPClientSync(client)
with x402_requests(client) as session:
response = session.get("https://api.example.com/paid-endpoint")
print(f"Response: {response.text}")
if response.ok:
settle_response = http_client.get_payment_settle_response(
lambda name: response.headers.get(name)
)
print(f"Payment settled: {settle_response}")
main()
```
You can register multiple payment schemes to handle different networks:
```typescript theme={null} import { wrapFetchWithPayment } from "@x402/fetch"; import { x402Client } from "@x402/core/client"; import { registerExactEvmScheme } from "@x402/evm/exact/client"; import { registerExactSvmScheme } from "@x402/svm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; import { createKeyPairSignerFromBytes } from "@solana/kit"; import { base58 } from "@scure/base";// Create signers
const evmSigner = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const svmSigner = await createKeyPairSignerFromBytes(
base58.decode(process.env.SOLANA_PRIVATE_KEY!)
);
// Create client with multiple schemes
const client = new x402Client();
registerExactEvmScheme(client, { signer: evmSigner });
registerExactSvmScheme(client, { signer: svmSigner });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// Now handles both EVM and Solana networks automatically!
```
// Create signers
evmSigner, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY"))
svmSigner, _ := svmsigners.NewClientSignerFromPrivateKey(os.Getenv("SVM_PRIVATE_KEY"))
// Create client with multiple schemes
x402Client := x402.Newx402Client().
Register("eip155:*", evm.NewExactEvmScheme(evmSigner)).
Register("solana:*", svm.NewExactSvmScheme(svmSigner))
// Wrap HTTP client with payment handling
httpClient := x402http.WrapHTTPClientWithPayment(
http.DefaultClient,
x402http.Newx402HTTPClient(x402Client),
)
// Now handles both EVM and Solana networks automatically!
```
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
from x402.mechanisms.svm import KeypairSigner
from x402.mechanisms.svm.exact.register import register_exact_svm_client
async def main() -> None:
client = x402Client()
# Register EVM scheme
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
# Register SVM scheme
svm_signer = KeypairSigner.from_base58(os.getenv("SVM_PRIVATE_KEY"))
register_exact_svm_client(client, svm_signer)
async with x402HttpxClient(client) as http:
response = await http.get("https://api.example.com/paid-endpoint")
print(f"Response: {response.text}")
asyncio.run(main())
```
Instead of hardcoding endpoints, you can use the x402 Bazaar to dynamically discover available services. This is especially powerful for building autonomous agents.
// Fetch available services from the Bazaar API
const response = await fetch('https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources');
const services = await response.json();
// Filter services by criteria
const affordableServices = services.items.filter(
(item) => item.accepts.some((req) => Number(req.amount) < 100000) // Under $0.10
);
console.log('Available services:', affordableServices);Learn more about service discovery in the Bazaar documentation.
Clients will throw errors if:
- No scheme is registered for the required network
- The request configuration is missing
- A payment has already been attempted for the request
- There is an error creating the payment header
Common error handling:
try {
const response = await fetchWithPayment(url, { method: 'GET' });
// Handle success
} catch (error) {
if (error.message.includes('No scheme registered')) {
console.error('Network not supported - register the appropriate scheme');
} else if (error.message.includes('Payment already attempted')) {
console.error('Payment failed on retry');
} else {
console.error('Request failed:', error);
}
}- Install x402 client packages (
@x402/fetchor@x402/axios) and mechanism packages (@x402/evm,@x402/svm) - Create a wallet signer
- Create an
x402Clientand register payment schemes - Use the provided wrapper/interceptor to make paid API requests
- (Optional) Use the x402 Bazaar to discover services dynamically
- Payment flows are handled automatically for you
References:
- @x402/fetch on npm
- @x402/axios on npm
- @x402/evm on npm
- x402 Go module
- x402 Bazaar documentation - Discover available services
For questions or support, join our Discord.
Source: https://docs.x402.org/getting-started/quickstart-for-sellers
This guide walks you through integrating with x402 to enable payments for your API or service. By the end, your API will be able to charge buyers and AI agents for access.
Note: 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) and Solana networks.
Before you begin, ensure you have:
- A crypto wallet to receive funds (any EVM-compatible wallet)
- Node.js and npm, Go, or Python and pip installed
- An existing API or server
Note
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.
```bash theme={null}
npm install @x402/express @x402/core @x402/evm
```
```bash theme={null}
npm install @x402/next @x402/core @x402/evm
```
```bash theme={null}
npm install @x402/hono @x402/core @x402/evm
```
```bash theme={null}
go get github.com/coinbase/x402/go
```
```bash theme={null}
pip install "x402[fastapi]"
# For Solana support, also add:
pip install "x402[svm]"
```
```bash theme={null}
pip install "x402[flask]"
# For Solana support, also add:
pip install "x402[svm]"
```
Integrate the payment middleware into your application. You will need to provide:
- The Facilitator URL or facilitator client. For testing, use
https://x402.org/facilitatorwhich works on Base Sepolia and Solana devnet.- For mainnet setup, see Running on Mainnet
- The routes you want to protect.
- Your receiving wallet address.
```typescript theme={null}
import express from "express";
import { paymentMiddleware } from "@x402/express";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const app = express();
// Your receiving wallet address
const payTo = "0xYourAddress";
// Create facilitator client (testnet)
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
// Create resource server and register EVM scheme
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001", // USDC amount in dollars
network: "eip155:84532", // Base Sepolia (CAIP-2 format)
payTo,
},
],
description: "Get current weather data for any location",
mimeType: "application/json",
},
},
server,
),
);
// Implement your route
app.get("/weather", (req, res) => {
res.send({
report: {
weather: "sunny",
temperature: 70,
},
});
});
app.listen(4021, () => {
console.log(`Server listening at http://localhost:4021`);
});
```
```typescript theme={null}
// middleware.ts
import { paymentProxy } from "@x402/next";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const payTo = "0xYourAddress";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
export const middleware = paymentProxy(
{
"/api/protected": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:84532",
payTo,
},
],
description: "Access to protected content",
mimeType: "application/json",
},
},
server,
);
export const config = {
matcher: ["/api/protected/:path*"],
};
```
```typescript theme={null}
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { paymentMiddleware } from "@x402/hono";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const app = new Hono();
const payTo = "0xYourAddress";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
paymentMiddleware(
{
"/protected-route": {
accepts: [
{
scheme: "exact",
price: "$0.10",
network: "eip155:84532",
payTo,
},
],
description: "Access to premium content",
mimeType: "application/json",
},
},
server,
),
);
app.get("/protected-route", (c) => {
return c.json({ message: "This content is behind a paywall" });
});
serve({ fetch: app.fetch, port: 3000 });
```
```go theme={null}
package main
import (
"net/http"
"time"
x402 "github.com/coinbase/x402/go"
x402http "github.com/coinbase/x402/go/http"
ginmw "github.com/coinbase/x402/go/http/gin"
evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server"
"github.com/gin-gonic/gin"
)
func main() {
payTo := "0xYourAddress"
network := x402.Network("eip155:84532") // Base Sepolia (CAIP-2 format)
r := gin.Default()
// Create facilitator client
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "https://x402.org/facilitator",
})
// Apply x402 payment middleware
r.Use(ginmw.X402Payment(ginmw.Config{
Routes: x402http.RoutesConfig{
"GET /weather": {
Accepts: x402http.PaymentOptions{
{
Scheme: "exact",
PayTo: payTo,
Price: "$0.001",
Network: network,
},
},
Description: "Get weather data for a city",
MimeType: "application/json",
},
},
Facilitator: facilitatorClient,
Schemes: []ginmw.SchemeConfig{
{Network: network, Server: evm.NewExactEvmScheme()},
},
SyncFacilitatorOnStart: true,
Timeout: 30 * time.Second,
}))
// Protected endpoint
r.GET("/weather", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"weather": "sunny",
"temperature": 70,
})
})
r.Run(":4021")
}
```
```python theme={null}
from typing import Any
from fastapi import FastAPI
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer
app = FastAPI()
# Your receiving wallet address
pay_to = "0xYourAddress"
# Create facilitator client (testnet)
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://x402.org/facilitator")
)
# Create resource server and register EVM scheme
server = x402ResourceServer(facilitator)
server.register("eip155:84532", ExactEvmServerScheme())
# Define protected routes
routes: dict[str, RouteConfig] = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to=pay_to,
price="$0.001", # USDC amount in dollars
network="eip155:84532", # Base Sepolia (CAIP-2 format)
),
],
mime_type="application/json",
description="Get current weather data for any location",
),
}
# Add payment middleware
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
@app.get("/weather")
async def get_weather() -> dict[str, Any]:
return {
"report": {
"weather": "sunny",
"temperature": 70,
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=4021)
```
```python theme={null}
from flask import Flask, jsonify
from x402.http import FacilitatorConfig, HTTPFacilitatorClientSync, PaymentOption
from x402.http.middleware.flask import payment_middleware
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServerSync
app = Flask(__name__)
pay_to = "0xYourAddress"
facilitator = HTTPFacilitatorClientSync(
FacilitatorConfig(url="https://x402.org/facilitator")
)
server = x402ResourceServerSync(facilitator)
server.register("eip155:84532", ExactEvmServerScheme())
routes: dict[str, RouteConfig] = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to=pay_to,
price="$0.001",
network="eip155:84532",
),
],
mime_type="application/json",
description="Get current weather data for any location",
),
}
payment_middleware(app, routes=routes, server=server)
@app.route("/weather")
def get_weather():
return jsonify({
"report": {
"weather": "sunny",
"temperature": 70,
}
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=4021)
```
Route Configuration Interface:
interface RouteConfig {
accepts: Array<{
scheme: string; // Payment scheme (e.g., "exact")
price: string; // Price in dollars (e.g., "$0.01")
network: string; // Network in CAIP-2 format (e.g., "eip155:84532")
payTo: string; // Your wallet address
}>;
description?: string; // Description of the resource
mimeType?: string; // MIME type of the response
extensions?: object; // Optional extensions (e.g., Bazaar)
}When a request is made to these routes without payment, your server will respond with the HTTP 402 Payment Required code and payment instructions.
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." }).
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:
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:8453",
payTo: "0xYourAddress",
},
],
description: "Get real-time weather data including temperature, conditions, and humidity",
mimeType: "application/json",
extensions: {
bazaar: {
discoverable: true,
category: "weather",
tags: ["forecast", "real-time"],
},
},
},
}Learn more about the discovery layer in the Bazaar documentation.
- 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
Once you've tested your integration on testnet, you're ready to accept real payments on mainnet.
For mainnet, use the CDP facilitator:
```typescript theme={null} const facilitatorClient = new HTTPFacilitatorClient({ url: "https://api.cdp.coinbase.com/platform/v2/x402" }); ``` ```go theme={null} facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ URL: "https://api.cdp.coinbase.com/platform/v2/x402", }) ``` ```python theme={null} from x402.http import FacilitatorConfig, HTTPFacilitatorClientfacilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)
```
facilitator = HTTPFacilitatorClientSync(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)
```
Change from testnet to mainnet network identifiers:
```typescript theme={null} // Testnet → Mainnet network: "eip155:8453", // Base mainnet (was eip155:84532) ``` ```typescript theme={null} // Testnet → Mainnet network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet// For Solana, use a Solana wallet address (base58 format)
payTo: "YourSolanaWalletAddress",
```
For multi-network support, register both EVM and SVM schemes:
```typescript theme={null} import { registerExactEvmScheme } from "@x402/evm/exact/server"; import { registerExactSvmScheme } from "@x402/svm/exact/server";const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
registerExactSvmScheme(server);
```
r.Use(ginmw.X402Payment(ginmw.Config{
// ...
Schemes: []ginmw.SchemeConfig{
{Network: x402.Network("eip155:8453"), Server: evm.NewExactEvmScheme()},
{Network: x402.Network("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"), Server: svm.NewExactSvmScheme()},
},
}))
```
server = x402ResourceServer(facilitator)
server.register("eip155:8453", ExactEvmServerScheme()) # Base mainnet
server.register("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", ExactSvmServerScheme()) # Solana mainnet
```
Make sure your receiving wallet address is a real mainnet address where you want to receive USDC payments.
Before going live:
- Test with small amounts first
- Verify payments are arriving in your wallet
- Monitor the facilitator for any issues
Warning: Mainnet transactions involve real money. Always test thoroughly on testnet first and start with small amounts on mainnet.
x402 v2 uses CAIP-2 format for network identifiers:
| Network | CAIP-2 Identifier |
|---|---|
| Base Mainnet | eip155:8453 |
| Base Sepolia | eip155:84532 |
| Solana Mainnet | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
| Solana Devnet | solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
See Network Support for the full list.
- Looking for something more advanced? Check out the Advanced Example
- Get started as a buyer
- Learn about the Bazaar discovery layer
For questions or support, join our Discord.
This quickstart covered:
- Installing the x402 SDK and relevant middleware
- Adding payment middleware to your API and configuring it
- Testing your integration
- Deploying to mainnet with CAIP-2 network identifiers
Your API is now ready to accept crypto payments through x402.
Source: https://docs.x402.org/guides/mcp-server-with-x402
Model Context Protocol (MCP) is a protocol for passing context between LLMs and other AI agents. This page shows how to use the x402 payment protocol with MCP to make paid API requests through an MCP server, and how to connect it to Claude Desktop.
This guide walks you through running an MCP server that can access paid APIs using the x402 protocol. The MCP server acts as a bridge between Claude Desktop (or any MCP-compatible client) and a paid API (such as the sample weather API in the x402 repo). When Claude (or another agent) calls a tool, the MCP server will:
- Detect if the API requires payment (via HTTP 402 with
PAYMENT-REQUIREDheader) - Automatically handle the payment using your wallet via the registered x402 scheme
- Return the paid data to the client (e.g., Claude)
This lets you (or your agent) access paid APIs programmatically, with no manual payment steps.
- Node.js v20+ (install via nvm)
- pnpm v10 (install via pnpm.io/installation)
- An x402-compatible server to connect to (for this demo, we'll use the sample express server with weather data from the x402 repo, or any external x402 API)
- An Ethereum wallet with USDC (on Base Sepolia or Base Mainnet) and/or a Solana wallet with USDC (on Devnet or Mainnet)
- Claude Desktop with MCP support
# Clone the x402 repository
git clone https://github.com/coinbase/x402.git
cd x402/examples/typescript
# Install dependencies and build packages
pnpm install && pnpm build
# Navigate to the MCP client example
cd clients/mcpAdd the MCP server to your Claude Desktop configuration:
{
"mcpServers": {
"demo": {
"command": "pnpm",
"args": [
"--silent",
"-C",
"<absolute path to this repo>/examples/typescript/clients/mcp",
"dev"
],
"env": {
"EVM_PRIVATE_KEY": "<private key of a wallet with USDC on Base Sepolia>",
"SVM_PRIVATE_KEY": "<base58-encoded private key of a Solana wallet with USDC on Devnet>",
"RESOURCE_SERVER_URL": "http://localhost:4021",
"ENDPOINT_PATH": "/weather"
}
}
}
}Make sure your x402-compatible server is running at the URL specified in RESOURCE_SERVER_URL:
# In another terminal, from the examples/typescript directory
cd servers/express
pnpm devRestart Claude Desktop to load the new MCP server, then ask Claude to use the
get-data-from-resource-server tool.
| Variable | Description | Required |
|---|---|---|
EVM_PRIVATE_KEY |
Your EVM wallet's private key (0x prefixed) | One of EVM or SVM required |
SVM_PRIVATE_KEY |
Your Solana wallet's private key (base58 encoded) | One of EVM or SVM required |
RESOURCE_SERVER_URL |
The base URL of the paid API | Yes |
ENDPOINT_PATH |
The specific endpoint path (e.g., /weather) |
Yes |
The MCP server uses @x402/axios to wrap axios with automatic payment handling:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import axios from 'axios';
import { x402Client, wrapAxiosWithPayment } from '@x402/axios';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { registerExactSvmScheme } from '@x402/svm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';
import { createKeyPairSignerFromBytes } from '@solana/kit';
import { base58 } from '@scure/base';
import { config } from 'dotenv';
config();
const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`;
const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string;
const baseURL = process.env.RESOURCE_SERVER_URL || 'http://localhost:4021';
const endpointPath = process.env.ENDPOINT_PATH || '/weather';
if (!evmPrivateKey && !svmPrivateKey) {
throw new Error('At least one of EVM_PRIVATE_KEY or SVM_PRIVATE_KEY must be provided');
}
/**
* Creates an axios client configured with x402 payment support for EVM and/or SVM.
*/
async function createClient() {
const client = new x402Client();
// Register EVM scheme if private key is provided
if (evmPrivateKey) {
const evmSigner = privateKeyToAccount(evmPrivateKey);
registerExactEvmScheme(client, { signer: evmSigner });
}
// Register SVM scheme if private key is provided
if (svmPrivateKey) {
const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey));
registerExactSvmScheme(client, { signer: svmSigner });
}
return wrapAxiosWithPayment(axios.create({ baseURL }), client);
}
async function main() {
const api = await createClient();
// Create an MCP server
const server = new McpServer({
name: 'x402 MCP Client Demo',
version: '2.0.0',
});
// Add a tool that calls the paid API
server.tool(
'get-data-from-resource-server',
'Get data from the resource server (in this example, the weather)',
{},
async () => {
const res = await api.get(endpointPath);
return {
content: [{ type: 'text', text: JSON.stringify(res.data) }],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});The MCP server exposes a tool that, when called, fetches data from a paid API endpoint. If the endpoint requires payment, the x402 axios wrapper automatically handles the payment handshake:
- 402 Response: The server returns HTTP 402 with
PAYMENT-REQUIREDheader - Parse Requirements: The wrapper extracts payment requirements from the header
- Create Payment: Uses the registered scheme (EVM or SVM) to create a payment payload
- Retry Request: Sends the original request with the
PAYMENT-SIGNATUREheader - Return Data: Once payment is verified, the data is returned to Claude
The example supports both EVM (Base, Ethereum) and Solana networks. The x402 client automatically selects the appropriate scheme based on the payment requirements:
import { x402Client, wrapAxiosWithPayment } from '@x402/axios';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { registerExactSvmScheme } from '@x402/svm/exact/client';
const client = new x402Client();
// Register EVM scheme for Base/Ethereum payments
registerExactEvmScheme(client, { signer: evmSigner });
// Register SVM scheme for Solana payments
registerExactSvmScheme(client, { signer: svmSigner });
// Now handles both EVM and Solana networks automatically
const httpClient = wrapAxiosWithPayment(axios.create({ baseURL }), client);When the server returns a 402 response, the client checks the network field in the payment
requirements:
eip155:*networks use the EVM schemesolana:*networks use the SVM scheme
When a payment is required, the client receives:
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: <base64-encoded JSON>
The wrapper automatically:
- Parses the payment requirements
- Creates and signs a payment using the appropriate scheme
- Retries the request with the
PAYMENT-SIGNATUREheader
After payment is processed, the MCP server returns:
{
"content": [
{
"type": "text",
"text": "{\"report\":{\"weather\":\"sunny\",\"temperature\":70}}"
}
]
}┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Claude Desktop │────▶│ MCP Server │────▶│ x402 API │
│ │ │ (x402 client) │ │ (paid endpoint)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ 1. Call tool │ 2. GET /weather │
│ │ │
│ │ 3. 402 + requirements│
│ │◀──────────────────────│
│ │ │
│ │ 4. Sign payment │
│ │ │
│ │ 5. Retry with payment│
│ │──────────────────────▶│
│ │ │
│ │ 6. 200 + data │
│ │◀──────────────────────│
│ │ │
│ 7. Return response │ │
│◀──────────────────────│ │
The example uses these x402 v2 packages:
{
"dependencies": {
"@modelcontextprotocol/sdk": "^1.9.0",
"@x402/axios": "workspace:*",
"@x402/evm": "workspace:*",
"@x402/svm": "workspace:*",
"axios": "^1.13.2",
"viem": "^2.39.0",
"@solana/kit": "^2.1.1",
"@scure/base": "^1.2.6"
}
}- x402-compatible server: Hosts the paid API (e.g., weather data). Responds with HTTP 402 and
PAYMENT-REQUIREDheader if payment is required. - MCP server (this implementation): Acts as a bridge, handling payment via
@x402/axiosand exposing tools to MCP clients. - Claude Desktop: Calls the MCP tool, receives the paid data, and displays it to the user.
- See the full example in the repo
- Try integrating with your own x402-compatible APIs
- Extend the MCP server with more tools or custom logic as needed
- Learn about building x402 servers
Source: https://docs.x402.org/guides/migration-v1-to-v2
This guide helps you migrate from x402 V1 to V2. The V2 protocol introduces standardized identifiers, improved type safety, and a more modular architecture.
| Aspect | V1 | V2 |
|---|---|---|
| Payment Header | X-PAYMENT |
PAYMENT-SIGNATURE |
| Response Header | X-PAYMENT-RESPONSE |
PAYMENT-RESPONSE |
| Network Format | String (base-sepolia) |
CAIP-2 (eip155:84532) |
| Version Field | x402Version: 1 |
x402Version: 2 |
| Packages | x402, x402-express, x402-axios |
@x402/core, @x402/express, @x402/axios, @x402/evm |
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: baseSepolia,
transport: http(),
});
// V1 pattern
const api = withPaymentInterceptor(
axios.create({ baseURL: "https://api.example.com" }),
walletClient,
);
const response = await api.get("/paid-endpoint");
```
from eth_account import Account
from x402.clients.httpx import x402HttpxClient
# V1 pattern
account = Account.from_key(os.getenv("PRIVATE_KEY"))
async with x402HttpxClient(account=account, base_url="https://api.example.com") as client:
response = await client.get("/protected-endpoint")
print(await response.aread())
```
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
// V2 pattern: Create client and register scheme separately
const client = new x402Client();
registerExactEvmScheme(client, { signer });
// Wrap axios with payment handling
const api = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.example.com" }),
client,
);
const response = await api.get("/paid-endpoint");
```
from eth_account import Account
from x402 import x402Client
from x402.http import x402HTTPClient
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
async def main() -> None:
# V2 pattern: Create client and register scheme separately
client = x402Client()
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
http_client = x402HTTPClient(client)
async with x402HttpxClient(client) as http:
response = await http.get("https://api.example.com/paid-endpoint")
await response.aread()
print(f"Response: {response.text}")
if response.is_success:
settle_response = http_client.get_payment_settle_response(
lambda name: response.headers.get(name)
)
print(f"Payment settled: {settle_response}")
asyncio.run(main())
```
const app = express();
const facilitatorConfig: FacilitatorConfig = {
url: "https://x402.org/facilitator",
};
app.use(
paymentMiddleware(facilitatorConfig, {
"GET /weather": {
price: "$0.001",
network: "base-sepolia", // V1 string format
config: {
description: "Get weather data",
},
},
}),
);
```
from fastapi import FastAPI
from x402.fastapi.middleware import require_payment
app = FastAPI()
# V1 pattern
app.middleware("http")(
require_payment(
path="/weather",
price="$0.001",
pay_to_address="0xYourAddress",
network="base-sepolia", # V1 string identifier
)
)
@app.get("/weather")
async def get_weather() -> Dict[str, Any]:
return {"report": {"weather": "sunny", "temperature": 70}}
```
const app = express();
const payTo = "0xYourAddress";
// V2 pattern: Create facilitator client and resource server
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532", // V2 CAIP-2 format
payTo,
},
],
description: "Get weather data",
mimeType: "application/json",
},
},
server,
),
);
```
from fastapi import FastAPI
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer
app = FastAPI()
# V2 pattern: Create facilitator client and resource server
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://x402.org/facilitator")
)
server = x402ResourceServer(facilitator)
server.register("eip155:84532", ExactEvmServerScheme())
# V2: Route config uses accepts array with explicit scheme, network, and pay_to
routes: dict[str, RouteConfig] = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to="0xYourAddress",
price="$0.001",
network="eip155:84532", # V2 CAIP-2 format
),
],
mime_type="application/json",
description="Get weather data",
),
}
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
@app.get("/weather")
async def get_weather() -> dict[str, Any]:
return {"report": {"weather": "sunny", "temperature": 70}}
```
| V1 Name | V2 CAIP-2 ID | Chain ID | Description |
|---|---|---|---|
base-sepolia |
eip155:84532 |
84532 | Base Sepolia Testnet |
base |
eip155:8453 |
8453 | Base Mainnet |
ethereum |
eip155:1 |
1 | Ethereum Mainnet |
sepolia |
eip155:11155111 |
11155111 | Ethereum Sepolia Testnet |
solana-devnet |
solana:devnet |
- | Solana Devnet |
solana |
solana:mainnet |
- | Solana Mainnet |
**Installation with extras:**
```bash theme={null}
# V1
pip install x402
# V2 - install with specific extras
pip install "x402[httpx]" # For async HTTP clients
pip install "x402[requests]" # For sync HTTP clients
pip install "x402[fastapi]" # For FastAPI servers
pip install "x402[flask]" # For Flask servers
pip install "x402[svm]" # For Solana support
```
If you're implementing custom HTTP handling, update your header names:
```typescript theme={null} // V1 const payment = req.header("X-PAYMENT"); res.setHeader("X-PAYMENT-RESPONSE", responseData);// V2
const payment = req.header("PAYMENT-SIGNATURE");
res.setHeader("PAYMENT-RESPONSE", responseData);
```
# V2
payment = request.headers.get("PAYMENT-SIGNATURE")
response.headers["PAYMENT-RESPONSE"] = response_data
```
Ensure you've installed all V2 packages:
```bash theme={null}
# For buyers
npm install @x402/axios @x402/evm
# For sellers (Express)
npm install @x402/express @x402/core @x402/evm
```
Ensure you've installed the x402 package with the correct extras:
```bash theme={null}
# For async HTTP clients (httpx)
pip install "x402[httpx]"
# For sync HTTP clients (requests)
pip install "x402[requests]"
# For FastAPI servers
pip install "x402[fastapi]"
# For Flask servers
pip install "x402[flask]"
# For Solana support
pip install "x402[svm]"
```
- Check you're using CAIP-2 network identifiers (
eip155:84532notbase-sepolia) - Verify your
payToaddress is correctly configured - Ensure the facilitator URL is correct for your network (testnet vs mainnet)
The facilitator supports both V1 and V2 protocols. During migration, your V2 server can still accept payments from V1 clients, but we recommend updating clients to V2 for full feature support.
Source: https://docs.x402.org/introduction
This guide will help you understand x402, the open payment standard, and help you get started building or integrating services with x402.
x402 is the open payment standard that enables services to charge for access to their APIs and
content directly over HTTP. It is built around the HTTP 402 Payment Required status code and
allows clients to programmatically pay for resources without accounts, sessions, or credential
management.
With x402, any web service can require payment before serving a response, using crypto-native payments for speed, privacy, and efficiency.
Want to contribute to our docs? The GitBook repo is open to PRs! Our only ask is that you keep these docs as a neutral resource, with no branded content other than linking out to other resources where appropriate.
Note about the docs: These docs are the credibly neutral source of truth for x402, as x402 is a completely open standard under the Apache-2.0 license. Coinbase Developer Platform is currently sponsoring AI-powered docs for users here, as we migrate to our own AI-powered solution on the main x402.org domain.
x402 addresses key limitations of existing payment systems:
- High fees and friction with traditional credit cards and fiat payment processors
- Incompatibility with machine-to-machine payments, such as AI agents
- Lack of support for micropayments, making it difficult to monetize usage-based services
- Sellers: Service providers who want to monetize their APIs or content. x402 enables direct, programmatic payments from clients with minimal setup.
- Buyers: Human developers and AI agents seeking to access paid services without accounts or manual payment flows.
Both sellers and buyers interact directly through HTTP requests, with payment handled transparently through the protocol.
x402 enables a range of use cases, including:
- API services paid per request
- AI agents that autonomously pay for API access
- Paywalls for digital content
- Microservices and tooling monetized via microtransactions
- Proxy services that aggregate and resell API capabilities
At a high level, the flow is simple:
- A buyer requests a resource from a server.
- If payment is required, the server responds with
402 Payment Required, including payment instructions. - The buyer prepares and submits a payment payload.
- The server verifies and settles the payment using an x402 facilitator's /verify and /settle endpoints.
- If payment is valid, the server provides the requested resource.
For more detail, see:
The goal is to make programmatic commerce accessible, permissionless, and developer-friendly.
Ready to build? Start here: