> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trynito.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Encrypted

> Encrypted requests on the API: the model ID, the headers, what is encrypted, and what is rejected.

Encrypted is end-to-end encrypted inference: encryption on your device on top of everything Confidential gives. The concepts are in [Encrypted Inference](/privacy/encrypted) and the wire protocol a client implements is on [Protocol](/privacy/encrypted/protocol). Your client encrypts each message with the model's public key from a fresh attestation, the gateway relays the ciphertext without decrypting it, and your client decrypts the reply. Supported on `POST /v1/chat/completions`.

## The Model

Choose an `:encrypted` ID from `GET /v1/models?privacy_tier=encrypted`. The [Model List](/models/all-models) also marks available variants. Fetch current evidence and the model public key from the [attestation endpoint](/api/api-reference/attestation/get-attestation) before sending a request.

## The Flow

<Steps>
  <Step title="Fetch and verify the attestation">
    Call [`GET /api/v1/attestation`](/api/api-reference/attestation/get-attestation) with the `:encrypted` model and `trust_tier=encrypted`. The response carries the `model_public_key`, `signing_algo`, and `proof_format`. Nito checks the key is present and the right shape for the algorithm and hands it to you with the evidence. Confirming the key belongs to the attested workload is part of verifying the evidence, so verify before encrypting with the key. See [Verify It Yourself](/privacy/tee-attestation/verify-yourself-recipe).
  </Step>

  <Step title="Encrypt the messages">
    Generate a key pair for the conversation and encrypt every `messages[].content` string locally with a fresh ephemeral key, following the protocol variant the attestation's `proof_format` identifies (see [Protocol](/privacy/encrypted/protocol)). Content must be a nonblank ciphertext string. Content arrays are rejected.
  </Step>

  <Step title="Send the request with the Encrypted headers">
    Send the chat request with the headers below. The gateway checks the ciphertext shape, route eligibility, and request bounds, forwards the request, and returns the encrypted reply.
  </Step>
</Steps>

## Headers

| Header | Required | Value |
| :- | :- | :- |
| `nito-encrypted` | Yes | `1`. Every other Encrypted header is rejected without it. |
| `nito-encrypted-client-pub-key` | Yes | Your public key as hex: 32 bytes for ed25519, 65 bytes uncompressed for ecdsa. Shape is validated and the key is never stored. |
| `nito-encrypted-model-pub-key` | Yes | The `model_public_key` from the attestation, as hex. |
| `nito-encrypted-signing-algo` | Yes | `ed25519` or `ecdsa`, matching the attestation's `signing_algo`. |
| `nito-encrypted-encryption-version` | Protocol version 2 | `2`. Omit it when the attestation's `proof_format` identifies the legacy protocol. |
| `nito-encrypted-nonce` | Some backends | A fresh request-bound nonce, where the backend's version 2 protocol requires one. |
| `nito-encrypted-timestamp` | Some backends | A positive Unix timestamp, where the backend's version 2 protocol requires one. |
| `nito-encrypted-encrypt-all-fields` | For function tools | `1`. Turns on encrypted tool definitions and results on backends that support them. |
| `nito-encrypted-response-evidence` | Optional | `1` on supported backends with `stream: false`. Returns original body bytes and signature evidence for client verification. |

Sending `:encrypted` without the headers, or the headers with a model that is not `:encrypted`, returns `400 invalid_request`.

## What Works

* **Streaming.** `stream: true` returns the provider's encrypted deltas as a passthrough for your client to reassemble and decrypt.
* **Reasoning.** Accepted when the route advertises visible reasoning support.
  Encrypted responses can carry visible thinking when a model emits it, even if
  that model does not advertise a reasoning request control. The model list
  separates output support from API-reported controls; only send reasoning
  controls when the route advertises them.
* **Function tools**, with `nito-encrypted-encrypt-all-fields: 1`. Function names, descriptions, JSON-schema parameters, `tool_choice` names, assistant tool-call names and arguments, and tool-result content are all sent as ciphertext hex. Your client decrypts the returned tool call, runs the tool, encrypts the result, and sends the follow-up request.

## Response Verification

For nonstreaming calls, request [Response Evidence](/api/api-reference/chat-and-text/response-evidence) to receive the original upstream body bytes and signature proof. Nito returns `verified: false`; your client checks the signed exchange against independently verified attestation.

## Rejected

* Hosted `web_search` and `web_fetch` on the Encrypted request, because plaintext evidence cannot be added to an encrypted envelope.
* Response evidence with `stream: true`.
* Content arrays and raw image, file, or document attachment parts.
* `/v1/responses`, `/v1/messages`, `/v1/messages/count_tokens`, and MCP: Encrypted runs on Chat Completions only.
* `uncensored=true` with an `:encrypted` model.

## Retention and Billing

The gateway never decrypts, logs, or persists the ciphertext. Usage is estimated from the envelope shape before the call and settled from the provider's reported usage after it.

## Related

* [Encrypted Inference](/privacy/encrypted)
* [Protocol](/privacy/encrypted/protocol)
* [Get attestation](/api/api-reference/attestation/get-attestation)
* [Encrypted in the Browser App](/web-app/privacy-in-the-app)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.