# TEE Proofs (/docs/tee-proof)

Turn on TEE confidential computing proof for an API key, and its responses come with a receipt signed by [VeriRelay](https://verirelay.com). The receipt names the provider host that received your request, such as `api.anthropic.com`, and carries SHA-256 hashes of the request and response bodies. You check it on VeriRelay, so you don't have to take our word for it: VeriRelay's signing key exists only inside an AMD SEV-SNP confidential VM, and the attestation that proves this is public.

## Turn it on [#turn-it-on]

On the [API keys](https://www.ohmygpt.com/keys) page, create or edit a key and switch on **TEE confidential computing proof**. Your code stays the same; every request made with that key asks for a proof.

## What a proven response carries [#what-a-proven-response-carries]

```http
X-VeriRelay-Request-Id: 36a420474e713c4ecbe0a6d5dfd79ed0
X-VeriRelay-Store-Id: cFMrwmc4IeTQT14_R9y6gg
X-VeriRelay-Store-Key: <secret>
```

| Header | Use it to |
|---|---|
| `X-VeriRelay-Request-Id` | Fetch the signed receipt |
| `X-VeriRelay-Store-Id`, `X-VeriRelay-Store-Key` | Fetch and decrypt the request and response bodies exactly as the provider received and sent them. Treat the Store-Key as a secret: whoever holds it can read that exchange until VeriRelay deletes it. |

A response without these headers was not proven. Proof is best effort, so a request that can't be proven is still answered, just without the headers. Requests to the chat endpoints (Chat Completions, Responses, Anthropic Messages and Gemini) can be proven; embeddings, images, audio and the other endpoints answer without a receipt, and so do some models. A stream that ends early has no receipt.

`GET /v1/generation?id=<X-Request-ID>` returns the same values for any proven request, plus when VeriRelay deletes each part:

```json
"verirelay": {
  "request_id": "36a420474e713c4ecbe0a6d5dfd79ed0",
  "store_id": "cFMrwmc4IeTQT14_R9y6gg",
  "store_key": "<secret>",
  "relay": "https://relay.verirelay.com",
  "receipt_expires_at": "2026-11-11T08:45:48Z",
  "store_expires_at": "2026-11-12T07:45:48Z"
}
```

## Check a receipt [#check-a-receipt]

On the [Usage](https://www.ohmygpt.com/usage) page, open a request marked **Verifiable** and choose **Verify on VeriRelay**. To build the link yourself, put the values after `#`:

```text
https://verirelay.com/verify#relay=https%3A%2F%2Frelay.verirelay.com&request_id=<X-VeriRelay-Request-Id>&store_id=<X-VeriRelay-Store-Id>&store_key=<X-VeriRelay-Store-Key>
```

Browsers never send the part after `#` to a server, so the Store-Key stays on your machine. The page checks the signature and the attestation, then decrypts the stored bodies and compares them with the hashes. Leave out `store_id` and `store_key` to check the receipt alone.

To check in code, fetch the receipt. No key is needed:

```bash
curl https://relay.verirelay.com/v1/avr/receipts/36a420474e713c4ecbe0a6d5dfd79ed0
```

```json
{
  "version": "avr/1",
  "canonicalization": "jcs-rfc8785",
  "signature_algorithm": "ed25519",
  "hash_algorithm": "sha256",
  "request_id": "36a420474e713c4ecbe0a6d5dfd79ed0",
  "timestamp": "2026-11-11T07:45:48.036395467Z",
  "method": "POST",
  "upstream_authority": "api.deepseek.com",
  "upstream_path": "/v1/chat/completions",
  "request_body_sha256": "…",
  "response_body_sha256": "…",
  "response_status": 200,
  "upstream_tls": { "sni": "api.deepseek.com", "spki_sha256": "…" },
  "service_public_key": "…",
  "key_id": "5262ba4e3931cd2a",
  "signature": { "payload_sha256": "…", "value": "…" }
}
```

`upstream_authority` is the host that answered, and `upstream_tls.spki_sha256` fingerprints the certificate it presented. `GET /v1/avr/evidence/<request_id>` returns the receipt together with the SEV-SNP attestation that binds the signing key to the confidential VM. The formats are specified in [avr1.md](https://github.com/verirelay/protocol/blob/main/docs/avr1.md).

## Keep a proof [#keep-a-proof]

VeriRelay keeps the signed receipt for **1 hour** and the stored bodies for **24 hours**, then deletes them. To keep a proof longer, save the evidence bundle within the hour. It carries its own signature and attestation, so it can still be checked after VeriRelay's copy is gone.

## What the receipt covers [#what-the-receipt-covers]

The receipt covers the exchange with the provider. What you receive matches it byte for byte, except for these changes:

| Change | Where you see it |
|---|---|
| Protocol conversion, when you call a model on a protocol its provider doesn't speak | The stored request is in the provider's protocol |
| The model name: the provider receives its own ID for the model | `model` in the stored request |
| The charge | `X-Cost-Credits`, and the `: x-cost-credits` line in streams |
| Responses IDs, when the response is stored | `resp_*` IDs issued by OhMyGPT |
| The output limit, when your balance can't cover the one you asked for | `X-Output-Tokens-Capped` gives the new limit, which matches the stored request ([details](/docs/costs#when-your-balance-runs-low)) |

The stored bodies are the bytes the provider sent, so they may be gzip-compressed, and the hashes cover the compressed bytes. Decompress them before comparing with what you received.
