Your AI agent can reason, plan, and execute. But the moment it needs to buy something — an API call, a data feed, compute time — it hits a wall. It can't fill out a Stripe form. It can't manage API keys across 50 services. It can't do KYC.
x402 fixes this. Your agent gets a wallet, and that wallet becomes its only credential for every paid service on the internet.
This guide is not theory. It's a step-by-step build. By the end, your agent will have a wallet, a payment-enabled HTTP client, and the ability to discover and pay for x402 services autonomously.
What you're building
Here's the end state:
- Agent wallet — a dedicated Base wallet funded with USDC
- Payment-wrapped HTTP client — any HTTP request your agent makes automatically handles x402 payments
- Service discovery — your agent finds paid APIs through the Bazaar (x402's discovery layer)
- MCP integration — LLM agents (Claude, GPT) can pay for services through Model Context Protocol
- Budget controls — spending caps, allowlists, monitoring
Let's build each piece.
Step 1 — Create your agent's wallet
Your agent needs its own wallet. Not your personal wallet — a dedicated wallet you fund with small amounts of USDC.
Option A: Quick wallet (Node.js)
npm install viem
// create-agent-wallet.ts
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
const privateKey = generatePrivateKey();
const account = privateKeyToAccount(privateKey);
console.log(`Address: ${account.address}`);
console.log(`Private key: ${privateKey}`);
console.log(`\nSave the private key securely. Fund this address with USDC on Base.`);
npx tsx create-agent-wallet.ts
Save the private key as an environment variable:
export AGENT_PRIVATE_KEY="0xabc123..."
Option B: Using OpenClaw's base-wallet skill
If you're running OpenClaw (an autonomous agent framework), it has a built-in wallet skill:
# Create a wallet in env var format (safest)
node ~/.openclaw/workspace/skills/base-wallet/scripts/create-wallet.js --env
# Or create a managed wallet file
node ~/.openclaw/workspace/skills/base-wallet/scripts/create-wallet.js --managed my-agent
This creates a wallet at ~/.openclaw/wallets/my-agent.json with the private key, address, and mnemonic. OpenClaw agents can then use this wallet for SIWE authentication, balance checks, and x402 payments.
Option C: Python
pip install eth-account
# create_agent_wallet.py
from eth_account import Account
account = Account.create()
print(f"Address: {account.address}")
print(f"Private key: {account.key.hex()}")
print(f"\nSave the private key securely. Fund this address with USDC on Base.")
Fund the wallet
Send USDC to your agent's address on Base. Start small — $5-10 is plenty for testing and early use. You can always top up.
Where to get USDC on Base:
- Bridge from Ethereum via the Base Bridge
- Buy directly on Coinbase and withdraw to Base
- Swap ETH for USDC on Aerodrome or Uniswap
For testnet: Get free test USDC on Base Sepolia from the Coinbase faucet.
Step 2 — Install the x402 client SDK
TypeScript / Node.js
# Fetch-based (recommended — wraps native fetch)
npm install @x402/fetch @x402/core @x402/evm
# Or Axios-based
npm install @x402/axios @x402/core @x402/evm
Python
# Async (recommended)
pip install "x402[httpx]"
# Sync
pip install "x402[requests]"
Go
go get github.com/coinbase/x402/go
Step 3 — Wire up the payment client
This is the core integration. You wrap your HTTP client once, and every request your agent makes will automatically handle x402 payments.
TypeScript — Fetch (recommended)
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// 1. Create signer from agent's private key
const signer = privateKeyToAccount(
process.env.AGENT_PRIVATE_KEY as `0x${string}`
);
// 2. Create x402 client and register Base payment scheme
const client = new x402Client();
registerExactEvmScheme(client, { signer });
// 3. Wrap fetch — this is the only setup you need
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
That's it. fetchWithPayment works exactly like fetch, but when a server responds with HTTP 402, the SDK automatically:
- Reads the payment requirements from the
PAYMENT-REQUIREDheader - Signs a USDC payment with your agent's private key
- Retries the request with the
PAYMENT-SIGNATUREheader - Returns the response to your agent
Your agent code never sees the 402. It just gets data.
TypeScript — Axios
import { wrapAxiosWithPayment } from "@x402/axios";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import axios from "axios";
const signer = privateKeyToAccount(
process.env.AGENT_PRIVATE_KEY as `0x${string}`
);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const api = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.example.com" }),
client,
);
// Use like normal axios
const { data } = await api.get("/paid-endpoint");
Python — httpx (async)
import os
from eth_account import Account
from x402.mechanisms.evm import EthAccountSigner
from x402.clients.httpx import AsyncX402Client
account = Account.from_key(os.getenv("AGENT_PRIVATE_KEY"))
signer = EthAccountSigner(account)
async with AsyncX402Client(signer=signer) as client:
response = await client.get("https://api.example.com/paid-endpoint")
data = response.json()
Step 4 — Make your first paid request
Let's test against the x402 sample server. Clone the repo and run the example server locally:
# Terminal 1: Start the sample x402 server
git clone https://github.com/coinbase/x402.git
cd x402/examples/typescript
pnpm install && pnpm build
cd servers/express
pnpm dev
# Server running at http://localhost:4021
# Terminal 2: Run your agent
// test-payment.ts
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(
process.env.AGENT_PRIVATE_KEY as `0x${string}`
);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
async function main() {
console.log("Fetching weather data (x402 paid endpoint)...");
const response = await fetchWithPayment("http://localhost:4021/weather");
const data = await response.json();
console.log("Weather data:", data);
// Check for payment receipt
const receipt = response.headers.get("PAYMENT-RESPONSE");
if (receipt) {
console.log("Payment settled:", JSON.parse(atob(receipt)));
}
}
main().catch(console.error);
AGENT_PRIVATE_KEY=0xyour_testnet_key npx tsx test-payment.ts
If it works, you'll see the weather data and a payment receipt. Your agent just paid for an API call autonomously.
Step 5 — Discover paid services with Bazaar
The Bazaar is x402's discovery layer — a machine-readable catalog of every x402-enabled API. Your agent can query it to find services without you hardcoding URLs.
TypeScript
import { HTTPFacilitatorClient } from "@x402/core/http";
import { withBazaar } from "@x402/extensions";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const bazaarClient = withBazaar(facilitatorClient);
// List all available x402 services
const response = await bazaarClient.extensions.discovery.listResources({
type: "http"
});
// Filter for affordable services (under $0.10 per call)
const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base
const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals)
const services = response.items.filter(item =>
item.accepts.find(req =>
req.asset === usdcAsset &&
Number(req.maxAmountRequired) < maxPrice
)
);
console.log(`Found ${services.length} affordable x402 services:`);
services.forEach(svc => {
console.log(` ${svc.resource} — ${svc.accepts[0].description || "no description"}`);
});
Python
from x402.http import FacilitatorConfig, HTTPFacilitatorClient
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)
response = await facilitator.list_resources(type="http")
usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
max_price = 100000 # $0.10
affordable = [
item for item in response.items
if any(
req.asset == usdc_asset and int(req.max_amount_required) < max_price
for req in item.accepts
)
]
for svc in affordable:
print(f" {svc.resource}")
This is powerful. Your agent doesn't need a pre-built list of services. It discovers what's available, evaluates pricing, and pays on the fly. No API keys. No accounts. Just discovery → pay → access.
Step 6 — Connect to Claude Desktop via MCP
Model Context Protocol (MCP) lets LLM agents like Claude call external tools. x402 has an official MCP integration — meaning Claude can discover and pay for x402 services directly.
Setup
git clone https://github.com/coinbase/x402.git
cd x402/examples/typescript
pnpm install && pnpm build
Configure Claude Desktop
Edit your Claude Desktop MCP config (claude_desktop_config.json):
{
"mcpServers": {
"x402-payments": {
"command": "pnpm",
"args": [
"--silent",
"-C",
"/path/to/x402/examples/typescript/clients/mcp",
"dev"
],
"env": {
"EVM_PRIVATE_KEY": "0xyour_agent_private_key",
"RESOURCE_SERVER_URL": "https://api.example.com",
"ENDPOINT_PATH": "/weather"
}
}
}
}
What happens
- Claude sees the
get-data-from-resource-servertool in its MCP tools - When Claude decides it needs data, it calls the tool
- The MCP server makes the HTTP request with x402 payment handling
- If the API returns 402, payment is handled automatically
- Claude gets the data back — it never even knows a payment happened
The MCP implementation uses @x402/axios under the hood:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { x402Client, wrapAxiosWithPayment } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
const client = new x402Client();
registerExactEvmScheme(client, { signer: evmSigner });
const api = wrapAxiosWithPayment(axios.create({ baseURL }), client);
const server = new McpServer({
name: "x402 Payment Agent",
version: "2.0.0",
});
server.tool(
"get-paid-data",
"Fetch data from a paid x402 API endpoint",
{},
async () => {
const res = await api.get(endpointPath);
return {
content: [{ type: "text", text: JSON.stringify(res.data) }],
};
},
);
This is the endgame for agent commerce: LLMs that can autonomously discover, evaluate, and pay for services — all through standard protocols.
Step 7 — OpenClaw agent integration
Most agents running on Base today use OpenClaw — a self-hosted gateway that connects AI agents to messaging apps (Telegram, Discord, WhatsApp) with built-in tools, skills, cron scheduling, and wallet management. If you're running an OpenClaw agent, here's how x402 fits into your actual workflow.
How OpenClaw agents work (quick context)
OpenClaw agents live in a workspace (~/.openclaw/workspace/). They have:
- Skills — folders with a
SKILL.mdthat teach the agent how to use specific tools (Bankr for token launches, base-wallet for crypto, x-research for X/Twitter, etc.) - Cron jobs — scheduled tasks that run the agent autonomously (post every 2 hours, check prices daily, etc.)
- Exec tool — the agent can run shell commands, including Node.js scripts
- Memory — persistent files the agent reads each session for context
x402 plugs into this by becoming a skill your agent can use — just like it uses Bankr to launch tokens or base-wallet to send transactions.
Step 1: Create an x402 skill in your workspace
Create a skill folder that gives your agent x402 payment capabilities:
mkdir -p ~/.openclaw/workspace/skills/x402-payments
Create the skill file:
# ~/.openclaw/workspace/skills/x402-payments/SKILL.md
---
name: x402-payments
description: "Pay for any x402-enabled API using USDC on Base. Use when the agent needs to access a paid HTTP service, buy API data, or interact with x402 endpoints."
---
# x402 Payments Skill
Pay for HTTP APIs that use the x402 protocol. Your agent wallet signs
USDC payments on Base automatically.
## Setup
The payment script lives at `{baseDir}/pay-fetch.ts`. It wraps fetch
with x402 payment handling using the agent's wallet.
## Usage
Run via exec tool:
\`\`\`bash
npx tsx {baseDir}/pay-fetch.ts "https://api.example.com/paid-endpoint"
\`\`\`
The script:
1. Loads the agent wallet from ~/.openclaw/wallets/
2. Sends the HTTP request
3. If the server returns 402, automatically signs a USDC payment
4. Returns the response data to stdout
## Environment
- Wallet: ~/.openclaw/wallets/x402-agent.json
- Network: Base mainnet (eip155:8453)
- Currency: USDC
- Max per request: $0.10 (configurable in script)
Step 2: Create the payment script
// ~/.openclaw/workspace/skills/x402-payments/pay-fetch.ts
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import { readFileSync, existsSync } from "fs";
import { homedir } from "os";
// --- Config ---
const MAX_PAYMENT = 0.10; // Max USDC per request
const WALLET_NAME = process.env.X402_WALLET || "x402-agent";
const WALLET_PATH = `${homedir()}/.openclaw/wallets/${WALLET_NAME}.json`;
// --- Load wallet ---
if (!existsSync(WALLET_PATH)) {
console.error(`Wallet not found: ${WALLET_PATH}`);
console.error(`Create one with: node skills/base-wallet/scripts/create-wallet.js --managed ${WALLET_NAME}`);
process.exit(1);
}
const wallet = JSON.parse(readFileSync(WALLET_PATH, "utf-8"));
const signer = privateKeyToAccount(wallet.privateKey as `0x${string}`);
// --- Setup x402 ---
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// --- Allowlist (add trusted services here) ---
const ALLOWED_HOSTS = new Set([
// Add your trusted x402 services:
// "api.weather-x402.com",
// "data.market-oracle.com",
]);
// --- Main ---
const url = process.argv[2];
if (!url) {
console.error("Usage: npx tsx pay-fetch.ts <url>");
process.exit(1);
}
// Optional: enforce allowlist
if (ALLOWED_HOSTS.size > 0) {
const host = new URL(url).hostname;
if (!ALLOWED_HOSTS.has(host)) {
console.error(`Host not in allowlist: ${host}`);
process.exit(1);
}
}
const response = await fetchWithPayment(url);
const data = await response.json();
// Log payment receipt if present
const receipt = response.headers.get("PAYMENT-RESPONSE");
if (receipt) {
console.error(`[x402] Payment settled: ${JSON.stringify(JSON.parse(atob(receipt)))}`);
}
// Output data to stdout (agent reads this)
console.log(JSON.stringify(data, null, 2));
Install dependencies in the skill folder:
cd ~/.openclaw/workspace/skills/x402-payments
npm init -y
npm install @x402/fetch @x402/core @x402/evm viem
Step 3: Create and fund the agent wallet
Use OpenClaw's base-wallet skill:
# Create a dedicated x402 wallet
node ~/.openclaw/workspace/skills/base-wallet/scripts/create-wallet.js --managed x402-agent
This creates ~/.openclaw/wallets/x402-agent.json. Fund it with USDC on Base — $5-10 to start.
Step 4: Use it — agent just talks
Now your OpenClaw agent can use x402 naturally. You message it on Telegram:
"Fetch the latest weather data from the x402 weather API at https://weather-x402.example.com/forecast"
The agent:
- Recognizes this needs the x402-payments skill (from the SKILL.md description)
- Runs:
npx tsx skills/x402-payments/pay-fetch.ts "https://weather-x402.example.com/forecast" - The script handles the 402 → payment → data flow
- Agent reads the JSON output and responds with the weather
You never touch a payment form. The agent never manages an API key. It just runs the script and gets data.
Step 5: Automate with cron
The real power is combining x402 with OpenClaw's cron scheduler. Your agent can autonomously fetch paid data on a schedule:
# Via OpenClaw CLI:
openclaw cron add \
--name "x402-market-data" \
--cron "0 */4 * * *" \
--tz "Europe/Paris" \
--session isolated \
--message "Use the x402-payments skill to fetch market data from https://data.example.com/prices. Summarize the key movements and post to Telegram." \
--announce
Or through the agent itself — just tell it:
"Set up a cron job that fetches premium market data every 4 hours from the x402 API at https://data.example.com/prices and posts a summary to this chat."
The agent creates the cron job. Every 4 hours, it wakes up, runs the x402 payment script, gets the data, and posts the summary. Fully autonomous.
Step 6: Combine with other skills
This is where OpenClaw shines. x402 isn't isolated — it stacks with your other skills:
x402 + Bankr skill: Agent monitors token data via x402 paid APIs, then uses Bankr to execute trades based on the data.
x402 + x-research skill: Agent pays for premium research data via x402, cross-references with free X/Twitter data from x-research, and delivers a combined analysis.
x402 + base-wallet skill: Agent checks its x402 wallet balance before making paid requests. If balance is low, it notifies you on Telegram: "My x402 wallet is running low ($1.23 remaining). Top up?"
The skill system means your agent composes capabilities naturally. It reads each SKILL.md, knows what tools are available, and chains them together based on what the task requires.
Why OpenClaw + x402 is the real agent stack
Most "AI agent" frameworks give you a chatbot that can call functions. OpenClaw gives you a persistent agent that:
- Lives on your machine 24/7
- Has its own wallet and can spend USDC autonomously
- Runs scheduled tasks via cron (no human triggering needed)
- Communicates through Telegram, Discord, WhatsApp — wherever you are
- Composes skills: Bankr for tokens, base-wallet for transactions, x-research for intel, x402 for paid APIs
- Maintains memory across sessions
x402 is the missing piece that lets this agent buy things. Before x402, an agent could search the web, post tweets, and deploy tokens — but it couldn't pay for premium data, compute, or services. Now it can. One skill, one wallet, unlimited paid APIs.
Step 8 — Budget controls and security
Giving an agent a wallet means giving it the ability to spend money. You need guardrails.
Fund small, refill often
Don't load $1,000 into an agent wallet. Fund $10-20. Top up as needed. This is the simplest budget control.
Per-request spending cap
const MAX_PER_REQUEST = 0.10; // $0.10 USDC
const safeFetch = async (url: string, init?: RequestInit) => {
// x402 SDK supports maxPaymentAmount option
return fetchWithPayment(url, {
...init,
maxPaymentAmount: MAX_PER_REQUEST,
});
};
If a service asks for more than your cap, the SDK throws instead of paying.
Allowlist trusted services
Don't let a prompt injection trick your agent into paying arbitrary endpoints:
const ALLOWED_HOSTS = new Set([
"api.weather-service.com",
"data.market-oracle.com",
"inference.ai-provider.com",
]);
async function safeFetch(url: string, init?: RequestInit) {
const host = new URL(url).hostname;
if (!ALLOWED_HOSTS.has(host)) {
throw new Error(`Payment blocked: ${host} not in allowlist`);
}
return fetchWithPayment(url, init);
}
Track spending
Log every payment receipt for auditing:
const response = await fetchWithPayment(url);
const receipt = response.headers.get("PAYMENT-RESPONSE");
if (receipt) {
const parsed = JSON.parse(atob(receipt));
// Log to your monitoring: timestamp, amount, service, tx hash
console.log({
service: url,
amount: parsed.amount,
txHash: parsed.txHash,
timestamp: new Date().toISOString(),
});
}
Separate wallets per agent
Run 3 agents? Create 3 wallets. Clean spending attribution, isolated blast radius, easy to kill one agent's spending by not refilling its wallet.
Testnet → Mainnet
The entire switch is two config values:
| Setting | Testnet (Base Sepolia) | Mainnet (Base) |
|---|---|---|
| Network | eip155:84532 | eip155:8453 |
| Facilitator | https://x402.org/facilitator | https://x402.org/facilitator (or production) |
| USDC | Testnet faucet | Real USDC |
That's it. Your code doesn't change. The SDK handles the rest.
Complete working example
Here's a full agent script that creates a wallet, discovers services, and makes a paid request:
// agent.ts — Complete x402 agent on Base
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import { HTTPFacilitatorClient } from "@x402/core/http";
import { withBazaar } from "@x402/extensions";
// --- Config ---
const AGENT_KEY = process.env.AGENT_PRIVATE_KEY as `0x${string}`;
const MAX_SPEND_PER_REQUEST = 0.10; // USDC
// --- Setup wallet & payment client ---
const signer = privateKeyToAccount(AGENT_KEY);
const x402 = new x402Client();
registerExactEvmScheme(x402, { signer });
const fetchPaid = wrapFetchWithPayment(fetch, x402);
// --- Setup service discovery ---
const facilitator = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const bazaar = withBazaar(facilitator);
async function discoverServices() {
const res = await bazaar.extensions.discovery.listResources({ type: "http" });
console.log(`Discovered ${res.items.length} x402 services`);
return res.items;
}
async function callService(url: string) {
console.log(`Calling ${url}...`);
const response = await fetchPaid(url);
const data = await response.json();
const receipt = response.headers.get("PAYMENT-RESPONSE");
if (receipt) {
console.log("Payment settled:", JSON.parse(atob(receipt)));
}
return data;
}
async function main() {
// 1. Discover available services
const services = await discoverServices();
// 2. Pick one and call it
if (services.length > 0) {
const firstService = services[0].resource;
const data = await callService(firstService);
console.log("Response:", data);
}
}
main().catch(console.error);
Run it:
AGENT_PRIVATE_KEY=0xyourkey npx tsx agent.ts
What's next
x402 is early. The protocol already has 75M+ transactions and $24M+ in volume, but the ecosystem of x402-enabled services is still growing. Here's what to watch:
- Bazaar expansion — more services listing themselves for agent discovery
- "upto" scheme — pay based on actual usage (tokens generated, compute consumed), not fixed prices
- More networks — Solana support already exists, more chains coming
- Agent frameworks adopting x402 natively — expect LangChain, CrewAI, AutoGPT, and others to add built-in x402 support
The direction is clear: every API becomes payable, every agent becomes a buyer, and the wallet becomes the universal credential. Base is where this is happening first — cheapest gas, deepest USDC liquidity, and the protocol was built here.
Build your agent. Give it a wallet. Let it pay for what it needs.
Related guides: What is x402? The payment protocol thesis · Accept x402 payments as a merchant · Launch an AI agent on Base