Wire Format
The PEAC wire format defines the on-the-wire representation of receipts. It is a compact JWS (JSON Web Signature, RFC 7515) with an Ed25519 signature (RFC 8032).
Two wire formats coexist: Wire 0.1 (peac-receipt/0.1, frozen legacy) and Wire 0.2 (interaction-record+jwt, stable). Both use Ed25519 JWS signatures and the PEAC-Receipt header. verifyLocal() auto-detects wire version.
Wire 0.1 (Stable)
Wire 0.1 uses flat payload claims with a simple structure.
Header
{
"alg": "EdDSA",
"typ": "peac-receipt/0.1",
"kid": "<key-id>"
}
| Field | Requirement | Value |
|---|---|---|
alg | MUST | EdDSA (Ed25519, RFC 8032) |
typ | MUST | peac-receipt/0.1 |
kid | MUST | Match a key in the issuer's published JWKS |
Payload
{
"iss": "https://api.example.com",
"aud": "https://client.example.com",
"iat": 1709500000,
"amt": 100,
"cur": "USD",
"rail": "x402",
"reference": "tx_abc123",
"subject": "https://api.example.com/inference"
}
Wire 0.2 (Stable)
Wire 0.2 (interaction-record+jwt) adds structured kinds, typed extensions, and policy binding.
Header
{
"alg": "EdDSA",
"typ": "interaction-record+jwt",
"kid": "<key-id>"
}
| Field | Requirement | Value |
|---|---|---|
alg | MUST | EdDSA (Ed25519, RFC 8032) |
typ | MUST | interaction-record+jwt |
kid | MUST | Match a key in the issuer's published JWKS (max 256 chars) |
Wire 0.2 rejects embedded keys (jwk, x5c, x5u, jku), crit, b64: false, and zip headers.
Payload
{
"iss": "https://api.example.com",
"iat": 1709500000,
"peac_version": "0.2",
"kind": "evidence",
"type": "org.peacprotocol/payment",
"pillars": ["commerce"],
"extensions": {
"org.peacprotocol/commerce": {
"payment_rail": "x402",
"amount_minor": "10000",
"currency": "USD"
}
},
"policy": {
"uri": "https://api.example.com/.well-known/peac.txt",
"version": "peac-policy/0.1",
"digest": "sha256:a1b2c3..."
}
}
Wire 0.2 Payload Claims
| Field | Required | Description |
|---|---|---|
iss | Yes | Issuer (canonical: https:// or did: only) |
iat | Yes | Issued-at timestamp (Unix seconds) |
peac_version | Yes | Must be "0.2" |
kind | Yes | Structural kind: evidence or challenge |
type | Yes | Semantic type (reverse-DNS or absolute URI) |
pillars | No | Verification domains (sorted, unique, from 10-pillar taxonomy) |
extensions | No | Typed extension groups (keyed by reverse-DNS) |
policy | No | Policy binding (uri, version, digest) |
occurred_at | No | ISO 8601 event time (evidence kind only) |
actor | No | Actor binding (identity proof) |
representation | No | Content representation fields |
Extension Groups
Wire 0.2 defines 12 typed extension groups:
| Key | Fields | Description |
|---|---|---|
org.peacprotocol/commerce | payment_rail, amount_minor, currency, reference?, asset?, env? | Payment evidence |
org.peacprotocol/access | resource, action, decision (allow/deny/review) | Access control |
org.peacprotocol/challenge | challenge_type, problem (RFC 9457) | Challenge requirements |
org.peacprotocol/identity | proof_ref? | Identity attestation |
org.peacprotocol/correlation | trace_id?, span_id?, workflow_id?, parent_jti?, depends_on? | Workflow correlation |
Kind Semantics
evidence: records something that happened. May includeoccurred_at.challenge: declares what is required before proceeding. Uses RFC 9457 problem details. Must NOT includeoccurred_at.
Policy Binding
Wire 0.2 supports policy binding via JCS (RFC 8785) + SHA-256. The policy.digest field contains sha256:<64-hex-chars>. Verification returns one of three states: verified, failed, or unavailable.
Common: Signature
The signature is an Ed25519 signature computed over the JWS signing input (<header>.<payload>). Both wire formats use identical signature computation.
Delivery
HTTP
Receipts are delivered via the PEAC-Receipt response header.
HTTP/1.1 200 OK
Content-Type: application/json
PEAC-Receipt: eyJhbGciOiJFZERTQSIsInR5cCI6InBlYWMtcmVjZWlwdC8wLjEiLCJraWQiOiJwZWFjLTIwMjYtMDMifQ...
Non-HTTP transports
For MCP, gRPC, WebSocket, and other non-HTTP transports, receipts are included in the response metadata using the transport's native metadata mechanism. The receipt format is identical: only the delivery channel changes.
Versioning
peac-receipt/0.1(Wire 0.1): frozen legacy receipt formatinteraction-record+jwt(Wire 0.2): stable with structured kinds, typed extensions, and policy bindingverifyLocal()auto-detects wire version and returnswireVersion: '0.1'orwireVersion: '0.2'- Both formats use Ed25519 JWS signatures and the
PEAC-Receiptheader