- A receipt is the signed record for one response.
- A session is the immutable verified security context for a confidential upstream channel.
Receipt Lifecycle
A completed inference response identifies its receipt withx-receipt-id. A stream whose headers were committed before the id was allocated may instead require lookup by response id after completion. Fetch it with Get Receipt:
What a Receipt Proves
A verified receipt proves:- The receipt was signed by a key in the attested gateway keyset.
workload_keyset_digestmatches the verified attestation report.- The exact request bytes match
request.received.body_hash, and the returned response bytes matchresponse.returned.body_hash. - The required upstream verification result is recorded. On this TEE-only endpoint
requiredistrue; a failed check refuses forwarding.
signature removed. Resolve key_id in the verified keyset’s receipt_signing_keys; the Phala key is dstack-kms-receipt-ed25519-v1 (ed25519). Hash comparisons alone do not verify the signature or attestation. Use the TypeScript SDK or Private AI Proxy.
Streaming Responses
For streaming,x-receipt-id can arrive before the stream ends. Fetch the receipt after the stream completes because response.returned.body_hash covers the full response body.
Attested Sessions
When the gateway verifies a confidential upstream, it records an attested session. A receipt references it fromupstream.verified.session_id.
A session captures:
- Verified upstream identity and endpoint.
- Enforced channel binding.
- Typed claims and reasons.
- Evidence digest and evidence payload.
session_id is the bare 64-character lowercase SHA-256 digest of the complete session document in JCS form, with no prefix. It is not a field in the full document. If the material changes, the id changes. The list endpoint returns { "api_version": "aci/1", "sessions": [...] }; entries include session_id but omit evidence.data. Fetch the full record before checking the content address. Filter the list with ?upstream_name=chutes or ?model=z-ai/glm-5.3.

