Skip to main content
This maintained example protects one Express route with x402 v2 exact USDC on Base Mainnet. It uses the upstream @x402/core, @x402/evm and @x402/express packages plus the PayAI facilitator config. The merchant supplies only a receiving address; ordinary exact payments can start without a PayAI portal signup or API key within the free allowance.

Get the runnable example

The complete source and offline safety tests are in PayAINetwork/docs.
These commands do not make a payment. The example pins @payai/facilitator 2.4.5, x402 2.27.0, Express 5.1.0 and viem 2.57.2. An October 1, 2026 live check returned unpaid 402, then paid 200 for exactly 0.01 USDC, with matching transfer and authorization events in a canonical finalized Base block. The sanitized verification record retains the receipt, dependency versions and evidence hashes. This was a disposable HTTPS route, not a performance benchmark or permanent deployment.

Merchant route

The resource server uses the standard upstream EVM exact scheme:
Keep existing authorization around private or user-specific data. Payment proves payment, not permission to read another customer’s resource. The runnable server additionally enforces its canonical route and rejects unsupported methods before payment middleware, including Express’s automatic HEAD fallback. Preserve those guards when adapting the snippet.

Prepare a bounded buyer

Use a new disposable Base wallet with only the USDC you intend to spend. Store its private key in a chmod 600 file outside the repository; the runner reads it from BUYER_KEY_FILE, never from a command argument, and never prints or persists it. The merchant address must be different.
The RPC must report chain ID 8453, serve native USDC bytecode and support the finalized block tag. Historical balance reads at the receipt block are optional reporting only. If an RPC cannot serve them, the guard records “unavailable”; it does not relabel a current balance as historical.

Run and verify one payment

Serve the route through HTTPS for a public test and use the same exact URL in both processes:
In a second shell:
Preflight verifies the unpaid 402, scheme, network, USDC address, merchant, amount cap, EIP-712 domain, buyer balance and current exact capability in /supported. payment:once writes a durable guard before signing and sends the paid request exactly once. Success requires two separate results: HTTP 200 with the protected resource and a valid PAYMENT-RESPONSE; then a successful transaction at or below Base’s finalized head with exactly one matching USDC Transfer and AuthorizationUsed event for the authorized payer, recipient, amount and nonce.

Reconcile without another authorization

If transport or RPC reporting is uncertain, keep the guard:
The command never signs or submits. It uses the recorded transaction hash when present. Otherwise it searches only the guard’s recorded 600-block range for the exact finalized authorization event. If the finalized head is still behind the start block, it waits for a later read-only reconciliation instead of issuing an invalid log query. Never pay again to diagnose an uncertain result, and never delete its guard. Read the example README before a live check. It covers HTTPS metadata, key handling, evidence and recovery boundaries.

Allowance, scaling and upstream references

The starter allowance is finite; it is not a promise of free unlimited production. Review pricing and live /supported. An agent can buy credits and a key over x402 when it needs paid capacity; the merchant dashboard remains optional. For protocol context, see the official x402 seller quickstart and facilitator directory.