Skip to main content
Version: v0.16.4

MPP / paymentauth

The @peac/mappings-paymentauth package provides PEAC evidence for the Machine Payments Protocol (MPP), also known as paymentauth (draft-ryan-httpauth-payment). MPP enables HTTP-native payment challenges and receipts using the Authorization and WWW-Authenticate headers, complementing x402-style payment flows.


What is MPP?​

MPP (Machine Payments Protocol) defines an HTTP authentication-based payment mechanism. A server signals that payment is required by returning a WWW-Authenticate: paymentauth challenge. The client responds with an Authorization: paymentauth credential containing payment proof.

IETF draft: draft-ryan-httpauth-payment (Machine Payments Protocol)

How MPP and x402 compare:

DimensionMPP / paymentauthx402
HTTP mechanismAuthorization / WWW-Authenticate headersHTTP 402 status code + custom headers
Challenge formatWWW-Authenticate: paymentauth challenge="..."X-PAYMENT-REQUIRED header
Payment credentialAuthorization: paymentauth token="..."X-PAYMENT header
IETF statusActive internet draft (draft-ryan-httpauth-payment)Linux Foundation spec (x402.org)
PEAC package@peac/mappings-paymentauth@peac/adapter-x402, @peac/rails-x402
Evidence typeChallenge observation + receipt observationPayment request + payment proof

Both MPP and x402 are supported by PEAC. Use them together for maximum payment rail coverage.


Install​

Terminal
pnpm add @peac/mappings-paymentauth @peac/protocol

Quick start​

Record an MPP payment challenge​

When your server issues an MPP payment challenge, issue a PEAC record of the challenge:

mpp-challenge.ts
import { parsePaymentauthChallenges, normalizeChallenge } from '@peac/mappings-paymentauth';
import { issue } from '@peac/protocol';

// Parse the WWW-Authenticate challenge your server issued
const [raw] = parsePaymentauthChallenges(
'Payment realm="api.example.com", request="<base64url>"',
);
const challenge = normalizeChallenge(raw);

// Record the observed challenge as a signed PEAC evidence record
const { jws } = await issue({
iss: 'https://api.example.com',
kind: 'evidence',
type: 'org.peacprotocol/paymentauth-challenge-observed',
privateKey: signingKey,
kid: 'peac-2026-03',
extensions: {
'org.peacprotocol/paymentauth': {
challenge_id: challenge.id,
realm: challenge.realm,
intent: challenge.intent,
},
},
});

// Return in HTTP response
// WWW-Authenticate: Payment ...
// PEAC-Receipt: <jws>

Record an MPP payment receipt​

When a client presents valid payment proof, record the receipt:

mpp-receipt.ts
import { fromPaymentauthReceipt } from '@peac/mappings-paymentauth';
import { issue } from '@peac/protocol';

// Build extension from the payment credential the client presented
const ext = fromPaymentauthReceipt({
credential_ref: 'ref:payment-credential/txn-001',
scheme_id: 'usdcbase',
resource_ref: 'ref:resource/premium-endpoint',
settled_at: new Date().toISOString(),
});

const { jws } = await issue({
sub: 'ref:payment-credential/txn-001',
iss: 'https://api.example.com',
kind: 'evidence',
type: 'org.peacprotocol/paymentauth-receipt-observed',
privateKey: signingKey,
kid: 'peac-2026-03',
extensions: ext,
});

Type URIs​

Type URIDescription
org.peacprotocol/paymentauth-challenge-observedServer issued an MPP payment challenge
org.peacprotocol/paymentauth-receipt-observedClient presented valid payment proof
org.peacprotocol/paymentauth-rejection-observedPayment credential was rejected
org.peacprotocol/paymentauth-cancellation-observedPayment flow was cancelled

Express middleware integration​

express-mpp.ts
import express from 'express';
import { parsePaymentauthChallenges, normalizeChallenge } from '@peac/mappings-paymentauth';
import { issue } from '@peac/protocol';

const app = express();

app.use('/premium', async (req, res, next) => {
const authHeader = req.headers.authorization;

if (!authHeader?.startsWith('Payment ')) {
// Issue challenge + PEAC record of the challenge
const wwwAuthenticate = 'Payment realm="api.example.com", request="<base64url>"';
const [raw] = parsePaymentauthChallenges(wwwAuthenticate);
const challenge = normalizeChallenge(raw);

const { jws } = await issue({
iss: process.env.PEAC_ISSUER_URL!,
kind: 'evidence',
type: 'org.peacprotocol/paymentauth-challenge-observed',
privateKey: signingKey,
kid: 'peac-2026-03',
extensions: {
'org.peacprotocol/paymentauth': {
challenge_id: challenge.id,
realm: challenge.realm,
},
},
});

res
.status(401)
.set('WWW-Authenticate', wwwAuthenticate)
.set('PEAC-Receipt', jws)
.json({ error: 'Payment required' });
return;
}

// Validate payment credential, then record the receipt
next();
});

Finality rules​

Observer scope

MPP payment records are observer scope only. A paymentauth-receipt-observed record means your server observed the client present a payment credential. It does not guarantee:

  • That the underlying payment settled on-chain or in the payment network
  • That funds were transferred
  • That the payment credential was valid (only that it was presented)

Issue a paymentauth-receipt-observed record only after your payment validation logic confirms the credential is valid. The record attests to your server's validation outcome, not the payment network's settlement.


Combining MPP and x402​

For maximum coverage across payment rail clients, support both MPP (HTTP Auth headers) and x402 (HTTP 402 status). PEAC provides evidence packages for both:

multi-rail.ts
import { parsePaymentauthChallenges } from '@peac/mappings-paymentauth';
import { fromOfferResponse } from '@peac/adapter-x402';

// Detect the client's preferred payment mechanism
const clientPrefers = req.headers['accept-payment']?.includes('Payment')
? 'mpp'
: 'x402';

if (clientPrefers === 'mpp') {
// MPP: WWW-Authenticate: Payment + 401
const [challenge] = parsePaymentauthChallenges(wwwAuthenticate);
// ...
} else {
// x402: HTTP 402 + X-PAYMENT-RESPONSE
const result = fromOfferResponse(responseHeaders);
// ...
}

Non-goals​

MPP / paymentauth records do not:

  • Process payments or move funds
  • Validate payment credentials against a payment network
  • Replace your payment processor or settlement infrastructure
  • Guarantee finality from the paymentauth credential alone