HTTP reference
The complete HTTP surface. Free means no payment, no auth.
| Route | Access | What |
|---|---|---|
GET /catalog | free | storefront, HTML |
GET /catalog.json | free | machine-readable catalog (products, files, sizes, excerpts) |
GET /feed | free | recent sales, payer truncated |
GET /docs… | free | these pages |
| product routes | paid | from products.json — 402 challenge / 200 + content |
GET /admin | Basic auth | dashboard: tiles, products, sales, requests |
GET/POST /admin/products… | Basic auth | add / edit / remove products |
GET / | free | redirects to /catalog |
GET/POST /admin/files/:sku… | Basic auth | folder file management: list+stats, multi-upload, view (/raw), edit text content (/file, /save), rename, delete |
GET/POST /admin/settings | Basic auth | network mode, wallet, CDP keys |
GET /admin/export/sales.csv | Basic auth | settlements as CSV |
The 402 exchange
Challenge — status 402, header payment-required (base64 JSON):
{ "x402Version": 2, "resource": { "url": "…", "description": "…" },
"accepts": [ { "scheme": "exact", "network": "eip155:84532", "amount": "10000",
"asset": "0x036C…CF7e", "payTo": "0x…", "maxTimeoutSeconds": 300 } ] }
amount is atomic units (USDC has 6 decimals: 10000 = $0.01). Retry with the signed payment in payment-signature (older clients: X-PAYMENT). Success — status 200, header PAYMENT-RESPONSE (base64 JSON):
{ "success": true, "payer": "0x…", "transaction": "0x…", "network": "eip155:84532" }
Browsers (Accept: text/html + Mozilla UA) get a wallet-connect payment page on 402 instead of JSON.
Environment
PAY_TO=0x… # receiving wallet (required)
NETWORK=eip155:84532 # default testnet; eip155:8453 = mainnet
FACILITATOR_URL=https://x402.org/facilitator # testnet default
ADMIN_PASSWORD=… # min 12 chars (required)
IP_SALT=… # for hashed request logging (required)
PORT=8402 DB_PATH=./sandbox.db RETENTION_DAYS=90
CDP_API_KEY_ID= CDP_API_KEY_SECRET= # mainnet only