Skip to main content
A receipt is the gateway’s signed record of one request: an ordered event log capturing what it received, which upstream it verified, and what it returned, with a hash at each step. It’s signed by a key published in the attestation report, so a verified receipt proves the response came from the attested workload and wasn’t altered. Every confidential response returns the receipt id in the x-receipt-id header (streaming: x_receipt_id on the final usage chunk). t2 chat --model phala/… surfaces it inline: 🔒 confidential · attested · receipt rcpt-….

Fetch a receipt

curl "https://api.t2000.ai/v1/aci/receipts/{x-receipt-id}"
{
  "api_version": "aci/1",
  "receipt_id": "rcpt-…", "chat_id": "…",
  "workload_id": "sha256:…",            // must match the attestation you verified
  "workload_keyset_digest": "sha256:…",
  "endpoint": "/v1/chat/completions", "served_at": 1782817781,
  "event_log": [  ],                    // the transparency events below
  "signature": { "algo": "ecdsa-secp256k1", "key_id": "dstack-kms-receipt-v1", "value": "…" }
}

Durable + anchored — verify any time

Every confidential response is automatically anchored on Sui (a ReceiptAnchored event over the wire_hash + workload_id), and its signed receipt is durably stored. So GET /v1/aci/receipts/{id} keeps working after the upstream gateway’s short receipt-retention window lapses — it transparently serves the durable copy. Verification stays trustless wherever the body is served: the receipt is signed and its hash is anchored on-chain, so it can’t be forged. Verify any time with t2 verify or in the browser at verify.t2000.ai.

The transparency event log

Each event carries a hash or a fact — never your prompt text:
EventRecords
request.receivedHash of the request body the gateway observed
route.selectedThe upstream route the backend accepted
request.forwardedHash of the provider-facing request body
upstream.verifiedThe upstream verification result + binding + typed claims (see attested sessions)
response.returnedwire_hash of the final response — what you match against the bytes you received

Why hashes, not bodies

The gateway stores hashes, not your request or response content — proving integrity without warehousing your data (zero data retention). The response.returned.wire_hash is what lets you prove the signature covers the exact bytes you received.

Streaming

For streaming, the x-receipt-id can return early, but the signed receipt is complete only after the stream finishes (the wire_hash covers the full body). Fetch it after the stream ends. Next: verify a response checks the receipt signature + the on-chain anchor yourself.