More than ten agent-payment protocols shipped between October 2025 and April 2026, and a seller has to pick one. polyglot402 is a small Fetch API middleware that answers a request with a single 402 carrying every protocol's challenge at once, settles whichever one the caller actually speaks, and records the result in one receipt format.
MIT licensed. The repository stays private until a settlement has actually run on a live network.
A caller that has never seen your service does not know which protocol you take. Rather than making it guess or read your docs, the first refusal states every option it could use, in each protocol's own vocabulary, in one round trip.
HTTP/1.1 402 Payment Required PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiYWNjZXB0cyI6W3sic2NoZW1l… WWW-Authenticate: L402 macaroon="eyJpZGVudGlmaWVy…", invoice="lnbc10n1p…", Payment id="c_8f3a", realm="example.com", method="tempo", intent="charge", request="eyJhbW91bnQiOiIw…", expires="2026-09-07T02:00:00Z" Content-Type: application/json { "error": "Payment required", "price": { "amount": "0.01", "currency": "USD" }, "accepts": [ { "protocol": "x402", "scheme": "exact", "network": "eip155:8453" }, { "protocol": "l402", "amountMsat": 1000 }, { "protocol": "mpp", "method": "tempo" } ] }
RFC 9110 allows several challenges in one WWW-Authenticate, so L402 and MPP share it while x402 uses its own header. Nothing is invented; each adapter emits exactly what its specification says.
A request carrying a credential is matched to the adapter whose format it fits, verified and settled there, and only then does your handler run.
Every protocol produces the same record: id, protocol, network, amount, payer, reference, resource, timestamp. Stored in memory or Cloudflare KV.
Each adapter was written from the protocol's published specification and is exercised by tests against a fake facilitator, a fake Lightning backend and a fake mppx instance.
| Protocol | Backed by | Status here |
|---|---|---|
| x402 v2 PAYMENT-SIGNATURE | Coinbase, Linux Foundation | implemented v1 X-PAYMENT is refused |
| L402 macaroon plus preimage | Lightning Labs | implemented HMAC macaroon, pluggable invoice provider |
| MPP WWW-Authenticate: Payment | Stripe, Tempo | implemented delegates to an mppx instance you construct |
| AP2 | stub pre-release; it authorizes, it does not settle | |
| Skyfire | Skyfire | stub seller services need their approval |
No dependencies, Fetch API only, so it runs on Cloudflare Workers, Deno, Bun and Node 18 or newer. Nothing is published to a package registry yet, so you copy src/ in or add the repo as a git dependency.
import { createRouter, x402Adapter, l402Adapter, mppAdapter, memoryReceipts } from "./src/index.js"; const router = createRouter({ price: { amount: "0.01", currency: "USD" }, adapters: [ x402Adapter({ facilitatorUrl: "https://x402.org/facilitator", payTo, network: "eip155:8453" }), l402Adapter({ invoiceProvider, rootKey, amountMsat: 1000 }), mppAdapter({ mppx, amount: "0.01" }), ], receipts: memoryReceipts(), }); export default { fetch: (req) => router.handle(req, (req, receipt) => Response.json({ data: "…", paidWith: receipt.protocol })) };
Stated plainly, because a payment library that oversells itself costs somebody real money.
This was built believing nothing like it existed. That was wrong, and saying so is cheaper than letting somebody else find out.