Skip to main content
Version: v0.12.4

Receipts

A PEAC receipt is a compact JWS (JSON Web Signature) token signed with Ed25519 that provides cryptographic proof of an AI agent interaction. Receipts are the core proof artifact of the protocol: every interaction that matters gets a receipt.

Two wire formats

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.


Format

Receipts use compact JWS serialization: three Base64url-encoded segments separated by dots.

<base64url-header>.<base64url-payload>.<base64url-signature>

The JWS header identifies the signing algorithm, wire format version, and the key used to sign.

Wire 0.1 JWS Header
{
"alg": "EdDSA",
"typ": "peac-receipt/0.1",
"kid": "peac-2026-03"
}
Wire 0.2 JWS Header
{
"alg": "EdDSA",
"typ": "interaction-record+jwt",
"kid": "peac-2026-03"
}
FieldValueDescription
algEdDSAEd25519 signature algorithm (RFC 8032)
typpeac-receipt/0.1 or interaction-record+jwtWire format identifier (0.1 or 0.2)
kidKey ID stringIdentifies the signing key in the issuer's JWKS (max 256 chars)

Wire 0.2 rejects embedded keys (jwk, x5c, x5u, jku), crit, b64: false, and zip headers.

Wire 0.1 Payload

Wire 0.1 uses flat payload claims with a simple structure.

Wire 0.1 Receipt 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"
}
ClaimRequiredDescription
issYesIssuer URL: the service that signed the receipt
audNoIntended audience URL
iatYesIssued-at timestamp (Unix seconds)
amtNoPayment amount
curNoCurrency code (ISO 4217 or token symbol)
railNoPayment rail identifier (e.g., x402, stripe)
referenceNoTransaction reference
subjectNoSubject resource URL

Wire 0.2 Payload

Wire 0.2 adds structured kinds, typed extensions, and policy binding.

Wire 0.2 Evidence Receipt 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..."
}
}
ClaimRequiredDescription
issYesIssuer (canonical: https:// or did: only)
iatYesIssued-at timestamp (Unix seconds)
peac_versionYesMust be "0.2"
kindYesStructural kind: evidence or challenge
typeYesSemantic type (reverse-DNS or absolute URI)
pillarsNoVerification domains (sorted, unique, from 10-pillar taxonomy)
extensionsNoTyped extension groups (keyed by reverse-DNS)
policyNoPolicy binding (uri, version, digest)
occurred_atNoISO 8601 event time (evidence kind only)
actorNoActor binding (identity proof)
representationNoContent representation fields

Kind semantics

  • evidence: records something that happened. May include occurred_at.
  • challenge: declares what is required before proceeding. Uses RFC 9457 problem details. Must NOT include occurred_at.

Delivery

Receipts are delivered via the PEAC-Receipt HTTP response header.

HTTP Response
HTTP/1.1 200 OK
PEAC-Receipt: eyJhbGciOiJFZERTQSIsInR5cCI6...
Content-Type: application/json

{"result": "success"}

For non-HTTP transports, receipts are included in the response metadata using the appropriate transport convention:

TransportDelivery mechanism
HTTPPEAC-Receipt response header
MCPResponse _meta field
A2Ametadata[extensionURI].carriers[]
gRPCTrailing metadata
WebSocketMessage envelope field

Extension Groups (Wire 0.2)

Wire 0.2 defines 12 typed extension groups under extensions, keyed by reverse-DNS:

KeyDescription
org.peacprotocol/commercePayment evidence: payment_rail, amount_minor, currency, event
org.peacprotocol/accessAccess control: resource, action, decision (allow/deny/review)
org.peacprotocol/challengeChallenge requirements: challenge_type, problem (RFC 9457)
org.peacprotocol/identityIdentity attestation: proof_ref
org.peacprotocol/correlationWorkflow correlation: trace_id, span_id, workflow_id, parent_jti
org.peacprotocol/consentConsent records: consent_type, consent_status, data_subject
org.peacprotocol/privacyPrivacy controls: data_categories, retention, legal_basis
org.peacprotocol/safetySafety signals: safety_category, severity, model_id
org.peacprotocol/complianceCompliance evidence: framework, requirement_id, status
org.peacprotocol/provenanceContent provenance: source_uri, content_hash, derivation
org.peacprotocol/attributionAttribution records: creator, license, contribution_type
org.peacprotocol/purposePurpose declaration: declared_purpose, enforced_purpose
Wire 0.2 Extension Example
{
"extensions": {
"org.peacprotocol/commerce": {
"payment_rail": "x402",
"amount_minor": "10000",
"currency": "USD"
},
"org.peacprotocol/correlation": {
"trace_id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"workflow_id": "checkout-flow-123"
}
}
}
Third-party extensions

Third-party extensions use reverse-DNS keys under their own domain (e.g., com.example/custom-data). Unrecognized-but-well-formed keys are preserved with a warning during verification.


Issuance

Use @peac/protocol to issue receipts programmatically.

Wire 0.1

issue-wire-01.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',
aud: 'https://client.example.com',
amt: 100,
cur: 'USD',
rail: 'x402',
},
});

// receipt is a compact JWS string ready for delivery
res.setHeader('PEAC-Receipt', receipt);

Wire 0.2

issue-wire-02.ts
import { issueWire02 } from '@peac/protocol';

const receipt = await issueWire02({
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: '10000',
currency: 'USD',
},
},
},
});

res.setHeader('PEAC-Receipt', receipt);

Next steps