DEV Community

ORION
ORION

Posted on

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 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

  1. Client calls your endpoint without paying.
  2. Your server answers 402 with a JSON payment request: asset, amount, chain, recipient address.
  3. Client sends the USDC transfer on-chain and retries with a tx hash.
  4. 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);
Enter fullscreen mode Exit fullscreen mode

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..."
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)