Payments
x402 Flow
Accept payments from AI agents using the x402 protocol
The x402 protocol enables AI agents to autonomously pay for API access. When an agent hits a paid endpoint, payment is negotiated and settled within a single HTTP request cycle.
How x402 Works
- Agent requests a resource - Makes a standard HTTP request
- Server responds with 402 - Returns payment requirements
- Agent creates payment - Signs a transaction meeting requirements
- Agent retries with payment - Includes
X-Paymentheader - Server verifies and settles - Validates payment and returns resource
Agent Server
| |
|--- GET /api/data ----------------->|
| |
|<-- 402 Payment Required -----------|
| { accepts: [payment_req] } |
| |
|--- GET /api/data ----------------->|
| X-Payment: <signed_payload> |
| |
|<-- 200 OK -------------------------|
| { data: ... } |Agent Implementation
Interactive
import { MoneyMQ } from '@moneymq/sdk';import { wrapFetchWithPayment } from 'x402-fetch';const moneymq = new MoneyMQ({ endpoint: 'http://localhost:8488',});// Fetch catalogconst catalog = await moneymq.catalog.list();const product = catalog.data[0];// Get signer for sandbox account by labelconst payer = await moneymq.x402.getSigner({ tag: 'alice' });// Get x402 config from serverconst config = await moneymq.x402.getConfig();// Create payment-enabled fetch (max 10 USDC)const fetchWithPayment = wrapFetchWithPayment( fetch, payer, BigInt(10_000_000), // 10 USDC undefined, config,);// Access a paid API - payment is handled automaticallyconst response = await fetchWithPayment( product.accessUrl, { method: 'GET' },);const data = await response.json();console.log(data);Payment-Enabled Fetch
The wrapFetchWithPayment function wraps the standard fetch API to automatically handle 402 responses:
import { wrapFetchWithPayment } from 'x402-fetch';
const fetchWithPayment = wrapFetchWithPayment(
fetch,
signer,
maxAmount, // Maximum amount willing to pay
undefined, // Optional: preferred network
config, // x402 configuration
);
// Use like regular fetch
const response = await fetchWithPayment('https://api.example.com/data');Creating a Signer
From Sandbox Account
// Get signer for a sandbox test account
const payer = await moneymq.x402.getSigner({ tag: 'alice' });From Private Key
import { createSigner } from 'x402-fetch';
const signer = await createSigner('solana', privateKeyHex, {
svmConfig: rpcUrl,
});Configuration
Get the x402 configuration from your MoneyMQ server:
const config = await moneymq.x402.getConfig();
// Config includes:
// - Facilitator URL
// - Supported networks
// - Token addressesPayment Requirements
When a server responds with 402, it includes payment requirements:
{
"accepts": [
{
"network": "solana",
"currency": "USDC",
"maxAmountRequired": "1000000",
"payTo": "recipient_address",
"extra": {
"product": "prod_xxxxx"
}
}
]
}Setting Maximum Payment
Control how much your agent is willing to pay:
// Pay up to 1 USDC
const fetchWithPayment = wrapFetchWithPayment(
fetch,
signer,
BigInt(1_000_000), // 1 USDC (6 decimals)
);
// Pay up to 0.10 USDC
const fetchWithPayment = wrapFetchWithPayment(
fetch,
signer,
BigInt(100_000), // 0.10 USDC
);Error Handling
try {
const response = await fetchWithPayment(url);
const data = await response.json();
} catch (error) {
if (error.code === 'INSUFFICIENT_FUNDS') {
console.error('Agent wallet needs more funds');
} else if (error.code === 'PAYMENT_REJECTED') {
console.error('Server rejected the payment');
} else if (error.code === 'MAX_AMOUNT_EXCEEDED') {
console.error('Price exceeds maximum willing to pay');
}
}Next Steps
- Payment Events - Real-time payment notifications
- Checkout Flow - Accept user payments