Choosing a facilitator
A facilitator sits between your API and the chain: it verifies payment payloads and settles them on-chain. You configure a base URL and call its POST /verify and POST /settle endpoints from your server middleware.
TallyPay does not replace your facilitator — it instruments your app and correlates events. You can change facilitators without changing TallyPay’s role.
What to compare
Section titled “What to compare”| Criterion | Questions to ask |
|---|---|
| Networks | Base, Arbitrum, Polygon, Solana, Stellar? Which match your users and liquidity? |
| Assets | USDC only, or others? Mainnet + testnet faucets for development? |
| API shape | Standard POST /verify + POST /settle with JSON, or custom SDK wrapper? |
| Latency & reliability | p95 for verify/settle? Incident history? |
| Compliance & custody | Who holds keys? What jurisdictions? (Legal review for your product.) |
| Pricing | Per-transaction fee? Free tier? Compare vs building in-house chain plumbing. |
| Chain coverage | Single-chain vs multi-chain? Does it auto-route based on the payment network? |
Active facilitators
Section titled “Active facilitators”| Facilitator | Base URL | Networks | Notes |
|---|---|---|---|
| Coinbase CDP | https://x402-facilitator.cdp.coinbase.com | Base, Ethereum, Arbitrum, Polygon | Free tier. Widely used. Docs. |
| thirdweb | Via SDK (facilitator() function) | 26+ EVM chains | Integrated into the thirdweb SDK. HTTP API available. Docs. |
| xpay | https://facilitator.xpay.sh | Multiple EVM chains | Exposes GET /health, GET /supported, POST /verify, POST /settle. Docs. |
| Self-hosted | Your own URL | Whatever you support | Full control, full operational burden. Implement the /verify + /settle contract yourself. |
Always verify endpoint URLs and payload formats against the facilitator’s current documentation before deploying. URLs and supported chains change.
Facilitator HTTP contract
Section titled “Facilitator HTTP contract”@tallypay/server expects the following standard endpoints:
POST {facilitatorUrl}/verify
- Body: raw payment signature string (from the client’s
payment-signatureheader). - Response:
{ "valid": true }or{ "valid": false, "reason": "..." }. - Timeout: 10 seconds.
POST {facilitatorUrl}/settle
- Body: same as verify.
- Response:
{ "settled": true, "txHash": "0x..." }or{ "settled": false }. - Timeout: 30 seconds.
If your facilitator uses different paths, response shapes, or authentication, write a thin HTTP proxy that normalizes to this contract.
Discovery: GET /supported
Section titled “Discovery: GET /supported”Some facilitators (e.g. xpay) expose a GET /supported endpoint returning the networks and assets they handle. Useful for dynamic configuration or multi-facilitator routing:
{ "networks": ["eip155:8453", "eip155:1", "eip155:42161"], "assets": ["USDC"], "x402Version": 2}Development vs production
Section titled “Development vs production”- Use testnets (Base Sepolia:
eip155:84532) and faucet USDC while integrating. Keep separate facilitator URLs and merchant addresses. - Log
x-trace-idfrom server responses in your own observability stack for correlation with TallyPay traces. - Some facilitators have sandbox modes or testnet-specific URLs — check their docs.
Using with @tallypay/server
Section titled “Using with @tallypay/server”import { tallypay } from "@tallypay/server/express";
app.use("/api/premium", tallypay({ facilitatorUrl: "https://x402-facilitator.cdp.coinbase.com", payTo: "0xYourAddress", price: "10000", network: "eip155:8453", asset: "USDC",}));The middleware handles the verify → settle flow against whichever facilitator URL you provide.
Next steps
Section titled “Next steps”- Wallet signing with viem — build the client-side authorization
- Express + React tutorial — end-to-end walkthrough
- Security considerations — trust boundaries with facilitators