x402 vs L402 vs MPP: Choosing an HTTP 402 Protocol
x402, L402 and MPP each answer a request with HTTP 402 and a price. How they pay, verify and settle as of October 2026, and when to use which.
HTTP has reserved status 402 since RFC 2068, the first HTTP/1.1 specification, published in January 1997. Its section 10.4.3 defines 402 Payment Required in one sentence: "This code is reserved for future use." HTTP/1.0 (RFC 1945, May 1996) has no 402 at all, and the current HTTP specification, RFC 9110 from 2022, still reserves the code without saying how to pay.
As of October 2026, three protocols say how:
- L402, from Lightning Labs, started in 2020 as LSAT. The 402 carries a Lightning invoice and a macaroon, and the client proves payment with the invoice's preimage.
- x402, released by Coinbase in May 2025 and run since 2026 by the x402 Foundation at the Linux Foundation. The 402 lists the payments the seller accepts, usually a stablecoin on Base, Solana or another chain, and the client signs an authorization that a facilitator settles on chain.
- MPP, the Machine Payments Protocol, published by Stripe and Tempo on March 18, 2026. It defines a
Paymentauthentication scheme and leaves the method open, from Tempo stablecoins to cards to Lightning.
All three put the price in the 402 and the proof in the retry, so a buyer needs no account and no API key. They differ in what money moves, when it moves, who checks it and what the seller has to run. L402 explained goes through the L402 exchange step by step; this page compares the three.
On the wire
One request for /weather and its paid retry, in each protocol. L402 uses HTTP's authentication headers (spec):
HTTP/1.1 402 Payment Required
WWW-Authenticate: L402 macaroon="AgJCAAA...", invoice="lnbc100n1p5..."
GET /weather HTTP/1.1
Authorization: L402 AgJCAAA...:9f2c...e41ax402 v2, from December 2025, uses headers of its own, each carrying base64 JSON (HTTP transport). Version 1 sent the payment in X-PAYMENT.
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Miwi...
GET /weather HTTP/1.1
PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miwi...Decoded, PAYMENT-REQUIRED lists what the seller accepts. This one, trimmed from the specification's example, asks for 10000 atomic units of USDC on Base Sepolia, a testnet. USDC has six decimals, so that is one cent:
{
"x402Version": 2,
"resource": { "url": "https://api.example.com/premium-data", "mimeType": "application/json" },
"accepts": [
{
"scheme": "exact",
"network": "eip155:84532",
"amount": "10000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDC", "version": "2" }
}
]
}MPP uses the authentication headers as L402 does, under the scheme name Payment (core draft). Its request parameter is base64url JSON whose fields depend on the payment method:
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment id="kM9xPqWvT2nJrHsY4aDfEb", realm="api.example.com", method="lightning", intent="charge", request="eyJhbW91bnQiOiIxMCIsImN1cnJlbmN5Ijoic2F0Iiwi..."
GET /weather HTTP/1.1
Authorization: Payment eyJjaGFsbGVuZ2UiOnsiaWQi...With the Lightning method, request decodes to {"amount":"10","currency":"sat","methodDetails":{"invoice":"lnbc100n1p5..."}}, and the credential echoes the challenge and adds "payload": {"preimage": "9f2c...e41a"}.
| L402 | x402 v2 | MPP | |
|---|---|---|---|
| The 402 carries | WWW-Authenticate: L402, a macaroon and an invoice |
PAYMENT-REQUIRED, the payments accepted |
WWW-Authenticate: Payment, a method and a request |
| The retry carries | Authorization: L402 <macaroon>:<preimage> |
PAYMENT-SIGNATURE, a signed payment |
Authorization: Payment <credential> |
| Receipt header | none | PAYMENT-RESPONSE |
Payment-Receipt |
| Money | bitcoin over Lightning | ERC-20 tokens on EVM chains, SPL tokens on Solana, other networks | per method: Tempo, Stripe and cards, EVM, Solana, Lightning and more |
| Money moves | before the retry | after the handler, by default | per method |
| Checked by | the seller, or ln.bot for its wallets | a facilitator, or the seller | the seller, per method |
| Specification | Lightning Labs | x402 Foundation | individual Internet-Draft |
What the retry proves
An L402 retry proves a payment that has already happened: the preimage only exists for the client once the Lightning payment settles. The seller does its work after the money has moved, and with @lnbot/l402 a token counts as spent once the request reaches the handler, even if the handler fails.
An x402 retry carries a signed instruction to pay. On EVM chains the client signs an EIP-3009 transferWithAuthorization, which USDC supports, or a Permit2 transfer for tokens that don't (exact scheme on EVM). On Solana it sends a partially signed SPL token transfer, which the facilitator or the seller completes as fee payer (on Solana). Nothing has moved when the server reads the header. In the default authorization flow the order is verify, run the handler, settle, and funds move only if the handler completes (spec, section 6.1), so a failed request costs the buyer nothing. A scheme can use the upfront flow instead and settle first. x402's Lightning scheme has to, because a preimage only exists after the payment (scheme).
An MPP credential proves whatever its method defines. For Lightning it's a preimage, as in L402. For cards, Stripe accepts MPP payments through its PaymentIntents API and Shared Payment Tokens (Stripe).
Who checks it, and what the seller runs
x402 sellers usually pass the payload to a facilitator's /verify and /settle endpoints. The protocol lets a seller run those itself, and the x402 docs describe self-facilitating inside the resource server; the public x402.org facilitator is for testnets only. Coinbase's CDP facilitator, as of October 2026, verifies for free, settles the first 1,000 on-chain transactions each month for free and charges $0.001 for each one after. It screens payments with OFAC and KYT checks, and its batch-settlement scheme claims many payments in one on-chain transaction.
A seller with the x402 Foundation's Express middleware, as in its seller quickstart (testnet settings):
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";
const app = express();
const facilitatorClient = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" });
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [{ scheme: "exact", price: "$0.001", network: "eip155:84532", payTo: "0xYourEvmAddress" }],
description: "Weather data",
mimeType: "application/json",
},
},
new x402ResourceServer(facilitatorClient).register("eip155:84532", new ExactEvmScheme()),
),
);
app.get("/weather", (req, res) => {
res.send({ report: { weather: "sunny", temperature: 70 } });
});
app.listen(4021);The same route behind L402 with ln.bot:
import express from "express";
import { l402, LnBot } from "@lnbot/l402";
const app = express();
const ln = new LnBot({ apiKey: process.env.LNBOT_KEY });
app.use("/weather", l402.paywall(ln, { walletId: "wal_...", price: 10, description: "Weather data" }));
app.get("/weather", (req, res) => {
res.send({ report: { weather: "sunny", temperature: 70 } });
});
app.listen(4021);Both are a middleware in front of a route; what sits behind the middleware differs. For x402 it's a facilitator and a chain. For @lnbot/l402 it's one HTTPS call to api.ln.bot per paid request, with ln.bot keeping the macaroon root keys and running the Lightning nodes. A self-hosted L402 server such as Aperture checks tokens locally against its own key store, and you run lnd, its channels and the database.
An MPP seller checks each credential the way its method says. Aperture v0.5.0, from March 2026, implements MPP's Lightning charge and session intents next to L402 and can offer both challenges in one 402.
Speed
On Lightning the client gets its preimage when the payment settles, and a settled payment is final. Between two ln.bot wallets that takes under a second. Across the network it usually takes a few seconds, and a payment that fails on one route is retried on another (how payments fail).
On Base, blocks come every 2 seconds, and Flashblocks give a preconfirmation every 200 ms; Base targets a Flashblock reorg rate under 0.1% (Base docs). In x402's default flow the handler doesn't wait for the chain, since /verify checks the signature and simulates the transfer, but the response waits for /settle. An MPP payment takes as long as its method does.
Cost per request
With x402's exact scheme and a token such as USDC that supports EIP-3009, the buyer pays no gas: the facilitator submits the transfer and pays for it. The seller pays the facilitator. On CDP that's nothing for the first 1,000 settlements a month and $0.001 for each one after, so at a price of a tenth of a cent the fee equals the price. Batch settlement exists for that case.
With L402 the buyer pays Lightning routing fees, set by each channel on the route (fees), and the seller receives the full amount. Through ln.bot, a payment between two ln.bot wallets is free. One that leaves ln.bot costs 0.25% with a ₿1 minimum, plus the routing fee, and at small prices the minimum dominates: a ₿1 request from an ln.bot wallet to a server elsewhere costs the buyer ₿2 plus routing. Receiving is free.
Price stability
USDC tracks the dollar, so an x402 price of $0.01 stays $0.01. L402 prices are in bitcoin units, and their dollar value moves with bitcoin. If your costs are in dollars, price in dollars and convert on each request, since the paywall's price can be a function. On the L402 server above:
// Priced in dollars, paid in bitcoin: the price function runs on every request.
// satsPerDollar() is your own rate source, updated on a schedule.
app.use("/api/report", l402.paywall(ln, {
walletId: "wal_...",
price: async () => Math.ceil(0.05 * (await satsPerDollar())), // $0.05
}));The @lnbot/l402 client pays whatever the invoice asks, within its maxPrice, so a moving price doesn't break it. One thing to watch: a 1.1 token is bound to the price it was issued at and refused on a request priced higher. If the price goes up between a 402 and its retry, the client has paid for a token that no longer opens the route, so change the rate now and then, not on every call.
Trust
Each protocol leaves you trusting someone different. With x402 on USDC, that includes the issuer: Circle's USDC terms reserve the right to block addresses and transfers to and from them on chain (section 13), and the CDP facilitator declines payments that involve sanctioned or high-risk addresses. With L402 the asset is bitcoin, which has no issuer.
With either, someone holds the balance an agent spends. For an agent on ln.bot, ln.bot runs the Lightning nodes and the channel liquidity, and the balance sits on its nodes, so treat the wallet as an operating balance funded with what the agent needs, not as savings. Running your own Lightning node makes that someone you. With MPP, the trust is the method's: a card payment comes with Stripe's rules, a Lightning payment with Lightning's.
Who is behind each, as of October 2026
x402: the x402 Foundation was announced at the Linux Foundation on April 2, 2026, with Coinbase contributing the protocol, and declared operational on July 14, 2026, with 40 members. Its 17 premier members include AWS, Cloudflare, Google, Stripe, Visa, Mastercard, Circle and Coinbase. The foundation's SDKs are in TypeScript, Python, Go and Java, and the TypeScript SDK has mechanisms for EVM chains, Solana and eleven other networks. The spec added an exact scheme for Lightning on September 23, 2026, which none of the foundation's SDKs implement yet.
L402: Lightning Labs maintains the spec and Aperture, which fronts its Lightning Loop service. In February 2026 it released lightning-agent-tools, seven agent skills including lnget, an L402-aware command-line HTTP client with a per-request --max-cost. ln.bot ships 1.1 middleware and clients for Express (@lnbot/l402) and ASP.NET Core (LnBot.L402). Alby's lightning-tools has a fetch402 that recognizes L402, MPP and x402 challenges and pays them from a Lightning wallet when they offer an invoice; for x402 it reads a Lightning offer format of its own, not the foundation's new scheme.
MPP: co-authored by Stripe and Tempo. Its core is an individual Internet-Draft, draft-httpauth-payment, last revised in September 2026, not an IETF standard. Method drafts cover Tempo, Stripe and cards, EVM chains, Solana, Stellar, the XRP Ledger, Hedera and Lightning, the last written by Lightspark, and there are SDKs for TypeScript, Python, Rust, Go and Ruby (specs).
Satring, a directory of paid APIs, listed 683 x402 services, 402 MPP and 126 L402 on October 23, 2026; a service can accept more than one. Of those, 395, 125 and 55 answered its health probes.
When to use which
- Your buyers hold dollars or stablecoins, and you want prices that stay put in dollars: x402. A hosted facilitator is the quick start; look at batch settlement if you charge fractions of a cent.
- Your buyers are agents with Lightning wallets, you price in small amounts of bitcoin, and you want no chain or facilitator in the request: L402. Self-host Aperture if you already run Lightning, or use
@lnbot/l402if you don't want to. - You want card payments or Stripe settlement, or one header that several payment methods share: MPP.
- A failed request must cost the buyer nothing: x402's default flow, which settles only after the handler succeeds. With L402 the buyer has paid before the server starts.
- Many requests to one API: an L402 pass (
reuse: true), an MPP session, or x402'suptoandbatch-settlementschemes, so that each request isn't its own settlement. - More than one: they can coexist. Aperture offers L402 and MPP in one 402, x402's headers don't collide with either, and a client such as Alby's
fetch402pays whichever challenge it can.
FAQ
What is the difference between x402 and L402?
Both answer an unpaid HTTP request with 402 and accept a retry that carries proof of payment. x402 puts its terms in a PAYMENT-REQUIRED header, usually a stablecoin amount on Base, Solana or another chain; the client signs a payment authorization, and a facilitator verifies it and settles it on chain, by default after the server has handled the request. L402 puts a Lightning invoice and a macaroon in WWW-Authenticate; the client pays the invoice first and proves it with the payment's preimage.
What is MPP?
The Machine Payments Protocol, published by Stripe and Tempo on March 18, 2026. It uses WWW-Authenticate: Payment and Authorization: Payment and leaves the payment method open: Tempo, cards through Stripe, EVM chains, Solana and Lightning are among its method drafts. Its core is an individual Internet-Draft at the IETF, not a standard.
Can x402 carry Lightning payments?
The x402 specification added an exact scheme for Lightning on September 23, 2026: the client pays a BOLT 11 invoice and returns the preimage, and the seller settles before handling the request. As of October 2026 none of the x402 Foundation's SDKs implement it.
Does L402 need a facilitator?
No. A self-hosted L402 server checks tokens itself, against root keys it stores. With ln.bot's middleware the check is one HTTPS call to api.ln.bot per paid request, and ln.bot keeps the keys and runs the Lightning nodes.
Can one API accept more than one 402 protocol?
Yes. Lightning Labs' Aperture (v0.5.0) can put an L402 challenge and an MPP challenge in the same 402 response, and x402 uses headers of its own, so it can sit beside them. A client then pays with whichever protocol it supports.