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 USDCE_CONTRACT = '0xc01efAaF7C5C61bEbFAeb358E1161b537b8bC0e0'; // 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: USDCE_CONTRACT,
        description: 'Premium API data access',
        mimeType: 'application/json',
        maxAmountRequired: '1000000', // 1 USDC.e (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: USDCE_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.

3. Test Supported

See the Supported Endpoint for details.

4. Simulate Payment Flow

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?