MPP
Machine Payments Protocol
MPP is a payment protocol for HTTP. It uses the standard HTTP authentication framework.
MPP asks for payment with the WWW-Authenticate header. The authentication scheme is Payment. The client answers with the Authorization header, in the same way it answers Basic or Bearer.
MPP has no facilitator. The server does the verification itself. Nothing in the challenge names a third party.
What people use it for
An agent pays with headers it already knows
An agent meets a 402 from an API. The challenge is in WWW-Authenticate, and the answer goes in Authorization. Its HTTP library already handles both.
A gateway charges for each request
A gateway sits in front of a model. It answers 402 for each request, and it verifies the payment itself. No third party sees the traffic.
A service proves it was paid
The server sends a Payment-Receipt header with the 200. The client keeps the receipt as proof, and it can show the receipt later.
How a payment works
- 1The client asksThe client requests the resource. It sends no payment.
- 2The server refusesThe server answers 402. The WWW-Authenticate header holds a Payment challenge. The body is an RFC 9457 problem document.
- 3The client paysThe client sends the request again with an Authorization: Payment header.
- 4The server agreesThe server answers 200. The Payment-Receipt header proves the delivery.
On the wire
- Status
- 402 Payment Required
- Challenge header
- WWW-Authenticate
- Scheme name
- Payment
- Credential header
- Authorization
- Receipt header
- Payment-Receipt
- Payload encoding
- base64url, no padding
- Error format
- RFC 9457 problem+json
- Version field
- None. MPP sends no version.
What the challenge holds
A Payment challenge has five required parameters: id, realm, method, intent, and request. The request parameter holds the payment data as base64url JSON. Padding characters are not permitted.
The challenge can also carry an expires time. The format is an RFC 3339 date.
Where clients break
A server can send more than one Payment challenge in one response. RFC 9110 puts them in the same header, and a comma divides them. A parser that reads the pair as one challenge gets the wrong terms.
The id parameter must not be empty. The draft tells servers not to send an empty id, and it tells clients to refuse one. Some tools accepted an empty id before the draft made the rule clear.
MPP does not send a protocol version. A client cannot ask which version it speaks to, so it must read the parameters it gets.
MPP tests you can point a client at
11 ready-made MPP endpoints. Each one is a link. Testnets only, and nothing is stored.
- Compliant MPP challenge
A well-formed MPP challenge on Base Sepolia. WWW-Authenticate: Payment, no facilitator.
Your client should Pay it with an Authorization: Payment credential.
- Expired MPP challenge
An MPP challenge on Base Sepolia whose WWW-Authenticate expires is in the past.
Your client should Refuse a challenge it cannot satisfy in time.
- Two MPP challenges at once
One WWW-Authenticate carrying two Payment challenges on Base Sepolia, an inflated decoy before the real one.
Your client should Pay the cheaper challenge, not blindly the first.
- MPP legacy network name
An MPP challenge whose request payload names the network base-sepolia rather than eip155:84532.
Your client should Refuse it rather than guess which chain it means.
- MPP undecodable request
An MPP challenge whose base64url request parameter is not decodable at all.
Your client should Fail cleanly, and not crash.
- MPP 402 with no challenge
A bare 402 and a problem+json body, with no WWW-Authenticate header to answer.
Your client should Treat it as unpayable, and not hang.
- MPP mismatched recipient
An MPP challenge on Base Sepolia paying an address the endpoint was not configured with.
Your client should Notice who it is about to pay.
- MPP inflated amount
An MPP challenge whose request payload asks 1000x the price, still atomic-shaped.
Your client should Catch it against its own maximum, or the asset's decimals.
- MPP amount as a number
An MPP request payload whose amount is a bare JSON number instead of an atomic-units string.
Your client should Refuse it, or read the amount as a big-integer string.
- Oversized MPP header
An MPP challenge padded past the 8KB header buffer many proxies and hardened clients enforce.
Your client should Fail cleanly; a reduced-limit HTTP parser rejects the response.
- MPP challenge with an empty id
An MPP challenge carrying id="", which the draft says a server must never send.
Your client should Reject it, as the draft requires of every parser.
How this differs from x402
Both protocols answer 402 and both settle on a blockchain. They differ in the headers they use, who verifies the payment, and whether they send a version at all.
Compare x402 and MPP