Skip to content

Quickstart

Get the x402 Facilitator running locally in under 5 minutes.

Prerequisites

RequirementVersion
Docker + Docker ComposeAny recent version
Go≥ 1.24 (local dev only)
PostgreSQL≥ 14 (via Docker or managed)

The fastest way to get started. Docker Compose spins up the facilitator, PostgreSQL, and Redis in one command.

1. Clone the repository

bash
git clone https://github.com/vitwit/facilitator-server.git
cd facilitator-server

2. Create your config file

bash
cp config.example.yaml config.yaml

Open config.yaml and fill in at minimum:

yaml
server:
  port: ":8080"
  environment: "development"
  host: "0.0.0.0"

database:
  host: "postgres"       # Docker service name
  port: 5432
  name: "x402db"
  user: "x402user"
  password: "yourpassword"
  ssl_mode: "disable"

jwt:
  access_token_secret: "change-me-to-a-long-random-string"
  refresh_token_secret: "change-me-to-another-long-random-string"
  access_token_expiry: "15m"
  refresh_token_expiry: "168h"

security:
  client_secret: "change-me-to-a-long-random-string"

networks:
  evm:
    - network_name: "base-sepolia"
      enabled: true
      chain_id: "base-sepolia"
      rpc: "https://sepolia.base.org"
      accepted_denom: "USDC"
      decimals: 6
      private_key: "<your-wallet-private-key>"
      fee_payer: "<your-wallet-address>"

Security note: Never commit config.yaml to version control. It contains private keys and secrets.

3. Start the stack

bash
docker-compose up -d

4. Verify it's running

bash
curl http://localhost:8080/health

Expected response:

json
{
  "status": "healthy",
  "timestamp": 1712345678,
  "version": "1.0.0"
}

Option B - Local Development

Use this if you want to run the Go binary directly (faster iteration, easier debugging).

1. Clone and install dependencies

bash
git clone https://github.com/vitwit/facilitator-server.git
cd facilitator-server
go mod tidy

2. Start PostgreSQL (via Docker)

bash
docker-compose up -d postgres redis

3. Create and edit your config

bash
cp config.example.yaml config.yaml
# Edit config.yaml - point database.host to "localhost"

4. Run the server

bash
go run cmd/main.go

First API Calls

Sign up for an account

bash
curl -X POST http://localhost:8080/api/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "yourpassword"}'

Log in to get tokens

bash
curl -X POST http://localhost:8080/api/v1/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "yourpassword"}'

Response:

json
{
  "data": {
    "access_token": "eyJ...",
    "refresh_token": "eyJ...",
    "id": 1
  }
}

Create a client API key

Client keys are passed in X-Client-ID / X-Client-Token headers when calling /verify and /settle.

bash
curl -X POST http://localhost:8080/api/v1/clients \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"title": "my-app", "scope": "verify,settle"}'

Check supported networks

bash
curl http://localhost:8080/api/v1/networks

Verify a payment

bash
curl -X POST http://localhost:8080/api/v1/verify \
  -H "Content-Type: application/json" \
  -H "X-Client-ID: <client_id>" \
  -H "X-Client-Token: <client_token>" \
  -d '{
    "paymentPayload": {
      "x402Version": 1,
      "scheme": "exact",
      "network": "base-sepolia",
      "payload": "<base64-encoded-signed-payload>"
    },
    "paymentRequirements": {
      "scheme": "exact",
      "network": "base-sepolia",
      "maxAmountRequired": "1000000",
      "resource": "/api/protected",
      "description": "Access to protected endpoint",
      "mimeType": "application/json",
      "payTo": "0xYourAddress",
      "maxTimeoutSeconds": 60,
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
    }
  }'

Next Steps

Released under the MIT License.