Wire Format Specification
The PEAC receipt wire format is a JWS (JSON Web Signature) compact serialization with Ed25519 signatures. Wire format peac-receipt/0.1 is FROZEN.
Versioning Doctrine
The repository version (0.10.13) is decoupled from the wire format version (peac-receipt/0.1). Wire format peac-receipt/0.1 is FROZEN until v1.0. New features are added via extension claims, not breaking changes to the core format.
Wire Format Identifier
Type (typ)
peac-receipt/0.1Algorithm (alg)
EdDSAKey Type (crv)
Ed25519Current Key ID (kid)
peac-2026-02JWS Structure
PEAC receipts are encoded as JWS Compact Serialization (RFC 7515) with three base64url-encoded parts separated by periods:
BASE64URL(header).BASE64URL(payload).BASE64URL(signature) // Example receipt structure: eyJ0eXAiOiJwZWFjLXJlY2VpcHQvMC4xIiwiYWxnIjoiRWREU0EiLCJraWQiOiJwZWFjLTIwMjYtMDEifQ. eyJyaWQiOiIwMUpRWEY4...
Protected Header
The protected header contains algorithm and type information:
| Claim | Value | Required | Description |
|---|---|---|---|
typ | peac-receipt/0.1 | Yes | Wire format type identifier |
alg | EdDSA | Yes | Signature algorithm (Ed25519 only) |
kid | peac-YYYY-MM | Yes | Key ID for JWKS lookup |
Payload Claims
The payload contains the receipt data:
| Claim | Type | Required | Description |
|---|---|---|---|
rid | string | Yes | Receipt ID (ULID format) |
iat | number | Yes | Issued at (Unix timestamp) |
exp | number | Yes | Expiration time (Unix timestamp) |
iss | string | Yes | Issuer (HTTPS URL) |
aud | string | Yes | Audience (recipient domain) |
sub | string | No | Subject identifier |
payment | object | No | Payment details (rail, amount, currency) |
control | object | No | Control decision details |
purpose_* | any | No | Purpose-specific extension claims |
Content Hash Format
Content hashes follow a specific format for interoperability:
// Format: algorithm:hex_value "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" // Requirements: // - Algorithm: sha256 (only supported algorithm) // - Value: 64 lowercase hexadecimal characters // - Total length: 71 characters (sha256: + 64 hex chars)
Example Receipt
A complete example of a PEAC receipt payload:
{
"rid": "01JQXF8N7K4P2R3S5T6V7W8X9Y",
"iat": 1706659200,
"exp": 1706662800,
"iss": "https://payment.example.com",
"aud": "api.consumer.com",
"sub": "agent:openai-gpt4",
"payment": {
"rail": "x402",
"amount": "0.05",
"currency": "USD",
"tx_hash": "0x1234...abcd"
},
"control": {
"decision": "allow",
"purposes": ["inference"],
"policy_version": "peac-policy/0.1"
}
}HTTP Transport
Receipts are transmitted via the PEAC-Receipt HTTP header as a detached JWS compact serialization:
# Request with receipt GET /api/resource HTTP/1.1 Host: api.example.com PEAC-Receipt: eyJhbGciOiJFZERTQSIsInR5cCI6InBlYWMtcmVjZWlwdC8wLjEiLCJraWQiOiJwZWFjLTIwMjYtMDEifQ.eyJyaWQiOiIwMUpRWEY4... # The header contains the complete JWS: # - Protected header (base64url) # - Payload (base64url) # - Signature (base64url)
Verification Process
Receipt verification follows these steps:
- Parse the JWS compact serialization
- Decode and validate the protected header
- Verify
typispeac-receipt/0.1 - Verify
algisEdDSA - Fetch JWKS from issuer's
/.well-known/jwks.json - Find key matching
kidin JWKS - Verify Ed25519 signature over
header.payload - Validate payload claims (
iat,exp,iss,aud)