Accept USDC Payments in Node.js Without Stripe: A Practical 402 Walkthrough
If you sell access to a small API, the usual answer is Stripe. But for a $5–$20 product, Stripe onboarding (KYC, payout delays, per-transaction fees, country availability) can cost more than it earns. There is an older i
If you sell access to a small API, the usual answer is Stripe. But for a $5–$20 product, Stripe onboarding (KYC, payout delays, per-transaction fees, country availability) can cost more than it earns. There is an older idea that fits machine-to-machine payments better: HTTP 402 Payment Required.
This post shows how to charge per API call in USDC with two lines of Express middleware.
The 402 flow in 30 seconds
- Client calls your endpoint without paying.
- Your server answers
402with a JSON payment request: asset, amount, chain, recipient address. - Client sends the USDC transfer on-chain and retries with a tx hash.
- Your server verifies the transfer (recipient, amount, block range) and returns the payload plus a short-lived HMAC receipt.
No API keys, no accounts, no custodian. The address is yours; funds never touch the middleware.
Server: two lines
import express from "express";
import { paymentMiddleware } from "@josealbertomaquina/usdc-paywall";
const app = express();
app.get("/v1/heavy",
paymentMiddleware({ usdc: 0.5, chain: "base", payTo: process.env.PAY_TO }),
(req, res) => res.json({ result: "your expensive compute here" }));
app.listen(3000);
The first free call gets 402 + a machine-readable payment request, so scripts and agents can pay programmatically — that's the whole point. Human clients get a 5-line curl flow documented in the README.
Client: pay and retry
curl -i https://api.example.com/v1/heavy # -> 402 + payment request
# send 0.5 USDC on Base to PAY_TO (any wallet), then:
curl "https://api.example.com/v1/heavy?tx=0x..."
Verification reads eth_getLogs for USDC transfers to your address in a replay window, checks amount and recipient, and issues an HMAC receipt so the next minutes don't need another on-chain roundtrip.
When this beats Stripe (and when it doesn't)
Beats: per-call pricing for APIs, machine/agent clients, global availability without country onboarding, sub-cent fees on Base.
Doesn't: subscriptions with dunning, card-user consumers who never held crypto, jurisdictions where you must invoice in fiat. Use both: Stripe for humans, 402 for machines.
Pricing your calls
A rule of thumb: price = max(cost_of_compute * 2, 0.10 USDC). On Base a transfer costs <$0.01, so micro-pricing actually clears. The library also supports one-time unlocks if per-call is too granular.
Beyond the middleware
The Pro tier ($19 one-time, license key) adds license issuance (Ed25519), a live on-chain watcher for payout monitoring, and a CLI to verify payments in CI — useful once you run more than one paid endpoint.
- Repo and docs: usdc-paywall
- npm:
npm i @josealbertomaquina/usdc-paywall
Questions on the verification model or the receipt TTL? Happy to go deeper in the comments.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.