Skip to main content
Need help? Join the x402 Discord for the latest updates.

Facilitator URLs

EnvironmentFacilitator URLNetworksAuth
CDP (recommended)https://api.cdp.coinbase.com/platform/v2/x402Base, Base Sepolia, Polygon, Solana, Solana DevnetCDP API keys required
x402.org (testnet only)https://x402.org/facilitatorBase Sepolia, Solana DevnetNone
We recommend the CDP facilitator for both testnet and mainnet. Use x402.org if you want to try x402 without signing up. 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. The x402 helper packages for various languages greatly simplify your integration with x402. You’ll be able to automatically detect payment challenges, authorize payments onchain, and retry requests with minimal code. The packages will automatically trigger the following flow:
  1. Makes the initial request (if using Fetch) or intercepts the initial request (if using Axios)
  2. If a 402 response is received, parses the payment requirements from the PAYMENT-REQUIRED header
  3. Creates a payment payload using the configured x402Client and registered schemes
  4. Retries the request with the PAYMENT-SIGNATURE header

Prerequisites

Before you begin, ensure you have:
  • A crypto wallet with USDC (any EVM-compatible wallet, e.g., CDP Wallet, AgentKit)
  • Node.js and npm, Go, or Python and pip installed
  • A service that requires payment via x402
  • For testnet: Base Sepolia ETH for gas and testnet USDC. Get funds from the CDP Faucet
We have pre-configured examples available in our repo, including examples for fetch, Axios, and MCP.

1. Install Dependencies

Install the x402 client packages:
# 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

# For Bazaar discovery (optional):
npm install @x402/core @x402/extensions

2. Create a Wallet Client

Create a wallet client using CDP’s Server Wallet (recommended) or a standalone wallet library (viem for EVM on Node.js, or Go’s crypto libraries).
Building with Embedded Wallets? If you’re building a user-facing application with embedded wallets, check out the X402 with Embedded Wallets guide which shows how to use the useX402 hook for seamless payment integration.
First, create an account at cdp.coinbase.com and get the following API keys from the portal to store as environment variables:
# store in .env or using the command `export <name>="secret-info"`
CDP_API_KEY_ID=your-api-key-id
CDP_API_KEY_SECRET=your-api-key-secret
CDP_WALLET_SECRET=your-wallet-secret
Then, install the required packages:
Node.js
npm install @coinbase/cdp-sdk dotenv
Finally, instantiate the CDP client as suggested by the Server Wallet Quickstart:
Node.js
import { CdpClient } from "@coinbase/cdp-sdk";
import { toAccount } from "viem/accounts";
import dotenv from "dotenv";

dotenv.config();

const cdp = new CdpClient();
const cdpAccount = await cdp.evm.createAccount();
const signer = toAccount(cdpAccount);

Standalone Wallet Libraries

If you prefer to use your own wallet, you can use standalone libraries:

EVM (Node.js with viem)

npm install viem
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}`,
);

EVM (Go)

import (
    "crypto/ecdsa"
    "github.com/ethereum/go-ethereum/crypto"
)

// Load private key from environment
privateKey, _ := crypto.HexToECDSA(os.Getenv("EVM_PRIVATE_KEY"))

EVM (Python)

Install the required package:
pip install eth_account
Then instantiate the wallet signer:
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)

Solana (SVM)

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!),
);

3. Make Paid Requests Automatically

You can automatically handle 402 Payment Required responses and complete payment flows using the x402 helper packages.
You can use either @x402/fetch or @x402/axios:
@x402/fetch extends the native fetch API to handle 402 responses and payment headers for you. Full example here
import { x402Client, wrapFetchWithPayment, x402HTTPClient } from "@x402/fetch";
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 schemes
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 body = await response.json();
console.log("Response:", body);

// 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);
}
Features:
  • Automatically handles 402 Payment Required responses
  • Verifies payment and generates PAYMENT-SIGNATURE headers
  • Retries the request with proof of payment
  • Supports all standard fetch options

Multi-Network Client Setup

You can register multiple payment schemes to handle different networks:
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
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!

4. Discover Available Services (Optional)

Instead of hardcoding endpoints, you can use the x402 Bazaar to dynamically discover available services. This is especially powerful for building autonomous agents that can find and use new capabilities.
import { HTTPFacilitatorClient } from "@x402/core/http";
import { withBazaar } from "@x402/extensions/bazaar";

// Create facilitator client with Bazaar extension
const facilitatorClient = withBazaar(
  new HTTPFacilitatorClient({
    url: "https://api.cdp.coinbase.com/platform/v2/x402"
  })
);

// Query available services
const discovery = await facilitatorClient.extensions.discovery.listResources({
  type: "http",
  limit: 20,
});

// Filter services by criteria
const affordableServices = discovery.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 x402 Bazaar documentation, including how to filter services, understand their schemas, and build agents that can autonomously discover new capabilities.

5. Paying with Any ERC-20 Token via Permit2 (EVM)

Some endpoints accept payment in non-USDC ERC-20 tokens via Permit2. The official TypeScript and Go client SDKs handle Permit2 automatically — no extra client code is needed. When a server advertises Permit2 as the transfer method (extra.assetTransferMethod: "permit2"), the client SDK creates the correct PermitWitnessTransferFrom payload instead of an EIP-3009 authorization.
Python clients currently support EIP-3009 only. Permit2 support is coming soon.

Gas Sponsorship (Automatic)

If the server declares a gas sponsorship extension (EIP-2612 or ERC-20), the TypeScript and Go client SDKs handle the Permit2 approval automatically:
  • EIP-2612 gas sponsoring: The client signs an off-chain permit() message. The facilitator submits the approval on-chain — no gas cost to you.
  • ERC-20 gas sponsoring: The client signs an approve() transaction. The facilitator broadcasts it on-chain before settling — no gas cost to you.
No additional client setup is needed for either case. The SDK detects the server’s advertised extension and responds accordingly.

One-Time Manual Approval (Fallback)

If the server uses Permit2 without gas sponsorship extensions, you must perform a one-time approval of the payment token to the Permit2 contract (0x000000000022D473030F116dDEE9F6B43aC78BA3) before your first payment. This only needs to be done once per token.
import { erc20Abi } from "viem";
import { walletClient } from "./your-wallet-setup";

await walletClient.writeContract({
  address: "0xYourTokenAddress",
  abi: erc20Abi,
  functionName: "approve",
  args: [
    "0x000000000022D473030F116dDEE9F6B43aC78BA3", // Permit2 contract
    BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), // max approval
  ],
});
After this one-time approval, all subsequent Permit2 payments for that token work automatically.
For full details on EVM transfer methods and gas sponsorship, see Network Support.

6. Error Handling

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);
  }
}

Summary

  • Install x402 client packages (@x402/fetch or @x402/axios) and mechanism packages (@x402/evm, @x402/svm)
  • Create a wallet signer
  • Create an x402Client and 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:

For questions or support, join our Discord.