x402 Integration
Verifiable payment evidence for HTTP 402 flows. When a server returns 402 Payment Required, the client pays, and PEAC records verifiable evidence of what happened. The receipt travels back to the server via the PEAC-Receipt header.
Built on the Evidence Carrier Contract.
How It Works
1. Server returns 402
The server responds with HTTP 402 Payment Required and an x402 offer describing the payment terms (amount, currency, accepted methods).
2. Client pays
The client (or agent) completes the payment via the specified payment rail. The x402 facilitator returns a settlement response.
3. PEAC records evidence
The settlement response is normalized into a PEAC receipt using @peac/rails-x402. The receipt is signed and attached to the retry request.
4. Receipt travels via header
The compact JWS is carried in the PEAC-Receipt HTTP header (8 KB limit). The server can verify the receipt before serving the resource.
Packages
The x402 integration is split into two packages with distinct responsibilities:
@peac/rails-x402
Layer 4: Payment Rail
Normalizes x402 offers and settlement responses into PEAC payment records. Maps payment fields (amount, currency, tx_hash) into the receipt payment claim.
@peac/adapter-x402
Layer 4: Evidence Carrier
Attaches and extracts receipts from x402 HTTP responses. Implements the CarrierAdapter interface for the PEAC-Receipt header. Four-layer architecture with 5-layer verification API.
Install
pnpm add @peac/rails-x402 @peac/adapter-x402
Receipt Issuance from Settlement
import { fromSettlement } from '@peac/rails-x402';
import { issue } from '@peac/protocol';
import { generateKeypair } from '@peac/crypto';
const { privateKey } = await generateKeypair();
// Settlement response observed from the x402 facilitator (PEAC does not settle)
const settlement = {
amount: '0.05',
currency: 'USD',
rail: 'x402',
tx_hash: '0x1234...abcd',
settled_at: '2026-02-25T12:00:00Z',
};
// Normalize the observed settlement into PEAC commerce extension fields
const commerce = fromSettlement(settlement);
// Issue a signed Wire 0.2 record observing the settlement
const { jws } = await issue({
iss: 'https://publisher.example.com',
kind: 'evidence',
type: 'org.peacprotocol/payment',
pillars: ['commerce'],
extensions: { 'org.peacprotocol/commerce': commerce },
privateKey,
kid: 'peac-2026-03',
});
// Attach to retry request via PEAC-Receipt header
const response = await fetch('https://api.example.com/resource', {
headers: {
'PEAC-Receipt': jws,
},
});HTTP Transport
The PEAC-Receipt header carries the compact JWS. The 8 KB header size limit applies.
GET /api/resource HTTP/1.1 Host: api.example.com PEAC-Receipt: eyJhbGciOiJFZERTQSIsInR5cCI6InBlYWMtcmVjZWlwdC8wLjEifQ...
v1 / v2 dual-header read
x402 settlement evidence is surfaced in different response headers across protocol versions. The adapter (@peac/adapter-x402) detects the version and reads the correct header, preserving the upstream artifact verbatim. The signed PEAC record always travels inPEAC-Receipt.
| Header | Version | Role |
|---|---|---|
PEAC-Receipt | all | Carries the signed PEAC interaction record (compact JWS) |
PAYMENT-RESPONSE | x402 v2 | Upstream x402 v2 settlement artifact (preserved as observed) |
X-PAYMENT-RESPONSE | x402 v1 | Upstream x402 v1 settlement artifact (preserved as observed) |
import {
detectX402Version,
extractSettlementProofFromHeaders,
fromX402SettlementObservation,
} from '@peac/adapter-x402';
// Detect v1 vs v2 and read the correct upstream settlement header
const version = detectX402Version(response.headers);
const proof = extractSettlementProofFromHeaders(response.headers);
// Normalize the observed settlement into PEAC commerce extension fields
const commerce = fromX402SettlementObservation(proof);
// PEAC-Receipt stays the compact JWS; the upstream artifact is preserved verbatimWhat PEAC records in an x402 flow
PEAC records observations of each state in the payment flow. Each is an evidence record; none of them execute or decide the payment.
| State | What is recorded |
|---|---|
| Offer / payment-required | The 402 challenge and its terms as presented |
| Payment submitted | That a payment attempt was made against the offer |
| Facilitator timeout | That the facilitator did not respond within the window |
| Settlement confirmed | The facilitator-attested settlement artifact (tx hash or reference) |
| Settlement failed | A facilitator-attested failure result |
| Unresolved settlement | That no terminal settlement state was observed |
| Budget / upto | An upto or budget authorization observation (no finality implied) |
What PEAC does and does not do
PEAC records and verifies observations of an x402 flow. It does not settle payments, custody funds, authorize or process transactions, operate a facilitator, or decide finality. The facilitator owns settlement; PEAC makes the observation verifiable outside the system that produced it.
Canonical specifications
Supported Payment Methods
The x402 rail supports crypto rails and fiat facilitators. PEAC records evidence of the settlement regardless of the underlying payment mechanism.
| Category | Description |
|---|---|
| Crypto rails | On-chain settlement with transaction hash evidence |
| Fiat facilitators | Card and account-based payments via payment processor APIs |
Implementation examples
| Provider | Type | Evidence Field |
|---|---|---|
| Base network (USDC) | Crypto rail | tx_hash |
| Stripe x402 profile | Fiat facilitator | payment_intent_id |
Payment Claim Structure
The payment claim in the receipt payload contains normalized settlement data:
| Field | Type | Description |
|---|---|---|
rail | string | Payment rail identifier ("x402") |
amount | string | Settlement amount as a decimal string |
currency | string | ISO 4217 currency code or token symbol |
tx_hash | string | Transaction hash or payment reference (optional) |
Links
Evidence Carrier Contract
The x402 adapter implements the CarrierAdapter interface shared across all PEAC integrations. Receipts issued from x402 settlements are portable: the same receipt can be carried through MCP, A2A, ACP, UCP, and HTTP transports.