Skip to main content

Payment Schemes

The facilitator supports two x402 payment schemes: exact and escrow. Understanding when to use each is key to building efficient applications.

Overview

exact

Standard x402 per-request payments. USDC only.

escrow

Multi-token payments with automatic swaps. Pay with any token, receiver gets USDC.

Exact Scheme

The exact scheme is the standard x402 payment method. Each API request requires an ERC-3009 signature authorizing the exact USDC payment amount.

How It Works

Characteristics

PropertyValue
Input tokenUSDC only
Signature typeERC-3009 transferWithAuthorization
Gas for userNone (gasless)
SettlementDirect USDC transfer

When to Use

  • USDC holders: Users already have USDC
  • Simple integration: No swap complexity
  • Predictable costs: Exact amounts, no slippage

Server Configuration

import { x402ResourceServer, HTTPFacilitatorClient } from '@x402/core/server';
import { ExactEvmScheme } from '@x402/evm/exact/server';
import { paymentMiddleware } from '@x402/express';

const facilitator = new HTTPFacilitatorClient({
  url: 'https://facilitator.agentokratia.com',
  createAuthHeaders: async () => ({
    verify: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
    settle: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
  }),
});

const server = new x402ResourceServer(facilitator)
  .register('eip155:8453', new ExactEvmScheme());

app.use(paymentMiddleware({
  'GET /api/endpoint': {
    accepts: {
      scheme: 'exact',
      price: '$0.10',
      network: 'eip155:8453',
      payTo: '0xYourAddress...',
    },
  },
}, server));

Client Usage

import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount(process.env.PRIVATE_KEY);

const client = new x402Client()
  .register('eip155:8453', new ExactEvmScheme(account));

const paidFetch = wrapFetchWithPayment(fetch, client);

const response = await paidFetch('https://api.example.com/endpoint');

Escrow Scheme

The escrow scheme enables multi-token payments. Users can pay with WETH, DAI, USDT, or USDC. The facilitator automatically swaps non-USDC tokens to USDC before paying the receiver.

How It Works

Characteristics

PropertyValue
Input tokensUSDC, WETH, DAI, USDT
Output tokenAlways USDC (to receiver)
Signature typeERC-3009 (USDC) or Permit2 (other tokens)
Gas for userNone (gasless)
DEX aggregatorsUniswap, Paraswap, OpenOcean

When to Use

  • Multi-token support: Accept payments in any supported token
  • Better UX: Users don’t need to swap to USDC first
  • AI agents: Agents can pay with whatever token they hold

Server Configuration

import { x402ResourceServer, HTTPFacilitatorClient } from '@x402/core/server';
import { ExactEvmScheme } from '@x402/evm/exact/server';
import { EscrowScheme } from '@agentokratia/x402-escrow/server';
import { paymentMiddleware } from '@x402/express';

const facilitator = new HTTPFacilitatorClient({
  url: 'https://facilitator.agentokratia.com',
  createAuthHeaders: async () => ({
    verify: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
    settle: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
  }),
});

const escrow = new EscrowScheme({ facilitator });

const server = new x402ResourceServer(facilitator)
  .register('eip155:8453', new ExactEvmScheme())
  .register('eip155:8453', escrow);

// Auto-discovers supported tokens and fetches quotes
const escrowAccepts = await escrow.buildAccepts({
  network: 'eip155:8453',
  price: '$0.01',
  payTo: '0xYourAddress...',
});

app.use(paymentMiddleware({
  'GET /api/endpoint': {
    accepts: [
      { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: '0x...' },
      ...escrowAccepts, // Adds USDC, WETH, DAI, USDT options
    ],
  },
}, server));
The buildAccepts() method returns an array of payment options for each supported input token. Spreading ...escrowAccepts into your accepts array enables multi-token payments.

Client Usage

import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm/exact/client';
import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
import {
  EscrowScheme,
  createBalanceSelector,
  preferTokenPolicy,
} from '@agentokratia/x402-escrow/client';

const WETH = '0x4200000000000000000000000000000000000006';
const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';

const account = privateKeyToAccount(process.env.PRIVATE_KEY);

const walletClient = createWalletClient({
  account, chain: base, transport: http(),
});

const publicClient = createPublicClient({
  chain: base, transport: http(),
});

// Balance-aware: auto-picks token you can afford
const client = new x402Client(
  createBalanceSelector(publicClient, account.address)
)
  .register('eip155:8453', new ExactEvmScheme(account))
  .register('eip155:8453', new EscrowScheme(walletClient))
  .registerPolicy(preferTokenPolicy([WETH, USDC]));

const paidFetch = wrapFetchWithPayment(fetch, client);

const response = await paidFetch('https://api.example.com/endpoint');

Token Selection

The client SDK provides two ways to control which token is used:

Balance-Aware Selection

createBalanceSelector checks on-chain balances and picks the first token the user can afford:
const client = new x402Client(
  createBalanceSelector(publicClient, account.address)
);

Token Preference Policy

preferTokenPolicy reorders payment options by your preferred token order:
const client = new x402Client(
  createBalanceSelector(publicClient, account.address)
)
  .registerPolicy(preferTokenPolicy([WETH, USDC, DAI]));
This prefers WETH first, then USDC, then DAI.

Accepting Both Schemes

Servers can accept both schemes, letting clients choose based on what tokens they hold:
const escrow = new EscrowScheme({ facilitator });
const escrowAccepts = await escrow.buildAccepts({
  network: 'eip155:8453',
  price: '$0.01',
  payTo: '0xYourAddress...',
});

app.use(paymentMiddleware({
  'GET /api/endpoint': {
    accepts: [
      { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: '0x...' },
      ...escrowAccepts,
    ],
  },
}, server));
The client will automatically select the best option based on:
  1. Token balances (via createBalanceSelector)
  2. Token preferences (via preferTokenPolicy)

Comparison Summary

Aspectexactescrow
Input tokensUSDC onlyUSDC, WETH, DAI, USDT
SignatureERC-3009ERC-3009 or Permit2
Gas for userNoneNone
Swap neededNoYes (for non-USDC)
SlippageNone~0.5% (configurable)
ComplexitySimpleMore setup
Best forUSDC holdersMulti-token flexibility