x402 is a revolutionary open payment protocol developed by Coinbase that enables instant, automatic stablecoin payments directly over HTTP. It empowers AI agents to autonomously pay for services without subscriptions or API keys, unlocking truly autonomous, monetized chat agents capable of reasoning, transacting, and delivering value seamlessly.
What is x402?
x402 transforms how agents interact with paid services by embedding payments directly into HTTP requests. Instead of managing API keys or subscriptions, your agents can pay for exactly what they use, when they use it.
Key Benefits
Autonomous economic transactions - Agents can transact without human intervention
Pay-as-you-go monetization - Only pay for the services you actually use
Minimal setup - Often requires just one middleware line
Instant settlement - Payments are verified on-chain in real-time
Protocol Flow
Understanding the x402 payment flow is essential for building autonomous agents:
Initial Request
Client requests access to a protected resource.
Payment Required Response
Server returns HTTP 402 status with payment details including:
Payment amount
Recipient address
Payment reference
Payment Execution
Client sends payment payload via HTTP header (e.g., X-PAYMENT
). The payment facilitator handles the on-chain settlement verification automatically.
Content Delivery
Client retries the original request, and server responds with:
Requested content
Payment confirmation header (e.g., X-PAYMENT-RESPONSE
)
Integrating x402 with XMTP Agents
Combining x402 with XMTP chat agents creates powerful autonomous economic agents. Here’s how to implement this integration:
Agent Architecture
Your agent needs to handle three main scenarios:
Free requests - Standard queries that don’t require payment
Payment-gated requests - Premium features that trigger x402 payments
Payment failures - Graceful handling when payments fail
Basic Implementation
Here’s how your agent handles payment-gated requests:
// Agent receives user request for premium feature
async function handlePremiumRequest ( message : string , conversation : any ) {
try {
// Attempt to access premium service
const response = await fetch ( "/premium-api/nft-floor-price" , {
method: "GET" ,
headers: {
"Content-Type" : "application/json"
}
});
// Check if payment is required
if ( response . status === 402 ) {
const paymentDetails = await response . json ();
// Notify user about payment requirement
await conversation . send ( `💰 This requires a payment of ${ paymentDetails . amount } USDC. Processing...` );
// Execute payment
const paymentPayload = await executePayment ( paymentDetails );
// Retry request with payment
const retryResponse = await fetch ( "/premium-api/nft-floor-price" , {
headers: {
"X-PAYMENT" : paymentPayload ,
"Content-Type" : "application/json"
}
});
if ( retryResponse . ok ) {
const data = await retryResponse . json ();
await conversation . send ( `📊 NFT floor price: ${ data . floorPrice } ETH` );
} else {
await conversation . send ( "❌ Payment processed but service unavailable. Please try again." );
}
} else if ( response . ok ) {
// Handle free-tier response
const data = await response . json ();
await conversation . send ( `📊 NFT floor price: ${ data . floorPrice } ETH` );
}
} catch ( error ) {
await conversation . send ( "❌ Unable to fetch data. Please try again later." );
}
}
Payment Execution Function
Implement the payment logic using Coinbase’s x402 SDK:
import { PaymentFacilitator } from '@coinbase/x402-sdk' ;
async function executePayment ( paymentDetails : any ) : Promise < string > {
const facilitator = new PaymentFacilitator ({
privateKey: process . env . AGENT_PRIVATE_KEY ,
network: 'base' // or 'mainnet'
});
try {
const payment = await facilitator . createPayment ({
amount: paymentDetails . amount ,
recipient: paymentDetails . recipient ,
reference: paymentDetails . reference ,
currency: 'USDC'
});
return payment . payload ;
} catch ( error ) {
throw new Error ( `Payment failed: ${ error . message } ` );
}
}
Complete Agent Example
Here’s a full implementation combining XMTP with x402:
Complete Agent
Server Setup
import { Client } from "@xmtp/node-sdk" ;
import { PaymentFacilitator } from '@coinbase/x402-sdk' ;
class AutonomousPaymentAgent {
private client : Client ;
private facilitator : PaymentFacilitator ;
constructor ( client : Client , privateKey : string ) {
this . client = client ;
this . facilitator = new PaymentFacilitator ({
privateKey ,
network: process . env . NETWORK || 'base'
});
}
async handleMessage ( message : any ) {
const conversation = await this . client . conversations . getConversationById (
message . conversationId
);
const content = message . content ;
// Route messages based on content
if ( content . includes ( 'floor price' )) {
await this . handleFloorPriceRequest ( conversation , content );
} else if ( content . includes ( 'market data' )) {
await this . handleMarketDataRequest ( conversation , content );
} else {
await conversation . send ( "Hi! I can help with: \n • NFT floor prices \n • Market data \n\n Just ask!" );
}
}
async handleFloorPriceRequest ( conversation : any , content : string ) {
// Extract collection name from message
const collection = this . extractCollection ( content );
if ( ! collection ) {
await conversation . send ( "Please specify an NFT collection name." );
return ;
}
try {
const response = await fetch ( `/api/nft-floor/ ${ collection } ` );
if ( response . status === 402 ) {
await this . processPaymentAndRetry (
conversation ,
`/api/nft-floor/ ${ collection } ` ,
`📊 Floor price for ${ collection } :`
);
} else if ( response . ok ) {
const data = await response . json ();
await conversation . send ( `📊 ${ collection } floor price: ${ data . floorPrice } ETH` );
}
} catch ( error ) {
await conversation . send ( "❌ Unable to fetch floor price data." );
}
}
async processPaymentAndRetry ( conversation : any , endpoint : string , successPrefix : string ) {
try {
// Initial request to get payment details
const response = await fetch ( endpoint );
const paymentDetails = await response . json ();
// Notify user of payment
await conversation . send ( `💰 Payment required: ${ paymentDetails . amount } USDC. Processing...` );
// Execute payment
const payment = await this . facilitator . createPayment ({
amount: paymentDetails . amount ,
recipient: paymentDetails . recipient ,
reference: paymentDetails . reference ,
currency: 'USDC'
});
// Retry with payment
const retryResponse = await fetch ( endpoint , {
headers: { "X-PAYMENT" : payment . payload }
});
if ( retryResponse . ok ) {
const data = await retryResponse . json ();
await conversation . send ( ` ${ successPrefix } ${ JSON . stringify ( data , null , 2 ) } ` );
} else {
await conversation . send ( "❌ Payment processed but service error occurred." );
}
} catch ( error ) {
await conversation . send ( `❌ Payment failed: ${ error . message } ` );
}
}
private extractCollection ( content : string ) : string | null {
// Simple extraction logic - enhance based on your needs
const words = content . toLowerCase (). split ( ' ' );
const collectionIndex = words . findIndex ( word =>
[ 'cryptopunks' , 'bayc' , 'azuki' , 'pudgypenguins' ]. includes ( word )
);
return collectionIndex !== - 1 ? words [ collectionIndex ] : null ;
}
}
Real-World Examples
Several projects have successfully implemented x402 with XMTP agents:
Stableburn x402
A live implementation showcasing:
XMTP v4 integration
AgentKit functionality
x402-based micro-payments (0.001 – 0.001– 0.001– 0.005 per request)
Automatic revenue burning via on-chain token swaps
Stableburn x402 Autonomous agent that monetizes premium endpoints with micro-payments
Crossmint Worldstore Agent
An XMTP chat agent for shopping featuring:
x402 payment integration
EIP-3009 gasless USDC transactions
Base network integration
Interactive content types in chat
Worldstore Agent Shopping agent with embedded x402 payments and commerce functionality
Best Practices
Payment UX Guidelines
Always inform users about payment requirements before executing transactions. Transparency builds trust with your agent.
Clear pricing - Display exact costs upfront
Payment confirmation - Confirm successful payments
Graceful failures - Handle payment errors elegantly
Value communication - Explain what users get for their payment
Error Handling
Implement comprehensive error handling for common scenarios:
async function robustPaymentHandler ( conversation : any , endpoint : string ) {
try {
const response = await fetch ( endpoint );
if ( response . status === 402 ) {
const paymentDetails = await response . json ();
// Validate payment details
if ( ! paymentDetails . amount || ! paymentDetails . recipient ) {
await conversation . send ( "❌ Invalid payment request from service." );
return ;
}
// Check if amount is reasonable
if ( parseFloat ( paymentDetails . amount ) > 1.0 ) {
await conversation . send ( `⚠️ High payment amount: ${ paymentDetails . amount } USDC. Skipping for safety.` );
return ;
}
// Process payment with timeout
const paymentPromise = this . executePayment ( paymentDetails );
const timeoutPromise = new Promise (( _ , reject ) =>
setTimeout (() => reject ( new Error ( 'Payment timeout' )), 30000 )
);
const payment = await Promise . race ([ paymentPromise , timeoutPromise ]);
// Retry with payment
const retryResponse = await fetch ( endpoint , {
headers: { "X-PAYMENT" : payment }
});
if ( retryResponse . ok ) {
const data = await retryResponse . json ();
await conversation . send ( `✅ Payment successful! ${ JSON . stringify ( data ) } ` );
} else {
await conversation . send ( "❌ Payment processed but service unavailable." );
}
}
} catch ( error ) {
if ( error . message . includes ( 'timeout' )) {
await conversation . send ( "⏱️ Payment timed out. Please try again." );
} else if ( error . message . includes ( 'insufficient funds' )) {
await conversation . send ( "💸 Insufficient funds for payment." );
} else {
await conversation . send ( `❌ Payment error: ${ error . message } ` );
}
}
}
Security Considerations
Never expose private keys in your code. Always use environment variables and secure key management practices.
Key management - Use secure environment variables
Payment limits - Set maximum payment thresholds
Rate limiting - Prevent payment spam attacks
Audit trails - Log all payment activities
Network validation - Verify on-chain settlement
Resources
Next Steps
Ready to build your autonomous payment agent? Here’s your roadmap:
Set up development environment
Install the x402 SDK and XMTP client libraries in your project.
Add payment functionality
Integrate x402 payment handling using the examples above.
Test thoroughly
Test payment flows on testnet before deploying to production.
Deploy and monitor
Deploy your agent and monitor payment transactions and user interactions.
The future of autonomous agents is here. With x402 and XMTP, you can build agents that truly operate independently in the digital economy.