MPP
Machine Payments Protocol
MPP is an internet payment protocol for machine-to-machine commerce. It uses the HTTP 402 status code to signal payment requirements, supporting both crypto (on-chain stablecoins) and fiat (cards, wallets via Stripe). Developed by Stripe and Tempo.
Key Features
Dual Payment Rails
Supports both on-chain crypto payments (USDC stablecoins) and traditional fiat payments (cards, wallets) through Stripe — all via the same protocol.
HTTP 402 Native
Built on the HTTP 402 Payment Required status code. Payment negotiation happens within standard HTTP request/response cycles.
Challenge-Based Sessions
Uses cryptographic challenge-response for payment verification. Each challenge is secured with a 32-byte random secret.
Machine-to-Machine First
Designed for autonomous agents and programmatic clients. No browser redirects or human interaction required.
How MPP Works
Client requests a paid resource from the server
Server returns HTTP 402 with a payment challenge (challengeId, amount, currency, accepted methods)
Client completes payment — either on-chain (crypto to deposit address) or off-chain (card/wallet via SPT)
Client retries the request with payment proof in the Authorization header
Server verifies the credential and returns 200 OK with the requested resource
Payment Methods
Two payment rails, one protocol
Crypto Payments
On-chain stablecoin payments via deposit addresses. The server provides a blockchain address, the client sends tokens directly. Settlement is confirmed on-chain.
- 1Server returns 402 with deposit address and supported tokens
- 2Client sends USDC to the deposit address on-chain
- 3Stripe auto-captures the PaymentIntent on fund arrival
- 4Client retries with Authorization header containing payment proof
SPT (Shared Payment Token) Payments
Fiat payments via cards, wallets, and other Stripe-supported methods. The client creates a token that the server uses to charge through Stripe's payment network.
- 1Client creates an SPT (Shared Payment Token)
- 2Server uses the token to create a Stripe PaymentIntent
- 3Payment processes through Stripe's rails (card, Link, etc.)
- 4Server verifies completion and grants access
Crypto Payments — Flow
Request paid resource (no payment)
Use crypto payment method
POST /v1/payment_intents
Return PaymentIntent with deposit address
HTTP 402 with payment requirements
Retry request with payment proof
Return requested resource
SPT (Shared Payment Token) Payments — Flow
Request paid resource (no payment)
HTTP 402 with payment requirements
Create Shared Payment Token (SPT)
Return SPT
Retry request with SPT credential
Create PaymentIntent with SPT
POST /v1/payment_intents
Return confirmed PaymentIntent
Return requested resource
HTTP Protocol Details
402 response and Authorization header specification
402 Response Body
When payment is required, the server returns a JSON problem details object following RFC 9457.
{
"type": "https://paymentauth.org/problems/payment-required",
"title": "Payment Required",
"status": 402,
"detail": "Payment is required to access this resource.",
"challengeId": "ch_1abc2def3ghi..."
}PaymentIntent (Crypto)
{
"id": "pi_123",
"amount": 5000,
"currency": "usd",
"status": "requires_action",
"next_action": {
"type": "crypto_display_details",
"crypto_display_details": {
"deposit_addresses": {
"tempo": {
"address": "0x...",
"supported_tokens": [
{
"token_currency": "usdc",
"token_contract_address": "0x..."
}
]
}
}
}
}
}Authorization Header
After payment, the client includes proof in the Authorization header. The scheme is extracted and validated by the server.
Code Example
Crypto Payments (Node.js)
// Server: MPP crypto payment endpoint
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2026-03-04.preview',
});
// 1. Client requests resource → server returns 402
app.get('/api/data', async (req, res) => {
const credential = Credential.fromRequest(req);
if (!credential) {
const challenge = await createChallenge({
amount: 500, // $5.00
currency: 'usd',
});
return res.status(402).json({
type: 'https://paymentauth.org/problems/payment-required',
title: 'Payment Required',
status: 402,
challengeId: challenge.id,
});
}
// 4. Verify payment credential
const scheme = Credential.extractPaymentScheme(credential);
const verified = await verifyPayment(scheme);
if (verified) {
return res.json({ data: 'protected resource' });
}
});SPT (Shared Payment Token) Payments (Client)
// Client: SPT (Shared Payment Token) flow
const response = await fetch('https://api.example.com/data');
if (response.status === 402) {
const challenge = await response.json();
// Create SPT and complete payment via Stripe
const payment = await stripe.charge({
networkId: 'internal',
paymentMethodTypes: ['card', 'link'],
secretKey: process.env.STRIPE_SECRET_KEY,
});
// Retry with Authorization header
const result = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${payment.token}`,
},
});
const data = await result.json();
}Security
Challenge Secret — 32-byte cryptographic random value (Base64-encoded) secures each payment challenge
Credential Verification — Server extracts and validates payment scheme, PaymentIntent ID, and address consistency
Replay Protection — Each challenge is single-use with unique identifiers
Ecosystem
Key organizations behind MPP
Stripe
Global payments infrastructure, MPP protocol co-creator, fiat payment rails
Tempo
On-chain payment infrastructure, crypto payment rails, stablecoin settlement
Testing & Tools
Stripe Sandbox for test transactions with simulated crypto deposits
mppx CLI tool (npm package) for command-line payment testing
Tempo testnet with PATH_USD test tokens for crypto flow development