Skip to content

Route sensitive prompts through private mode

Some prompts carry data that no third party may see in plaintext. private is the routing constraint for those: the request is served only by a TeeML provider, where the model itself runs inside the enclave and the prompt is decrypted nowhere else. If no such provider is available, the request fails rather than being served by something weaker.

This page shows the header, the model choice it forces, and the failure you must handle correctly.

Add X-0G-Provider-Trust-Mode: private to an otherwise ordinary chat completion. Header names are case-insensitive; the value must be exactly standard, verified, or private.

Terminal window
curl https://router-api.0g.ai/v1/chat/completions \
--max-time 120 \
--fail-with-body \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ZG_API_KEY" \
-H "X-0G-Provider-Trust-Mode: private" \
-d '{
"model": "glm-5.2",
"messages": [{"role": "user", "content": "Summarize this contract clause: <YOUR_TEXT>"}]
}'

The header is one of eight routing headers; the rest are documented in Headers.

private routes to TeeML providers only. A model with no TeeML provider can never satisfy the request, and the Router will not substitute a weaker one — you get a 503 on every attempt, no matter how long you wait.

Two models in the catalog serve private for chat: glm-5.2 and 0gm-1.0-35b-a3b. Models reporting TeeTLS — such as glm-5 or deepseek-v4-pro — can serve verified but not private. Models with no TEE backing at all — the claude-* and gpt-5.6-* families — serve neither.

The catalog is the live source of truth, public and unauthenticated. Check it rather than a list in a document:

Terminal window
curl -s https://router-api.0g.ai/v1/models \
| jq '.data[] | select(.verifiability == "TeeML") | .name'

Why the tiers split this way, and what TeeML proves that TeeTLS does not, is covered in Trust modes.

The response shape is unchanged; the x_0g_trace block names the provider that served it.

{
"id": "chatcmpl-0852f405-6c56-40c2-a800-e6fd70785065",
"object": "chat.completion",
"model": "glm-5.2",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "The clause obliges..." },
"finish_reason": "stop"
}
],
"x_0g_trace": {
"request_id": "9c58b3d7-1f42-4e69-b8a0-5d2c7e94f16b",
"provider": "0xd9966e13a6026Fcca4b13E7ff95c94DE268C471C",
"billing": { "input_cost": "85600000000000", "output_cost": "285760000000000", "total_cost": "371360000000000" }
}
}

When no TeeML provider is free, the request fails instead:

{
"error": {
"message": "failed to select provider: no provider available for the requested trust mode: tier=private",
"type": "server_error",
"code": "no_provider_for_trust_mode"
},
"request_id": "4a17e6c5-3b98-4f02-9d7e-8c1a5b6f2049"
}

Live response, 2026-07-20.

This is a supply condition, not a permissions problem or a malformed request. Two correct responses:

  1. Retry with backoff, if the workload tolerates delay and you expect supply to return.
  2. Switch to another TeeML model for that request, if the work can be done by a different model.

An invalid value returns 400 invalid_trust_mode instead. That is a bug in your code, and retrying it unchanged will never succeed.

A trust mode can also be attached to the API key. In the Console, open Dashboard → API Keys and set the key’s trust mode. Programmatically, create the key with trust_mode, which requires an mk- management key with the appropriate scope:

Terminal window
curl https://router-api.0g.ai/v1/api-keys \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ZG_MANAGEMENT_KEY" \
-d '{"name":"sealed-prod","trust_mode":"private"}'

A per-key trust mode is enforced on every request made with that key, whatever the calling code sends. The header cannot weaken it. That is the point: hand a service a key that is structurally incapable of routing outside the enclave and the guarantee survives a bug in that service.

Use the header when one service handles mixed workloads under your control. Use the key when the guarantee is a property of the deployment.

What private mode guarantees, and how to check it

Section titled “What private mode guarantees, and how to check it”

Under private, the prompt enters the enclave as ciphertext, is decrypted only inside it, and the response is signed inside it. Neither 0G nor the operator of the hardware sees the plaintext. Inference content is not retained after the request completes.

That is a claim you do not have to take on faith. Each response carries a TEE signature you can check yourself, against the chain and the provider rather than against the Router. See Verify a response.

Status code Cause Fix
400 invalid_trust_mode Value is not standard, verified, or private Fix the value; do not retry unchanged
400 invalid_provider_header Another X-0G-Provider-* header has an illegal value See Headers
401 invalid_api_key Bad, revoked, or mk- key on an inference call Use a live sk- key
402 insufficient_balance Deposit exhausted Top up, then retry
429 rate_limit_exceeded Too many requests Wait for Retry-After seconds
503 no_provider_for_trust_mode No TeeML provider serving this model right now Back off, or switch to another TeeML model

Full list with retry guidance: Error codes.

  • Verify a response — prove the response really came from the enclave
  • Trust modes — what standard, verified, and private each buy you
  • Headers — the full X-0G-Provider-* reference