Quick Start for Sellers
This section explains how sellers (API providers, resource servers) can integrate x402 payment verification and settlement into their services. For the buyer-side implementation, see Quick Start for Buyers.
Prerequisites
Cronos-compatible wallet for receiving payments
Integration Steps
Detect Payment Requirement: Check if the requested resource requires payment
Respond with 402: Return payment requirements to the buyer
Extract Payment Header: Buyer retries with signed authorization in
X-PAYMENTVerify Payment: Forward to facilitator's Verify Endpoint
Settle Payment: If valid, call the Settle Endpoint
Deliver Resource: Return protected content with 200 OK
Complete Payment Flow
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// Configuration
const FACILITATOR_URL = 'https://facilitator.cronoslabs.org/v2/x402';
const SELLER_WALLET = process.env.SELLER_WALLET;
const USDX_CONTRACT = '0x149a72BCdFF5513F2866e9b6394edba2884dbA07'; // Cronos testnet - see Network Constants
// Protected API endpoint
app.get('/api/premium-data', async (req, res) => {
const paymentHeader = req.headers['X-PAYMENT'] || req.body?.paymentHeader;
// Step 1: Check if payment is provided
if (!paymentHeader) {
return res.status(402).json({
error: 'Payment Required',
x402Version: 1,
paymentRequirements: {
scheme: 'exact',
network: 'cronos-testnet', // Switch to 'cronos' for Cronos mainnet
payTo: SELLER_WALLET,
asset: USDX_CONTRACT,
description: 'Premium API data access',
mimeType: 'application/json',
maxAmountRequired: '1000000', // 1 USDX (6 decimals)
maxTimeoutSeconds: 300
}
});
}
try {
const requestBody = {
x402Version: 1,
paymentHeader: paymentHeader,
paymentRequirements: {
scheme: 'exact',
network: 'cronos-testnet', // Same network as in 402 response
payTo: SELLER_WALLET,
asset: USDX_CONTRACT,
description: 'Premium API data access',
mimeType: 'application/json',
maxAmountRequired: '1000000',
maxTimeoutSeconds: 300
}
};
// Step 2: Verify payment
const verifyRes = await axios.post(`${FACILITATOR_URL}/verify`, requestBody, {
headers: { 'Content-Type': 'application/json', 'X402-Version': '1' }
});
if (!verifyRes.data.isValid) {
return res.status(402).json({
error: 'Invalid payment',
reason: verifyRes.data.invalidReason
});
}
// Step 3: Settle payment
const settleRes = await axios.post(`${FACILITATOR_URL}/settle`, requestBody, {
headers: { 'Content-Type': 'application/json', 'X402-Version': '1' }
});
// Step 4: Check settlement and return content
if (settleRes.data.event === 'payment.settled') {
return res.status(200).json({
data: {
premiumContent: 'This is your premium data',
},
payment: {
txHash: settleRes.data.txHash,
from: settleRes.data.from,
to: settleRes.data.to,
value: settleRes.data.value,
blockNumber: settleRes.data.blockNumber,
timestamp: settleRes.data.timestamp
}
});
} else {
return res.status(402).json({
error: 'Payment settlement failed',
reason: settleRes.data.error
});
}
} catch (error) {
return res.status(500).json({
error: 'Server error processing payment',
details: error.response?.data || error.message
});
}
});
app.listen(3000);Testing Your Integration
1. Test Environment
The facilitator uses a single base URL for both networks:
Facilitator URL:
https://facilitator.cronoslabs.org/v2/x402Network Selection: Specify via
"network"field in payment requirementsTestnet:
"network": "cronos-testnet"(Chain ID:338)Mainnet:
"network": "cronos"(Chain ID:25)
2. Test Health Check
See the Health Check Endpoint for details.
curl -X GET https://facilitator.cronoslabs.org/healthcheck3. Test Supported
See the Supported Endpoint for details.
curl -X GET https://facilitator.cronoslabs.org/v2/x402/supported4. Simulate Payment Flow
# Request without payment (should return 402)
curl -X GET http://localhost:3000/api/premium-data
# Request with payment header (after signing)
curl -X GET http://localhost:3000/api/premium-data \
-H "X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MS4uLn0="5. Test Edge Cases
See Verify Endpoint and Settle Endpoint for complete error documentation.
Invalid signature
{"isValid": false, "invalidReason": "Invalid EIP-3009 signature"}
Wrong network
{"isValid": false, "invalidReason": "Unsupported network: ethereum-mainnet"}
Duplicate nonce
{"event": "payment.failed", "error": "Authorization already used"}
Expired auth
{"event": "payment.failed", "error": "Authorization expired"}
6. Monitor Transactions
Check facilitator response for
txHashandblockNumberView on Cronos Block Explorer:
https://explorer.cronos.org/testnet/tx/[txHash]
Last updated
Was this helpful?