Book402 runs its own x402 facilitator — no dependency on Coinbase CDP or any third party.

What Is a Facilitator?

In the x402 protocol, a facilitator is a server that:

  1. Verifies payment signatures (checks that the agent signed a valid USDC transfer)
  2. Settles payments (submits the actual USDC transfer on-chain)
graph TD subgraph External["❌ External Facilitator (CDP)"] A1[Your API] -->|"verify/settle"| B1[Coinbase CDP] B1 -->|"needs API key"| C1[Rate limits] C1 --> D1[Third-party dependency] end subgraph SelfHosted["✅ Self-Hosted (Book402)"] A2[Book402 API] -->|"verify/settle"| B2[x402-rs on localhost] B2 -->|"direct RPC"| C2[Base L2] C2 --> D2[Full control] end style SelfHosted fill:#0a1a0a,stroke:#33aa33 style External fill:#1a0a0a,stroke:#aa3333

Why Self-Host?

Option Supports Mainnet Auth Required Rate Limits Control
x402.org ❌ Sepolia only ?
Coinbase CDP ✅ API key 1K/mo free
Self-hosted None

Our Setup

We use x402-rs — a production-grade Rust implementation:

  • Image: ghcr.io/x402-rs/x402-facilitator:latest
  • Runtime: Docker on QuimServer
  • Port: 127.0.0.1:8402 (not exposed to internet)
  • Networks: Base mainnet + Base Sepolia

Docker Setup

# config.json
{
  "port": 8080,
  "host": "0.0.0.0",
  "chains": {
    "eip155:8453": {
      "eip1559": true,
      "signers": ["0xYOUR_PRIVATE_KEY"],
      "rpc": [{ "http": "https://mainnet.base.org", "rate_limit": 50 }]
    }
  },
  "schemes": [
    { "id": "v1-eip155-exact", "chains": "eip155:*" },
    { "id": "v2-eip155-exact", "chains": "eip155:*" }
  ]
}
docker run -d \
  --name x402-facilitator \
  --restart unless-stopped \
  -v ./config.json:/app/config.json:ro \
  -p 127.0.0.1:8402:8080 \
  ghcr.io/x402-rs/x402-facilitator:latest

Verify It's Running

curl http://localhost:8402/supported
{
  "kinds": [
    { "x402Version": 1, "scheme": "exact", "network": "base" },
    { "x402Version": 2, "scheme": "exact", "network": "eip155:8453" }
  ],
  "signers": {
    "eip155:8453": ["0x6B1925e4a1f779797eF51A18A4694B59FFb60Aba"]
  }
}

Integration with Express

The API server connects to the facilitator via HTTPFacilitatorClient:

import { paymentMiddleware, x402ResourceServer } from '@x402/express';
import { HTTPFacilitatorClient } from '@x402/core/server';
import { ExactEvmScheme } from '@x402/evm/exact/server';

const facilitatorClient = new HTTPFacilitatorClient({
  url: 'http://127.0.0.1:8402'  // Local facilitator
});

const resourceServer = new x402ResourceServer(facilitatorClient)
  .register('eip155:8453', new ExactEvmScheme());

// Define paid routes
const paidRoutes = {
  'GET /search/hybrid': {
    accepts: { scheme: 'exact', price: '$0.01', network: 'eip155:8453' },
    payTo: '0x6B1925e4a1f779797eF51A18A4694B59FFb60Aba',
    description: 'Hybrid BM25+vector book search'
  }
};

app.use(paymentMiddleware(paidRoutes, resourceServer));

Facilitator API

The facilitator exposes these internal endpoints:

Endpoint Method Description
/supported GET List supported payment kinds and networks
/verify POST Verify a payment signature
/settle POST Settle a verified payment on-chain

Security

The facilitator listens on 127.0.0.1 only — it's never exposed to the internet. Only the Book402 API server talks to it.