Skip to content
All prompts

Paywall an HTTP Route with x402

You are adding the x402 payment protocol to an HTTP API so individual requests can be monetized — no API keys, no accounts, just per-call crypto micropayments.

Goal

A client calls GET /premium. If unpaid, the server responds 402 Payment Required with payment instructions. The client pays, retries with an x-payment header, and the server verifies and serves the response.

Environment variables

X402_PAY_TO=0xYourMerchantWalletAddress
X402_FACILITATOR_URL=https://coinpayportal.com/api/x402
X402_PRICE_USDC=0.01

Where to find them:

  • X402_PAY_TO — your own merchant wallet address. For crypto wallets you control already, paste it directly. For one managed by CoinPay, copy it from https://coinpayportal.com/settings/wallets (the chain you intend to receive on).
  • X402_FACILITATOR_URL — always https://coinpayportal.com/api/x402 for production. CoinPay is the multi-chain x402 facilitator; no key needed.
  • X402_PRICE_USDC — pick whatever you want to charge per request. Server-side only.

Steps (Merchant)

  1. Install the middleware (Node example):

``bash npm install @coinpay/x402 ``

  1. Wrap the route:

```js import { createX402Middleware, buildPaymentRequired, verifyX402Payment } from '@coinpay/x402';

const x402 = createX402Middleware({ price: { amount: '0.01', currency: 'USDC', chain: 'base' }, payTo: '0xYourMerchantWalletAddress', facilitator: 'https://coinpayportal.com/api/x402', });

export async function GET(request) { const paymentHeader = request.headers.get('x-payment'); if (!paymentHeader) { const body = buildPaymentRequired(x402.config); return new Response(JSON.stringify(body), { status: 402 }); } const result = await verifyX402Payment(paymentHeader, x402.config); if (!result.valid) return new Response('Invalid payment', { status: 402 }); return Response.json({ data: 'premium content' }); } ```

  1. Set the price server-side from your config — never trust the client's claimed amount.

Steps (Client)

import { CoinPayWallet } from '@coinpay/wallet';

const wallet = new CoinPayWallet();
const response = await wallet.x402fetch('https://api.example-business.com/premium');
const data = await response.json();

The wallet automatically handles the 402, signs a payment, and retries.

Rules

  • The merchant config — including payTo and price — must live server-side.
  • Verify every payment via the facilitator before serving the response.
  • Use example-business.com as the placeholder API host.

Deliverable

  • A protected route that returns 402 when unpaid and 200 when paid.
  • A client snippet that consumes it via x402fetch.
  • A test that asserts both branches.