Skip to main content
This recipe builds an Express server that returns HTTP 402 until an on-chain USDC payment is verified. handleVerify and handleSettle from @glideco/x402-facilitator are called directly in route handlers — there is no Express middleware abstraction. The client side constructs and sends the X-Payment header with a payment payload. F1 rule: the server verifies payment via server-side RPC, never by trusting a facilitator response body. on_chain_tx in the receipt is always server-fetched from chain RPC. Audience: developers who want to monetize an API call without a billing dashboard.

Prerequisites

  • Node 22+ and pnpm.
  • A Base Sepolia wallet with test USDC — get some from the Coinbase faucet.
  • Optional: a Chainalysis API key if you want real sanctions screening instead of the permissive demo screener.

Steps

1. Clone the example

2. Set environment variables

3. Build the server (src/server.ts)

The server exposes three routes:
  • GET /api/weather — returns 402 (no payment) or 200 (valid payment)
  • POST /x402/verify — verify a payment payload; returns { isValid, ... }
  • POST /x402/settle — settle on-chain (mocked in the example); returns { success, txHash }
Compliance screener. The example uses a permissive allow-all screener so it runs without Chainalysis credentials. Swap in @glideco/connector-chainalysis in production — the ComplianceScreener interface is the same.
/x402/verify route. Decodes the payment payload and runs the compliance pipeline. In production, replace the demo decoder with EIP-712 signed transfer authorization validation.
/x402/settle route. Derives a content-bound idempotency key, replays on cache hit, re-verifies (TOCTOU defense), then broadcasts.
Paid endpoint. On a request without X-Payment, return 402 with the payment requirements. On a request with X-Payment, call handleVerify directly before returning data.

4. Write the client (src/client.ts)

The client follows the four-step x402 flow: probe → verify → settle → retry with header. No special x402 client library is needed — standard fetch throughout.
In production, replace the demo payload with a real EIP-712 signed USDC transfer authorization from the payer’s wallet.

Run it

Expected output:

Extend it

  • Swap the permissive screener for @glideco/connector-chainalysis to get real OFAC screening on every payment.
  • Move idempotencyCache to Redis so replay protection survives server restarts.
  • Add tiered pricing: return different maxAmountRequired values per endpoint in the 402 body.
  • Port to a Next.js API route — call handleVerify and handleSettle directly in the route handler; the pattern is identical.
  • Derive the idempotency cache key using deriveIdempotencyCacheKey from @glideco/x402-facilitator — it binds the key to (payTo, network, payloadHash) to prevent cross-tenant cache poisoning.

Source

github.com/darshanbathija/axtior-neobank/tree/main/examples/x402-paid-api

Reading list

  • @glideco/x402-facilitator packagehandleVerify, handleSettle, runCompliancePipeline, deriveIdempotencyCacheKey API reference.
  • @repo/connectors-coinbase-x402decodeXPaymentHeader, encodeXPaymentHeader, handleX402Request for production client-side payment construction.
  • Receipt schema — how x402 receipts map to the Glide receipt model.
  • F1 rule — why on_chain_tx must be server-fetched, never from a facilitator body.