Rate-shop every carrier and buy the label in two paid calls — the label PDF comes back base64 in the response body.
git clone https://github.com/nirholas/x402-shipping
cd x402-shipping && npm install
npm run dev # http://localhost:4023
| Route | Price | What you get back |
|---|---|---|
POST /rates | $0.003 | the full carrier rate table with prices, transit days, and `cheapest` / `fastest` flags |
POST /label | $0.02 | the label as base64 PDF plus tracking number, tracking URL, carrier, service and the amount charged |
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 /ratesX-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));
const shipment = { from, to, parcel };
// Rate-shop — $0.003
const { rates, cheapest } = await (await payFetch("http://localhost:4023/rates", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(shipment),
})).json();
// Buy the cheapest — $0.02
const label = await (await payFetch("http://localhost:4023/label", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ rateId: cheapest.rateId, ...shipment }),
})).json();
writeFileSync("label.pdf", Buffer.from(label.labelPdfBase64, "base64"));
console.log(label.trackingNumber); // the label is already on disk
Live carrier data is used when `SHIPPO_API_TOKEN` or `EASYPOST_API_KEY` is set — both providers issue free test-mode keys. Without either, the service quotes from a deterministic fixture rate table (seven real carrier services: USPS Ground Advantage / Priority / Priority Express, UPS Ground / 2nd Day Air, FedEx Home Delivery / 2Day) priced on actual weight, volume and ZIP-derived zone, and issues a genuine one-page PDF label. Every response carries `"source": "fixture"` and `"testMode": true`.