Networks
One gateway, two modes. The flip is a setting, not a migration — products, sales history, and stats survive it.
| Testnet (default) | Mainnet | |
|---|---|---|
| Network | Base Sepolia — eip155:84532 | Base — eip155:8453 |
| Money | test USDC (free from faucets) | real USDC |
| Facilitator | x402.org — free, no signup | Coinbase CDP — free tier 1,000 settlements/mo, then $0.001 |
| Credentials | none | CDP_API_KEY_ID / CDP_API_KEY_SECRET |
Flipping to mainnet
- Create a CDP account + Secret API Key at
portal.cdp.coinbase.com(leave all Coinbase App/Trade permission toggles OFF — the key only authenticates to the facilitator and can never move funds; Ed25519 signature is fine; no client API key needed) - In Settings: paste the keys, fill the mainnet receive address slot with a self-custody wallet you control, select Mainnet, save
- Click Restart server now in the amber banner (or restart however you run it — automatic under systemd)
The testnet receive address lives in its own slot and survives the flip — the two channels never mix.
Refusals that protect you
- Mainnet without CDP keys → refuses to start, names the missing variables
- Mainnet with a generated dev wallet as
payTo→ refused; a throwaway testnet key must never receive real funds
Treat your first mainnet sale as the go-live test: buy from yourself for $0.01 and check the settlement on basescan.org before publicizing the URL.
Going public without a static IP
Bind stays 127.0.0.1; expose via a Cloudflare Tunnel ingress hostname (outbound-only — works behind CGNAT/dynamic IP, zero open ports). Block /admin at the tunnel itself with a path rule ahead of the catch-all:
ingress:
- hostname: store.example.com
path: ^/admin.*
service: http_status:404
- hostname: store.example.com
service: http://127.0.0.1:8402
- service: http_status:404
The gateway already sends cache-control: no-store on every product path, so an edge cache can never serve a stale 402 or leak paid content. Run gateway and tunnel as services (systemd Restart=always); under systemd the settings restart button hands off to the supervisor automatically.