Operate x402 at scale.

Solana-first, multi-network facilitator. Automate payments, capture receipts, and integrate with lightweight SDKs.

Wallet

Not connected
Provider
Address
Network

“Sign Payment” uses message-sign to confirm user presence. Replace with a real transfer or program call in your settlement path.

Recent Receipts

No receipts yet.

Workflow Builder

Create lightweight rules that react to events and call your endpoints.

Rules are client-side for now—persist them in your backend and dispatch with your own webhook secret.

Runbook

  • Idempotency: store last nonce for a short TTL; reject repeats.
  • Retries: exponential backoff; sign new nonce each retry.
  • Observability: log gateway decision, chain, latency, and receipt hash.
  • Security: verify signature and timestamp before executing any action.
TTL 90s Nonce per-call Idempotent yes Webhook x-integ-secret

Receipt JSON

receipt.json
{
  "feature": "api.translate",
  "amount": "0.01",
  "unit": "SOL",
  "ttl": 90,
  "nonce": "7f62b0e1…a9c1",
  "merkleId": "0x9d8b…ff21",
  "payer": "Fv3…QpN",
  "sig": "3Kq…TtW",
  "gatewayPubkey": "GWy…7dL",
  "ts": 1730616273
}

Verify Offline

Check TTL and nonce, then verify the signature against the gateway public key.

verify (Node)
// pseudo: verify receipt offline
import { verifySig, isFresh, seen } from "./verifier.js";

export function verifyReceipt(rcpt){
  if(!isFresh(rcpt.ts, rcpt.ttl)) return { ok:false, err:"expired" };
  if(seen(rcpt.nonce))            return { ok:false, err:"replay" };
  const msg = [
    rcpt.feature, rcpt.amount, rcpt.unit,
    rcpt.nonce, rcpt.merkleId, rcpt.ts
  ].join("|");
  const ok = verifySig(msg, rcpt.sig, rcpt.gatewayPubkey);
  return ok ? { ok:true } : { ok:false, err:"bad-sig" };
}

Install

npm
npm i quantum402

Usage

browser
import { pay } from "quantum402";

const { receipt } = await pay({
  feature: "api.translate",
  amount: "0.01",   // SOL (default chain: Solana)
  ttlSec: 90,
  wallet: "phantom" // or "metamask" via adapter
});

await fetch("/api/translate", {
  headers: { "x402-receipt": JSON.stringify(receipt) }
});
node
import { verifyReceipt } from "quantum402/server";

app.post("/api/translate", async (req,res) => {
  const raw = req.headers["x402-receipt"];
  const rcpt = JSON.parse(raw || "{}");
  const result = await verifyReceipt(rcpt);
  if(!result.ok) return res.status(402).json({ error: result.err });
  // proceed with work...
  res.json({ ok: true });
});