Give an agent an address and a paragraph and it puts paper in someone's mailbox — the proof PDF comes back in the same response.
git clone https://github.com/nirholas/x402-print-mail
cd x402-print-mail && npm install
npm run dev # http://localhost:4024
| Route | Price | What you get back |
|---|---|---|
POST /letters | $0.05 | `{mailId, previewPdfBase64, expectedDelivery}` plus page count, carrier, mail class, and the addresses as printed |
POST /postcards | $0.03 | `{mailId, previewPdfBase64, expectedDelivery}` for a two-page proof: front artwork, then back with address block and postage box |
GET /health | free | Liveness, data source, configured rails |
GET /.well-known/x402 | free | Machine-readable discovery manifest |
Every paid route returns the purchased artifact in the 200 body — nothing is deferred to a webhook or a second fetch.
POST /lettersX-PAYMENTPay in USDC on Base or Solana — your client picks. The 402 body always lists both.
USDC on base-sepolia (or base). The wallet signs an EIP-3009 authorization locally — no server round-trip.
USDC SPL transfer on solana. A facilitator sponsor pays the SOL network fee, so buyers need only USDC. Helpers at /api/x402-checkout build and wrap the transaction.
import { writeFileSync } from "node:fs";
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "x402-fetch";
const payFetch = wrapFetchWithPayment(fetch, privateKeyToAccount(process.env.PRIVATE_KEY));
// Send a letter — $0.05
const letter = await (await payFetch("http://localhost:4024/letters", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ to, from, body: "Dear Dana,\n\nYour order shipped today.\n\nSincerely,\nAcme" }),
})).json();
writeFileSync("letter.pdf", Buffer.from(letter.previewPdfBase64, "base64"));
console.log(letter.mailId, "arrives by", letter.expectedDelivery);
Live printing runs through [Lob](https://lob.com) when `LOB_API_KEY` is set. Without it, the service typesets and renders the proof itself — a genuine, paginated PDF with the address block, body copy and a footer marking it a preview — and labels every response `"source": "fixture"` with `"testMode": true`. Expected delivery dates use the same USPS First-Class business-day math Lob quotes. Nothing is printed or mailed in either mode unless you supply a **live** Lob key.