Verifiable receipts
Every chat completion and embedding comes with a signed receipt: a small, metadata-only attestation that Sable served the request, on which node, in which region, under which tier — signed with secp256k1 so anyone can verify it without trusting us. The receipt proves that inference happened and how; it never carries the prompt or completion.
What you get back
Non-streaming POST /v1/chat/completions and POST /v1/embeddings
responses add four headers:
x-sable-receipt— base64url of the canonical JSON receipt payloadx-sable-receipt-sig—0xsecp256k1 signature over the payload, using the EIP-191 (personal_sign) schemex-sable-receipt-signer— the0xaddress that signed itx-sable-region— the region the request was routed through
curl -i https://api.buildsable.com/v1/chat/completions \
-H "Authorization: Bearer $SABLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sable-llama-3.3-70b",
"messages": [{"role":"user","content":"hi"}]
}'
# ... response headers ...
# x-sable-region: eu-central
# x-sable-receipt: eyJ2IjoxLCJyZXF1ZXN0X2lkIjoi...
# x-sable-receipt-sig: 0x4f8c...1b
# x-sable-receipt-signer: 0xA1b2...9FThe receipt payload
Base64url-decode x-sable-receipt and you get canonical JSON. It is
metadata only — note content_fingerprint, a SHA-256 over the sealed
payload, not the content itself.
{
"v": 1,
"request_id": "req_8f3c...",
"content_fingerprint": "9b1c4e...",
"model": "sable-llama-3.3-70b",
"privacy_tier": "confidential",
"node": "sable-node-fra-1",
"region": "eu-central",
"prompt_tokens": 12,
"completion_tokens": 48,
"total_tokens": 60,
"cost_micro_usd": 540,
"logging": "metadata-only",
"issued_at": "2026-05-30T12:00:00Z"
}
The fingerprint lets you bind a receipt to a specific request you made
(hash your own sealed envelope and compare) without ever exposing the
plaintext to the receipt itself. cost_micro_usd is the metered cost in
millionths of a dollar — see Cost & metering.
Confidential-tier attestation
A request on the confidential tier (today, sable-confidential-24b)
adds an attestation block — also metadata only — proving it ran inside an
attested Intel TDX enclave. Standard-tier receipts omit it entirely.
{
"attestation": {
"platform": "nvidia-cc",
"measurement": "3b6dd335…",
"mrtd": "f06dfda6…",
"tcb_status": "UpToDate",
"verification": "tee-attested",
"response_bound": true,
"signer": "0x79a5061e…"
}
}
The gateway verifies the enclave's TDX quote against a pinned measurement
before routing, and verifies a per-response signature from the key bound into
that quote after — so verification: "tee-attested" with response_bound: true
means this specific response came from a correctly-measured enclave the host
couldn't see into. The public GET /v1/attestation returns the live verified
status, and the SDK's verifyAttestation() checks it as a pre-flight before you
send anything.
Streaming
A streamed chat completion can't set trailing headers, so the receipt arrives as the final SSE event after the stream ends:
event: sable.receipt
data: {"receipt":"eyJ2Ijox...","signature":"0x4f8c...","signer":"0xA1b2...9F"}
Read it the same way you'd read the headers: base64url-decode receipt for
the payload, verify signature against signer.
Verifying a receipt
Because receipts use standard secp256k1 + EIP-191, any Ethereum signature
library verifies them. Recover the signer over the decoded payload
string (atob(receipt)) and check it equals x-sable-receipt-signer.
import { verifyMessage } from "viem";
// receipt = x-sable-receipt, signature = x-sable-receipt-sig,
// signer = x-sable-receipt-signer
async function verifyReceipt(
receipt: string,
signature: `0x${string}`,
signer: `0x${string}`,
): Promise<boolean> {
const payload = atob(receipt); // base64url -> canonical JSON string
return verifyMessage({ address: signer, message: payload, signature });
}
// ethers works too:
// ethers.verifyMessage(payload, signature) === signerVerify endpoints
Two public endpoints (no auth) help you verify without wiring up crypto yourself:
GET /v1/receipts/pubkey→{ "scheme": "secp256k1-eip191", "signer_address": "0x…", "verify": "…" }. Pinsigner_addressfor your deployment.POST /v1/receipts/verifywith body{ receipt, signature }→{ "valid": true, "signer_address": "0x…", "recovered_address": "0x…", "payload": { … } }.validistrueonly when the recovered address matches the deployment signer.
The signing key is derived from the deployment's master key, so the signer
address is stable per deployment — fetch it once from
/v1/receipts/pubkey, pin it, and reject any receipt that recovers to a
different address.