Skip to main content
A facilitator in the x402 protocol is an HTTP service that processes payments and provides settlement. It exposes /accepts and /settle endpoints that work with x402 middleware to handle payment flows.

Prerequisites

  • Understanding of x402 protocol
  • Node.js and npm installed
  • A SKALE Chain endpoint
  • Understanding of HTTP services
  • Familiarity with TypeScript/JavaScript

Overview

A facilitator service:
  1. Exposes /accepts endpoint - Returns payment requirements for resources
  2. Exposes /settle endpoint - Validates and processes payment settlements
  3. Handles payment verification
  4. May charge fees for services

Quick Start

Install the facilitator package:
npm install @faremeter/facilitator

Basic Facilitator Service

Here’s a simple facilitator service:
import express from 'express';
import { createFacilitator } from '@faremeter/facilitator';

const app = express();
app.use(express.json());

const facilitator = createFacilitator({
  network: 'skale-base-sepolia',
  paymentHandlers: [
    {
      scheme: 'exact',
      network: 'skale-base-sepolia',
      handler: async (payment) => {
        return { success: true };
      },
    },
  ],
});

// Mount facilitator routes
app.use('/facilitator', facilitator.router);

app.listen(3000, () => {
  console.log('Facilitator running on port 3000');
});

Facilitator Endpoints

/accepts

Returns payment requirements for a given resource:
app.get('/accepts', async (req, res) => {
  const { resource } = req.query;
  
  const requirements = {
    accepts: [
      {
        scheme: 'exact',
        network: 'skale-base-sepolia',
        maxAmountRequired: '1.5',
        description: 'SKALE USDC payment',
      },
    ],
  };
  
  res.json(requirements);
});

/settle

Validates and processes payment settlements:
app.post('/settle', async (req, res) => {
  const payment = req.body;
  const isValid = await validatePayment(payment);
  
  if (!isValid) {
    return res.status(400).json({ error: 'Invalid payment' });
  }
  
  const result = await processSettlement(payment);
  res.json({ success: true, result });
});

Payment Handler

Implement payment handlers for different schemes:
import { createPaymentHandler } from '@faremeter/payment-evm';

const paymentHandler = createPaymentHandler({
  network: 'skale-base-sepolia',
  rpcUrl: 'YOUR_SKALE_RPC_URL',
  verifyPayment: async (payment) => {
    return true;
  },
  settlePayment: async (payment) => {
    return { txHash: '0x...' };
  },
});

Fee Management

Add fee calculation to your facilitator:
const facilitator = createFacilitator({
  network: 'skale-base-sepolia',
  feeBasisPoints: 100,
  paymentHandlers: [paymentHandler],
  calculateFee: (amount) => {
    return (amount * 100) / 10000;
  },
});

Error Handling

app.post('/settle', async (req, res) => {
  try {
    const result = await facilitator.settle(req.body);
    res.json(result);
  } catch (error) {
    if (error.code === 'INVALID_SIGNATURE') {
      return res.status(400).json({ error: 'Invalid payment signature' });
    }
    if (error.code === 'EXPIRED_PAYMENT') {
      return res.status(400).json({ error: 'Payment expired' });
    }
    if (error.code === 'INSUFFICIENT_AMOUNT') {
      return res.status(400).json({ error: 'Insufficient payment amount' });
    }
    res.status(500).json({ error: 'Internal server error' });
  }
});

Next Steps

Resources