Payments

Use x402 as an AI agent on Base

Step-by-step guide to wiring x402 payments into your AI agent. Wallet setup, SDK config, service discovery, MCP integration, and OpenClaw.

18 minUpdated 2026-03-03

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:

  1. Agent wallet — a dedicated Base wallet funded with USDC
  2. Payment-wrapped HTTP client — any HTTP request your agent makes automatically handles x402 payments
  3. Service discovery — your agent finds paid APIs through the Bazaar (x402's discovery layer)
  4. MCP integration — LLM agents (Claude, GPT) can pay for services through Model Context Protocol
  5. 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)

bash
npm install viem
typescript
// 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.`);
bash
npx tsx create-agent-wallet.ts

Save the private key as an environment variable:

bash
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:

bash
# 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

bash
pip install eth-account
python
# 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:

For testnet: Get free test USDC on Base Sepolia from the Coinbase faucet.


Step 2 — Install the x402 client SDK

TypeScript / Node.js

bash
# 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

bash
# Async (recommended)
pip install "x402[httpx]"

# Sync
pip install "x402[requests]"

Go

bash
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
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:

  1. Reads the payment requirements from the PAYMENT-REQUIRED header
  2. Signs a USDC payment with your agent's private key
  3. Retries the request with the PAYMENT-SIGNATURE header
  4. Returns the response to your agent

Your agent code never sees the 402. It just gets data.

TypeScript — Axios

typescript
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)

python
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:

bash
# 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
bash
# Terminal 2: Run your agent
typescript
// 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);
bash
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

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

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

bash
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):

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

  1. Claude sees the get-data-from-resource-server tool in its MCP tools
  2. When Claude decides it needs data, it calls the tool
  3. The MCP server makes the HTTP request with x402 payment handling
  4. If the API returns 402, payment is handled automatically
  5. Claude gets the data back — it never even knows a payment happened

The MCP implementation uses @x402/axios under the hood:

typescript
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.md that 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:

bash
mkdir -p ~/.openclaw/workspace/skills/x402-payments

Create the skill file:

markdown
# ~/.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

typescript
// ~/.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:

bash
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:

bash
# 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:

💡Pro Tip

"Fetch the latest weather data from the x402 weather API at https://weather-x402.example.com/forecast"

The agent:

  1. Recognizes this needs the x402-payments skill (from the SKILL.md description)
  2. Runs: npx tsx skills/x402-payments/pay-fetch.ts "https://weather-x402.example.com/forecast"
  3. The script handles the 402 → payment → data flow
  4. 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:

bash
# 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:

💡Pro Tip

"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

typescript
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:

typescript
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:

typescript
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:

SettingTestnet (Base Sepolia)Mainnet (Base)
Networkeip155:84532eip155:8453
Facilitatorhttps://x402.org/facilitatorhttps://x402.org/facilitator (or production)
USDCTestnet faucetReal 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:

typescript
// 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:

bash
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