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

  1. Detect Payment Requirement: Check if the requested resource requires payment

  2. Respond with 402: Return payment requirements to the buyer

  3. Extract Payment Header: Buyer retries with signed authorization in X-PAYMENT

  4. Verify Payment: Forward to facilitator's Verify Endpoint

  5. Settle Payment: If valid, call the Settle Endpoint

  6. 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);

Note: For Python, Go, or other language examples, the integration pattern is identical: make HTTP POST requests to /verify and /settle with the same JSON structure.

Testing Your Integration

1. Test Environment

The facilitator uses a single base URL for both networks:

  • Facilitator URL: https://facilitator.cronoslabs.org/v2/x402

  • Network Selection: Specify via "network" field in payment requirements

    • Testnet: "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/healthcheck

3. Test Supported

See the Supported Endpoint for details.

curl -X GET https://facilitator.cronoslabs.org/v2/x402/supported

4. 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.

Scenario
Expected Response

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 txHash and blockNumber

  • View on Cronos Block Explorer: https://explorer.cronos.org/testnet/tx/[txHash]

Last updated

Was this helpful?