Skip to content

chetparker/x402-fastapi-kit

Repository files navigation

x402-fastapi-kit

Production-ready starter kit for building x402 payment-gated FastAPI services.

Turn any FastAPI endpoint into a paid API with one decorator. Built on Coinbase's x402 protocol — the open standard for internet-native payments.

Features

  • One-line payment gating@require_payment(price="$0.01") on any route
  • PaymentApp — batteries-included FastAPI subclass with middleware pre-wired
  • Environment-driven config — Pydantic Settings with .env support
  • Multi-chain — EVM (Base, Ethereum, Polygon) and Solana out of the box
  • Introspection — built-in /x402/health and /x402/routes endpoints
  • CLI scaffoldingx402kit init my-api generates a ready-to-run project
  • Spec-compliant — x402 v2 responses, PAYMENT-REQUIRED header, facilitator verification
  • API key fallbackX-API-Key header auth for traditional clients
  • Wallet allowlist — free-pass access for partners and your own AI agents
  • Rate limiting — sliding-window rate limiter with per-route limits and 429 responses
  • Event hooks@bus.on("payment.verified") callbacks for logging, analytics, alerts

Quick Start

1. Install

pip install x402-fastapi-kit

2. Set your wallet

export X402_PAY_TO=0xYourWalletAddress

3. Write your app

from x402_fastapi_kit import PaymentApp, require_payment

app = PaymentApp()

@app.get("/free")
async def free():
    return {"msg": "hello, no payment needed"}

@app.get("/premium")
@require_payment(price="$0.05", description="Premium data")
async def premium():
    return {"data": "this costs $0.05 per request"}

4. Run

uvicorn app:app --reload

Try it:

curl http://localhost:8000/free        # → 200 OK
curl http://localhost:8000/premium     # → 402 Payment Required
curl http://localhost:8000/x402/routes # → list of gated routes

Configuration

All settings are loaded from environment variables (prefix X402_) or a .env file:

Variable Default Description
X402_PAY_TO (required) Wallet address (EVM or Solana)
X402_NETWORK eip155:84532 CAIP-2 network ID
X402_FACILITATOR_URL https://x402.org/facilitator Facilitator service URL
X402_DEFAULT_PRICE $0.01 Default price for gated routes
X402_SCHEME exact Payment scheme
X402_MAX_TIMEOUT_SECONDS 300 Payment expiry
X402_HOST 0.0.0.0 Server bind host
X402_PORT 8000 Server bind port
X402_DEBUG false Debug mode
X402_SVM_PAY_TO (optional) Solana address for dual-chain
X402_RATE_LIMIT_ENABLED true Enable rate limiting
X402_RATE_LIMIT_RPM 60 Default requests per minute per client
X402_RATE_LIMIT_ROUTES (empty) Per-route limits: /weather=30,/forecast=10
X402_API_KEYS_ENABLED false Enable API key fallback auth
X402_API_KEYS (empty) Keys as name=secret,name=secret
X402_ALLOWLIST_ENABLED false Enable wallet allowlist
X402_ALLOWLIST_ADDRESSES (empty) Comma-separated wallet addresses

Supported Networks

Network CAIP-2 ID
Base Sepolia (testnet) eip155:84532
Base Mainnet eip155:8453
Ethereum Mainnet eip155:1
Polygon Mainnet eip155:137
Solana Devnet solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
Solana Mainnet solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp

Access Control

The middleware runs a 4-step pipeline on every gated request. The first match wins:

Request → [1] Wallet Allowlist → [2] API Key → [3] Rate Limit → [4] x402 Payment
               (bypass)            (bypass)        (429)           (402/200)

API Key Fallback

Support traditional clients alongside x402 payers:

from x402_fastapi_kit import PaymentApp, APIKeyManager, require_payment

keys = APIKeyManager()
keys.add_key("partner-1", "sk_live_abc123")
keys.add_key("internal",  APIKeyManager.generate_key())

app = PaymentApp(api_key_manager=keys)

@app.get("/data")
@require_payment(price="$0.05")
async def data():
    return {"result": "works with X-PAYMENT or X-API-Key header"}
curl -H "X-API-Key: sk_live_abc123" http://localhost:8000/data  # 200 — bypassed

Wallet Allowlist

Give free access to partners, your own agents, or test wallets:

from x402_fastapi_kit import PaymentApp, WalletAllowlist

allowlist = WalletAllowlist()
allowlist.add("0xPartnerWallet...", label="acme-corp")
allowlist.add("0xMyAgentWallet...", label="internal-bot")

app = PaymentApp(wallet_allowlist=allowlist)
curl -H "X-WALLET: 0xPartnerWallet..." http://localhost:8000/data  # 200 — free

Rate Limiting

Protect your facilitator from abuse with per-client sliding-window limits:

from x402_fastapi_kit import PaymentApp, RateLimiter

limiter = RateLimiter(
    requests_per_minute=60,
    route_limits={"/expensive": 10, "/cheap": 200},
)

app = PaymentApp(rate_limiter=limiter)

Allowlisted wallets and API key holders bypass rate limits (they're checked first).

Event Hooks

Get notified at every decision point in the pipeline:

from x402_fastapi_kit import PaymentApp, EventBus, EventType

bus = EventBus()

@bus.on(EventType.PAYMENT_VERIFIED)
async def on_paid(event):
    print(f"💰 {event.route} — tx: {event.tx_hash}")

@bus.on(EventType.RATE_LIMITED)
async def on_throttled(event):
    alert(f"⚠️ Client {event.client_id} rate limited on {event.route}")

# Wildcard — see everything
bus.on_all(lambda e: metrics.emit(e.event_type, e.route))

app = PaymentApp(event_bus=bus)

Event types: payment.verified, payment.rejected, request.gated, auth.api_key, auth.allowlist, rate.limited, facilitator.error

Service Discovery

Make your API findable by AI agents and the x402 ecosystem:

from x402_fastapi_kit import PaymentApp, ServiceManifest

manifest = ServiceManifest(
    name="Weather API",
    description="Real-time weather data",
    tags=["weather", "data", "climate"],
    homepage="https://weather.example.com",
)

app = PaymentApp(manifest=manifest)
# Now serves /.well-known/x402 automatically

Enrich your OpenAPI schema so tools can read pricing from /openapi.json:

app.enrich_openapi_schema()
# Each gated endpoint now has x-x402 metadata in the spec

Register with the Bazaar discovery layer:

from x402_fastapi_kit import register_with_bazaar

await register_with_bazaar("https://weather.example.com", settings, manifest)

Client SDK (Buyer Side)

Make x402 payments from Python — for AI agents, scripts, and services that consume paid APIs:

from x402_fastapi_kit import X402Client, PaymentPolicy, DryRunSigner

# Dry-run mode (no real wallet, for testing)
client = X402Client(signer=DryRunSigner())

# With spending controls
client = X402Client(
    signer=my_wallet_signer,
    policy=PaymentPolicy(
        max_per_request="1.00",
        max_per_session="10.00",
        preferred_network="eip155:8453",
    ),
)

# Transparent 402 → pay → retry
resp = await client.get("https://api.example.com/weather")
print(resp.json())

# Check spending
print(f"Total spent: ${client.total_spent}")
print(f"Receipts: {client.receipts}")

# Discover a service
manifest = await client.discover("https://api.example.com")

Implement PaymentSigner for real wallets:

from x402_fastapi_kit import PaymentSigner

class MyWalletSigner(PaymentSigner):
    async def sign(self, requirements: dict) -> str:
        # Sign with your wallet (viem, web3.py, solders, etc.)
        return signed_payload_string

    @property
    def address(self) -> str:
        return "0xYourAddress"

Analytics Dashboard

Live revenue and request monitoring, powered by the EventBus:

from x402_fastapi_kit import PaymentApp, EventBus

bus = EventBus()
app = PaymentApp(event_bus=bus, analytics=True)
# Serves:
#   /x402/stats     → JSON snapshot (revenue, routes, auth breakdown)
#   /x402/dashboard → live HTML dashboard (auto-refreshes every 5s)

The dashboard shows: total revenue, payment count, per-route breakdown, auth method distribution, rate limit events, and a live event feed.

CLI

# Scaffold a new project
x402kit init my-paid-api

# Show version and networks
x402kit info

API Reference

PaymentApp

A FastAPI subclass that auto-wires the payment middleware, discovers @require_payment routes, and adds introspection endpoints.

from x402_fastapi_kit import PaymentApp

app = PaymentApp(
    title="My API",
    settings=X402Settings(pay_to="0x..."),
)

@require_payment

Decorator to gate a route. Apply after the route decorator:

@app.get("/data")
@require_payment(
    price="$0.05",           # required
    description="My data",   # shown in 402 response
    network="eip155:8453",   # override global network
    scheme="exact",          # payment scheme
    pay_to="0xOther",        # override global pay_to
)
async def get_data():
    return {"data": "paid content"}

PaymentGate

ASGI middleware (used internally by PaymentApp, or add manually):

from fastapi import FastAPI
from x402_fastapi_kit import PaymentGate, X402Settings

app = FastAPI()
app.add_middleware(PaymentGate, settings=X402Settings())

How It Works

Client                    Your FastAPI               Facilitator
  │                           │                          │
  │  GET /premium             │                          │
  │──────────────────────────▶│                          │
  │                           │ (no X-PAYMENT header)    │
  │  402 + payment details    │                          │
  │◀──────────────────────────│                          │
  │                           │                          │
  │  GET /premium             │                          │
  │  X-PAYMENT: <signed>      │                          │
  │──────────────────────────▶│                          │
  │                           │  POST /verify            │
  │                           │─────────────────────────▶│
  │                           │  { valid: true }         │
  │                           │◀─────────────────────────│
  │  200 + data               │                          │
  │◀──────────────────────────│                          │

Development

git clone https://github.com/your-org/x402-fastapi-kit
cd x402-fastapi-kit
pip install -e ".[dev]"
pytest

License

MIT

About

Production-ready starter kit for building x402 payment-gated FastAPI APIs. Deploy a paid API in 10 minutes.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors