Authentication
The zr_ key format, interchangeable authentication headers, and how to keep keys safe.
Authentication on the inference API is a single API key. There are no separate client secrets, OAuth flows, or signed requests — everything from a simple curl call to a production SDK client authenticates the same way.
API key format#
Every key follows the format zr_<public-id>_<secret>. The public-id identifies the key in your workspace (for example, when you list or revoke keys), while the secret is the sensitive portion you send with each request.
Authentication headers#
Send your key in either of two interchangeable headers:
Authorization: Bearer zr_<public-id>_<secret>x-api-key: zr_<public-id>_<secret>
Key security best practices#
A key grants full spending authority over your account, so treat it as a root credential:
| Practice | Why it matters |
|---|---|
| Never commit keys to source control or public issues | A leaked key lets anyone spend your balance. Treat it like a password. |
| Store keys in a secret manager | Keys are reveal-once, so keep the secret where CI and runtime can read it — environment variables, AWS Secrets Manager, or a password manager. |
| Use one key per environment or project | Isolation makes revoking a single compromised key painless without affecting the rest. |
| Rotate by revoking and creating a new key | There is no in-place secret edit. Revocation plus a fresh key is the supported rotation path. |
| Revoke immediately on suspicion of a leak | Revocation is instant and invalidates the key everywhere it was used. |
How keys are stored#
zrouter stores only a SHA-256 hash of your key. The plaintext secret is never persisted after you create it, which means zrouter staff cannot read your key. This is also why the reveal-once model is strict: if the secret is lost, the only recovery is to create a new key.
Keys can optionally be created with an expiry. Once expired, a key stops authenticating and must be replaced.
If your account is blocked, requests are denied with the same 401 invalid_api_key as a wrong or missing key. The response is intentionally indistinguishable so it does not disclose account state.
Choosing the right credential#
zrouter uses three separate authentication worlds. They are never interchangeable:
| Context | Credential | Used for |
|---|---|---|
| Inference API | zr_ key (Bearer or x-api-key) | Calling /v1/chat/completions, /v1/responses, and /v1/messages. |
| Reseller API | Reseller JWT (Bearer) | Calling /api/reseller/* in the reseller program. |
| Dashboard / workspace | Browser session cookie | Managing keys, checkout, and receipts in the web app; the five read-only endpoints also accept a zr_ key. |