Encrypted inference
Create encrypted chat completion
Relay an encrypted chat request for a resolved encrypted model and offer.
https://api.numes.ai/api/v1/e2ee/chat/completionsThe body is ciphertext produced on your device, so send it through an encryption SDK such as the Tinfoil SDK, or use the dashboard chat or the CLI. Authenticate with your inference key, resolve the model first, and set these headers from that fresh resolution:
| Header | Value |
|---|---|
X-Inference-Model | The public :e2ee model ID |
X-Inference-Offer-Id, X-Inference-Offer-Revision-Id | The resolved offer |
X-Inference-Native-Model | The resolved native model ID |
X-Inference-Profile | The resolved transport |
The SDK adds the encryption headers its profile requires. The response stays encrypted until the SDK decrypts it; for EHBP profiles, preserve the Ehbp-Response-Nonce header. X-Generation-Id identifies the request in GET /generation.
Treat an interrupted body as a failure, even if the decrypted output looked complete. Don't retry automatically, and never fall back to a regular model: once encrypted output starts, the request is billed on the provider's final usage, even if you disconnect. See Billing and limits.
Regular POST /chat/completions rejects :e2ee model IDs.
A 503 response with error.metadata.error_type: "inference_not_dispatched" confirms that the pinned request was rejected before execution. You may resolve and encrypt one fresh attempt with a new idempotency key and the same encryption policy. The dashboard and CLI handle this automatically. Do not apply this recovery to other errors or interrupted response bodies.
Authorization
AuthorizationheaderRequired
Bearer inference key. Charges settle in the key's billing currency. Authorization: Bearer $NUMES_API_KEY
Headers
X-Request-IdstringCorrelation ID, not an idempotency key. Inference request IDs recorded with a generation are unique per account. A traffic-admitted request reusing a recorded ID returns 400 invalid_request. Traffic admission rejection takes precedence over this conflict, including for reused IDs; it performs no generation lookup and writes no generation, result or attempt. Rate-limit rejection returns 429 rate_limited with Retry-After; an inference limiter outage retains 500 server.
Length1–128
Request body
application/octet-streamapplication/jsonThe contract declares a 10 MiB body limit. The size the service enforces is listed in Limits.
application/octet-stream
application/json
Responses
200Encrypted response bytes; incomplete streams terminate with a transport error.application/octet-streamapplication/jsontext/event-stream
Headers
application/octet-stream
application/json — Native JSON with encrypted content fields.
text/event-stream — Native SSE with encrypted content fields.
503No eligible provider can serve the request. Unknown, unpublished, currency-mismatched and unauthorized shared model IDs receive the same bounded response (`error.code` 503, `error.metadata.error_type` "provider_unavailable", message "no provider is available"). Inference and encrypted resolution do not classify model existence after routing fails. Earlier validation and authorization errors remain unchanged. An interrupted server execution while the original HTTP caller remains connected also uses 503 provider_unavailable with the fixed message "service temporarily unavailable". Once streaming has started, the error is in-band and the HTTP status remains 200. If an otherwise eligible USD-indexed Bitcoin offer is blocked by an unavailable market reference, or its reference expires before dispatch, the response instead uses 503 with error_type "bitcoin_reference_price_unavailable" and message "Bitcoin pricing is unavailable. Try again shortly."application/json
ErrorCompatible error envelopeapplication/json
Headers