Skip to content

Receipt Schema

A receipta receipt is a JSON object: a body (the signed payload) and a detached signature (hex Ed25519 over the RFC 8785-canonical body).

json
{
  "body": {
    "schema_version": "receipta.v0",
    "suite": "ed25519",
    "chain_id": "550e8400-e29b-41d4-a716-446655440000",
    "seq": 1,
    "prev_hash": "0000...0000",
    "key_id": "a3f5...c91e",
    "timestamp": { "iso8601_ms": "2026-07-10T08:06:00.123Z", "trust_level": "local_asserted" },
    "actor": { "type": "service", "id": "my-app", "label": "support-bot" },
    "provider": "openai",
    "model": "gpt-4o-2024-08-06",
    "request_id": "req_abc123",
    "attempt_index": 0,
    "outcome": "success",
    "content_captured": true,
    "capture_mode": "full",
    "content": { "request": {/* ... */}, "response": {/* ... */} },
    "content_commitments": {
      "request": "b9d0...f1a2",
      "response": "7c4e...88ab",
      "request_integrity": "e3b0...b855",
      "response_integrity": "9a2f...11cd"
    },
    "usage": { "input_tokens": 12, "output_tokens": 7 }
  },
  "signature": "f3a1...c2b9"
}

attempt_index is best-effort: it is populated only when the provider's SDK sets a retry-count request header (the OpenAI and Anthropic Stainless SDKs set x-stainless-retry-count0 on the first attempt, incrementing on retry). When no retry-count header is present (a non-Stainless provider, a caller-supplied fetch, or a gateway that strips it), attempt_index is omitted from the receipt rather than defaulted to 0 — absence is honest, not "first attempt."

Fields

FieldMeaningInvariant
schema_version"receipta.v0" — gates verificationS1.8
suite"ed25519" — the signature suite (permits ML-DSA/FIPS later)S1.8
chain_idUUID of the store/chain this receipt belongs toS1.5
seq1-based sequence within the chainS1.5
prev_hashhex SHA-256 of the previous receipt body (all-zero for seq 1)S1.5
key_idhex SHA-256 of the signing public keyS3.1
timestamp.iso8601_msUTC millisecond ISO-8601 timestampS1.7
timestamp.trust_levellocal_asserted | rfc3161 | transparency_log | witnessS1.7
actorWho/what made the decision (distinct from the signing key)S3.2
provider"openai" | "anthropic" | "vercel-ai-sdk" | …
modelThe model that answered
request_idThe provider's request id (for correlation)
attempt_indexWhich retry attempt (best-effort; see note above)S2.2
outcome"success" | "error" | "retry"S2.2
content_capturedWhether prompt/completion bytes are presentS1.3
capture_mode"full" | "metadata_only"S1.3
contentCaptured request/response (absent if metadata-only)S1.3
content_commitmentsHMAC-SHA256 + integrity digests over contentS1.4
usageToken counts
anchor(reserved) external anchoring evidenceS1.6
extensionsExtension fields; critical: true unknowns fail verificationS1.8

Canonicalization

The signature is over the RFC 8785 canonicalization of body (the signature field itself is never signed). See Concepts › Deterministic bytes.

Released under the Apache-2.0 License.