Skip to main content

x402 Payments

The x402 protocol enables pay-per-request API access using cryptocurrency.

How It Works

The 402 Response

When free tier is exhausted, you receive:

{
"error": true,
"code": "PAYMENT_REQUIRED",
"price": "$0.01",
"priceUSD": 0.01,
"network": {
"name": "Base",
"chainId": 8453
},
"asset": "USDC",
"recipient": "0xF499102c8707c6501CaAdD2028c6DF1c6C6E813b",
"x402": {
"version": "1",
"facilitator": "https://api.cdp.coinbase.com/platform/v2/x402"
}
}

Payment Flow

1. Free Tier First

Every IP/wallet gets 100 free calls per day. No payment needed.

curl https://api.web3identity.com/api/ens/resolve/vitalik.eth
# Works! Returns data.

2. 402 Response

After exhausting free tier:

curl https://api.web3identity.com/api/ens/nick.eth
# Returns 402 with payment instructions

3. Sign Authorization

Sign an EIP-712 TransferWithAuthorization message permitting USDC transfer:

const signature = await wallet.signTypedData({
domain: { name: 'USDC', version: '2', chainId: 8453 },
types: { TransferWithAuthorization: [...] },
message: {
from: yourWallet,
to: recipientWallet,
value: priceInWei,
validAfter: 0,
validBefore: deadline,
nonce: randomNonce,
},
});

4. Retry with Payment

Send both headers with identical value (required by x402 adapter):

curl -X GET "https://api.web3identity.com/api/ens/nick.eth" \
-H "x-payment: <payment_json_base64>" \
-H "payment-signature: <payment_json_base64>"
Both Headers Required

The x402 adapter requires both x-payment AND payment-signature headers with the same payment payload. This is due to timing in the @x402/express middleware.

Raw Payment Example (Without SDK)

For developers implementing x402 manually:

import { createWalletClient, http, encodeAbiParameters } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

// 1. Make request, get 402
const res = await fetch('https://api.web3identity.com/api/ens/nick.eth');
if (res.status !== 402) { /* handle response */ }

const paymentReq = await res.json();
// paymentReq.priceUSD = 0.01
// paymentReq.recipient = "0xF499..."

// 2. Prepare EIP-3009 TransferWithAuthorization
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour
const nonce = crypto.randomBytes(32);

// 3. Sign the authorization
const wallet = createWalletClient({
account: privateKeyToAccount(WALLET_KEY),
chain: base,
transport: http()
});

const signature = await wallet.signTypedData({
domain: {
name: 'USD Coin',
version: '2',
chainId: 8453,
verifyingContract: USDC_BASE
},
types: {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' }
]
},
primaryType: 'TransferWithAuthorization',
message: {
from: wallet.account.address,
to: paymentReq.recipient,
value: BigInt(paymentReq.priceUSD * 1e6), // USDC has 6 decimals
validAfter: 0n,
validBefore: BigInt(deadline),
nonce: nonce
}
});

// 4. Build payment header
const payment = {
x402Version: 1,
scheme: 'exact',
network: 'eip155:8453',
payload: {
signature,
authorization: {
from: wallet.account.address,
to: paymentReq.recipient,
value: String(paymentReq.priceUSD * 1e6),
validAfter: '0',
validBefore: String(deadline),
nonce: '0x' + nonce.toString('hex')
}
}
};

const paymentHeader = Buffer.from(JSON.stringify(payment)).toString('base64');

// 5. Retry with payment
const paidRes = await fetch('https://api.web3identity.com/api/ens/nick.eth', {
headers: {
'x-payment': paymentHeader,
'payment-signature': paymentHeader // BOTH required
}
});

const data = await paidRes.json();
// Success! Payment settled via CDP facilitator

Pricing

Endpoint TypePrice
ENS Resolution$0.01
Farcaster Profile$0.01
Token Prices$0.001
Batch Operations$0.02
Historical Data$0.05

Why x402?

For Developers:

  • No API key signup required
  • Pay only for what you use
  • Works with any wallet

For the API:

  • Sustainable revenue model
  • No free tier abuse
  • Automatic settlement

SDK Support

The SDK handles payments automatically:

import { ATVClient } from '@atv-eth/x402-sdk';

const client = new ATVClient({
privateKey: process.env.WALLET_KEY,
});

// SDK handles 402 → sign → retry automatically
const profile = await client.getProfile('nick.eth');

Network Details

PropertyValue
NetworkBase (Chain ID 8453)
AssetUSDC
FacilitatorCoinbase CDP
SettlementInstant