Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.monkepay.xyz/llms.txt

Use this file to discover all available pages before exploring further.

How agents pay

An x402-capable agent needs two things:
  1. A wallet with USDC on the right network
  2. A payment-aware fetch wrapper that handles the 402 → pay → retry flow automatically
The most widely used solution is x402-fetch from Coinbase, which wraps the standard fetch API:
import { wrapFetchWithPayment } from 'x402-fetch'
import { createSigner } from 'x402/types'

const walletClient = await createSigner(
  'base-sepolia',
  process.env.AGENT_PRIVATE_KEY as `0x${string}`,
)

const fetch402 = wrapFetchWithPayment(fetch, walletClient)

// Works exactly like fetch — payment is handled automatically
const response = await fetch402('https://api.example.com/api/data')
const data = await response.json()
When fetch402 receives a 402 Payment Required response, it:
  1. Reads the payment requirements from the response
  2. Signs and broadcasts a USDC transaction on Base
  3. Retries the original request with payment proof in the X-Payment header
  4. Returns the 200 OK response to your code
Your agent code sees only the final response. The payment flow is invisible.

Setting up a wallet

Your agent needs an EVM wallet with USDC on Base Sepolia (testnet) or Base (mainnet).

Option A — Private key (simplest)

Generate a wallet and export its private key. Store it as an environment variable.
AGENT_PRIVATE_KEY=0x...
import { createSigner } from 'x402/types'

const walletClient = await createSigner(
  'base-sepolia',
  process.env.AGENT_PRIVATE_KEY as `0x${string}`,
)
Keep your private key secret. Never commit it or log it.

Option B — Coinbase CDP wallet

For production agents, Coinbase Developer Platform wallets offer programmatic key management without storing raw private keys:
import { CdpClient } from '@coinbase/cdp-sdk'
import { createSigner } from 'x402/types'

const cdp = new CdpClient({
  apiKeyId: process.env.CDP_API_KEY_ID!,
  apiKeySecret: process.env.CDP_API_KEY_SECRET!,
  walletSecret: process.env.CDP_WALLET_SECRET!,
})

const exported = await cdp.evm.exportAccount({
  address: process.env.AGENT_WALLET_ADDRESS as `0x${string}`,
})

const walletClient = await createSigner('base-sepolia', exported as `0x${string}`)
See the Coinbase CDP docs for wallet creation and funding.

Funding your agent wallet

Testnet (Base Sepolia): Mainnet (Base):

Setting a payment cap

You can cap how much the agent will pay per request:
import { parseUnits } from 'viem'

// Cap at $1.00 USDC per request
const maxPaymentAtomic = parseUnits('1.00', 6) // 1,000,000 atomic units

const fetch402 = wrapFetchWithPayment(fetch, walletClient, maxPaymentAtomic)
If an endpoint asks for more than your cap, the payment is refused and the agent receives a 402 error instead of proceeding.

Using with MCP

If you’re building an MCP server or connecting to AI assistants like Claude or Cursor, Coinbase provides an x402 MCP server that handles payments transparently: x402 MCP Server — Coinbase Developer Documentation This lets any MCP-compatible agent pay for x402 endpoints without any custom payment code.

Handling one_time unlock tokens

If the API uses one_time payment mode, the agent receives an unlock token after the first payment. The agent must persist this token and send it on subsequent requests:
const response = await fetch402('https://api.example.com/api/report')

// Save the unlock token
const unlockToken = response.headers.get('X-MonkePay-Unlock')
if (unlockToken) {
  await storage.set('unlock:api.example.com/api/report', unlockToken)
}

// On subsequent requests, send the token directly
const cachedToken = await storage.get('unlock:api.example.com/api/report')
if (cachedToken) {
  const response = await fetch('https://api.example.com/api/report', {
    headers: { 'X-MonkePay-Unlock': cachedToken },
  })
}
If the token is lost, the agent must pay again for a new one.