X402 Payment Flow
The X402 protocol uses HTTP status code 402 (“Payment Required”) as a payment negotiation mechanism. Here’s how it works under the hood.
If you use the x402-fetch library, all of this is handled automatically. This page explains what happens behind the scenes.
Initial request
Your agent sends a POST request to the endpoint:
curl -X POST https://402claw.cloud/api/x402/nano-banana \
-H "Content-Type: application/json" \
-d '{"prompt": "A photorealistic cat riding a skateboard"}'Receive 402 challenge
The server responds with HTTP 402 Payment Required and includes payment details in the response body:
{
"error": "X402: Payment Required",
"accepts": [
{
"scheme": "exact",
"network": "base",
"asset": "USDC",
"amount": "50000",
"recipient": "0x1234...abcd"
}
],
"x402Version": 1
}The amount is in USDC’s smallest unit (6 decimals), so 50000 = $0.05 USDC.
Sign EIP-712 payment
Your agent creates an EIP-712 typed data signature using its wallet private key. This signature proves the agent authorizes the payment without making an on-chain transaction.
import { createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { base } from 'viem/chains'
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY)
const client = createWalletClient({ account, chain: base, transport: http() })
// The x402-fetch library handles this signing automatically
const signature = await client.signTypedData({
// ... EIP-712 typed data from the 402 response
})Retry with payment header
The agent retries the original request with the signed payment in the X-PAYMENT header:
curl -X POST https://402claw.cloud/api/x402/nano-banana \
-H "Content-Type: application/json" \
-H "X-PAYMENT: <base64-encoded-signed-payment>" \
-d '{"prompt": "A photorealistic cat riding a skateboard"}'Receive task ID
If the payment signature is valid, the server creates a generation task and returns:
{
"success": true,
"taskId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"statusUrl": "/api/task/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"message": "Generation started. Poll statusUrl for results."
}Poll for results
Poll the status URL every 2 seconds until you get a terminal status:
curl https://402claw.cloud/api/task/a1b2c3d4-e5f6-7890-abcd-ef1234567890Processing:
{ "taskId": "...", "status": "processing", "elapsed": 5 }Success:
{
"taskId": "...",
"status": "success",
"resultUrl": "https://cdn.example.com/generated-image.png",
"elapsed": 12
}Failed:
{
"taskId": "...",
"status": "failed",
"error": "Generation failed after 3 retries",
"code": "GENERATION_FAILED",
"retries": 3,
"elapsed": 45
}Important Notes
- No on-chain transaction needed — The EIP-712 signature authorizes payment without gas fees. The facilitator settles later.
- One payment per request — Each generation requires its own payment. Payments cannot be reused.
- Async by default — Results are not returned inline. You must poll the status endpoint.
- Auto-retry — The server automatically retries failed generations up to 3 times before marking as failed.
Rate Limits
| Endpoint | Limit |
|---|---|
POST /api/x402/* | 10 requests per 60 seconds per IP |
GET /api/task/* | 5 requests per second per IP |