Skip to content

OpenReceipt protocol

The OpenReceipt protocol is an open spec — read the canonical version at signedreceipts.org/spec. This page summarises how CloakAPI implements it.

Two envelopes in production

CloakAPI issues two envelope kinds today, depending on the way you use:

  • v3 (client-signed) — on the client-side ways (browser chat, desktop app, browser extension), the device that performed the tokenisation signs an OpenReceipt v3 envelope (v: "v3", alg: "ecdsa-p256-sha256") before egress, carrying the v3-attestation claim set (what egressed, which detector categories fired, engine hashes, trust tier). When the request goes through the gateway, the gateway verifies the client signature and adds an additive countersignature witnessing provider, model, and upstream byte hashes. See the v3 specification for the normative format.
  • v2 (gateway-signed) — on the bare-SDK API way (api.cloakapi.io), the gateway seals every response with the v2 flat envelope described below.

v2 envelope shape

The v2 envelope is a flat JSON object signed with ES256 (ECDSA P-256 over SHA-256), canonicalised per RFC 8785 (JCS), and chain-linked per tenant.

{
"v": 2,
"alg": "ES256",
"kid": "cloakapi-gateway-receipt-2026-q3-es256",
"iss": "https://api.cloakapi.io",
"jti": "9f1c2b7a4e8d4f0a8c3b2d1e6f7a0b9c",
"iat": 1759420800,
"timestamp": "2026-04-18T12:00:00.000Z",
"request_id": "req_01HWRK9GTBF3MXQJ4VZPND",
"provider": "openai",
"model": "gpt-4o",
"input_tokens": 184,
"output_tokens": 312,
"hash_upstream_request": "sha256:b3a…",
"hash_upstream_response": "sha256:c91…",
"chain": {
"chain_id": "receipt-v2-org-42",
"seq": 47,
"prev_hash": "sha256:a3f8c2…"
},
"signature": "BASE64URL_RAW_R_S_ECDSA_SIGNATURE"
}
FieldMeaning
vProtocol version. Integer 2 for the gateway-signed flat envelope (client-signed receipts use string "v3").
algSigning algorithm. "ES256" (ECDSA P-256 over SHA-256).
kidKey id — look up the matching key in the public JWKS to get the verifying key.
issIssuer URL (https://api.cloakapi.io).
jtiUnique receipt id (128-bit random hex).
iatUnix-seconds timestamp the gateway sealed the response.
timestampRFC 3339 timestamp with millisecond precision, always UTC (Z).
provider / modelUpstream provider slug and model the call was routed to.
input_tokens / output_tokensToken counts billed for the call.
hash_upstream_request / hash_upstream_responseSHA-256 of the on-the-wire bytes — never the bytes themselves.
chain.chain_idPer-tenant chain identifier (receipt-v2-org-<org_id>).
chain.seqMonotonically increasing per-tenant sequence number.
chain.prev_hashHash of the previous receipt’s canonical bytes (same chain). Lets auditors detect missing or out-of-order receipts.
signatureURL-safe base64 (unpadded) raw r‖s (64-byte) ECDSA signature over the JCS-canonical bytes of the envelope with signature removed.

Where to find the public key

  • JWKS: https://api.cloakapi.io/api/.well-known/cloakapi-receipt-pubkeys.jwks
  • PEM: https://api.cloakapi.io/api/.well-known/cloakapi-receipt-pubkey.pem

Keys rotate quarterly. Old keys remain in the JWKS so historic receipts keep verifying indefinitely.