Skip to content

Self-Hosted Facilitator

What is a Facilitator?

The facilitator verifies x402 payments. It:

  1. Decodes payment proof from the client
  2. Verifies the EIP-712 signature
  3. Checks nonce uniqueness
  4. Submits payment to the USDC contract
  5. Confirms receipt to the API server

Default public facilitator: https://x402.org/facilitator

Why Self-Host?

ReasonBenefit
Lower latencyNo third-party round-trip (~50-100ms saved)
Full controlCustom verification logic
PrivacyPayment data stays internal
ReliabilityNo dependency on public service
CostFree for your own endpoints

Setup

git clone https://github.com/x402/facilitator
cd facilitator
npm install
cp .env.example .env

Configuration

Edit .env:

# Required
RPC_URL=https://mainnet.base.org
CHAIN_ID=8453
PORT=3000

# Optional
LOG_LEVEL=info
REDIS_URL=redis://localhost:6379  # For nonce tracking
RECEIVER_ADDRESS=0x_your_receiver_address

Start

npm start
# Facilitator running on http://localhost:3000

Docker

docker build -t x402-facilitator .
docker run -d -p 3000:3000 --env-file .env x402-facilitator

Point Client to Your Facilitator

client = X402Client(
    wallet=wallet,
    facilitator_url="http://localhost:3000"
)

API Endpoints

Verify Payment

POST /verify
Content-Type: application/json

{
  "payment_proof": "base64_encoded_proof",
  "requirements": {
    "amount": "10000",
    "token": "0x833589...",
    "network": "base"
  }
}

# Response
{
  "valid": true,
  "tx_hash": "0x_abc123...",
  "amount": "10000",
  "payer": "0x_wallet_address"
}

Check Nonce

GET /nonce/:nonce

# Response
{ "used": false }

Production Tips

  1. Use a dedicated RPC (Alchemy, Infura) for reliability
  2. Add Redis for distributed nonce tracking
  3. Run behind a reverse proxy (nginx) with SSL
  4. Monitor with Prometheus metrics (built-in at /metrics)
  5. Scale horizontally — facilitator is stateless (except nonce DB)

Architecture

Client -> 4SEC API -> Your Facilitator -> Base RPC
                              |
                         Redis (nonces)

Troubleshooting

IssueFix
RPC connection failedCheck RPC_URL and network
Nonce collisionEnsure Redis is running
High latencyUse dedicated RPC provider
Signature invalidCheck chain ID matches Base (8453)

Released under the MIT License.