Skip to main content
Version: v0.16.1

x402 Payment Protocol

PEAC integrates with HTTP 402-based payment protocols through two packages: @peac/rails-x402 for payment evidence extraction and @peac/adapter-x402 for evidence carrier transport. Together they enable payment receipts that are verifiable, portable, and transport-neutral.


Install

Terminal
# Payment evidence extraction
pnpm add @peac/rails-x402

# Evidence carrier for x402 responses
pnpm add @peac/adapter-x402

How it works

The x402 payment flow uses HTTP 402 (Payment Required) responses to negotiate payment before granting access. PEAC attaches evidence of the completed payment to a receipt.

x402 Payment Flow
Client -> Server: GET /api/data
Server -> Client: 402 Payment Required (payment details)
Client -> Payment: Complete payment
Client -> Server: GET /api/data + X-PAYMENT header
Server -> Client: 200 OK + PEAC-Receipt header

The receipt captures the settlement reference, amount, currency, and payment rail without storing sensitive payment details.


Payment evidence

Extract the signed settlement receipt from x402 response headers:

x402-evidence.ts
import { extractReceiptFromHeaders } from '@peac/adapter-x402';

// x402 settlement responses carry the receipt in X-PAYMENT-RESPONSE
const receipt = extractReceiptFromHeaders(res.headers);

The extractReceiptFromHeaders function returns the upstream signed receipt, or null when no settlement receipt is present:

RawSignedReceipt
{
format: 'jws', // 'jws' or 'eip712'
signature: '0xabc123...',
// ...remaining upstream receipt fields as sent by the x402 facilitator
}

Evidence carrier

The @peac/adapter-x402 package implements the Evidence Carrier Contract for x402 responses, placing receipt evidence in HTTP response headers.

x402-carrier.ts
import { toPeacCarrier, extractReceiptFromHeaders } from '@peac/adapter-x402';

// Build a PEAC evidence carrier from a signed receipt JWS, then send it
// in the PEAC-Receipt response header
const carrier = await toPeacCarrier(receiptJws);
res.setHeader('PEAC-Receipt', carrier.receipt_jws);

// Extract the signed receipt from an incoming x402 response
const receipt = extractReceiptFromHeaders(incomingResponse.headers);

Transport limits

ConstraintValue
Header size limit8 KB
Header namePEAC-Receipt
FormatCompact JWS

Issuing a payment receipt

Wire 0.1

issue-x402-receipt-wire01.ts
import { issue } from '@peac/protocol';
import { extractReceiptFromHeaders } from '@peac/adapter-x402';

// Confirm the x402 settlement response carries a signed receipt before
// recording the observed payment as a PEAC record
const settlement = extractReceiptFromHeaders(res.headers);
if (!settlement) throw new Error('No x402 settlement receipt present');

const receipt = await issue({
privateKey: process.env.PEAC_PRIVATE_KEY,
kid: 'peac-2026-03',
claims: {
iss: 'https://api.example.com',
aud: 'https://client.example.com',
amt: '0.001',
cur: 'USDC',
rail: 'x402',
reference: 'tx_abc123...',
},
});

Interaction Record format

issue-x402-receipt-wire02.ts
import { issue } from '@peac/protocol';

const receipt = await issue({
privateKey: process.env.PEAC_PRIVATE_KEY,
kid: 'peac-2026-03',
claims: {
iss: 'https://api.example.com',
kind: 'evidence',
type: 'org.peacprotocol/payment',
pillars: ['commerce'],
extensions: {
'org.peacprotocol/commerce': {
payment_rail: 'x402',
amount_minor: '1000',
currency: 'USDC',
},
},
},
});

Supported payment methods

The x402 adapter works with any payment method supported by the x402 ecosystem:

CategoryExamples
StablecoinsUSDC, USDT, DAI
CryptocurrenciesETH, BTC (via bridge)
Fiat wrappersStripe-backed x402
Category-first

PEAC extracts settlement evidence from the x402 response headers regardless of the underlying payment method. The same extractReceiptFromHeaders function handles all x402-compatible payment flows.


Implementation examples

Express middleware with x402

express-x402.ts
import express from 'express';
import { peacMiddleware } from '@peac/middleware-express';

const app = express();

app.use(peacMiddleware({
privateKey: process.env.PEAC_PRIVATE_KEY,
kid: 'peac-2026-03',
issuer: 'https://api.example.com',
}));

app.get('/api/data', (req, res) => {
// x402 payment already completed at this point
// PEAC middleware auto-attaches receipt to response
res.json({ data: 'protected content' });
});

Next steps