Authentication
Authentication is identical across Speech, Interview, CV
DeepMatch, and CV DeepSearch. Every request carries your key in the
X-API-Key header:
X-API-Key: zh_abc123...
Getting a key
API keys are issued from the ZenHire dashboard. Admins of a client account can create, list, and revoke keys at any time.
The public API is request-only — you submit work, poll for results, and list past runs. Creating keys and organizing them into Projects both happen in the dashboard, not through any API endpoint. Each run automatically inherits the Project of the API key that submitted it, so there is no project field to send on a request. (You can still filter list endpoints by project — see each module's list endpoint.)
Key format & rate limits
All keys use the zh_api_… format. The rate limit is configured per key
(default 500 req/min) and can be adjusted from the dashboard.
Keys issued before this format was introduced (zh_speech_live_…,
zh_speech_test_…, zh_cv_live_…, zh_…) continue to work without
any changes needed.
Keys draw on the same credit balance.
Per-module permissions
A key's client account must have the relevant module permission
enabled. A call to a module the account isn't entitled to returns
403 MISSING_PERMISSION:
| Module | Permission |
|---|---|
| Speech | speech (non-English additionally requires multilingual access) |
| Interview | interview |
| CV DeepMatch | cvdeepmatch |
| CV DeepSearch | cvdeepsearch |
Contact your account manager to enable a module.
Storing keys securely
- Never commit keys to version control. Use environment variables or a secret manager.
- Never expose keys in client-side code (browser JavaScript, mobile apps). The API is server-to-server. To surface results in a browser, proxy through your own backend.
- Rotate keys you suspect have been exposed. Rotation is one click in the dashboard.
The one unauthenticated endpoint
GET /api/v1/health is the only endpoint that does
not require a key, so you can wire it into third-party uptime monitors
without storing a key there.
Auth errors
| Status | Code | Meaning |
|---|---|---|
401 | MISSING_API_KEY | No X-API-Key header. |
401 | INVALID_API_KEY | Missing, malformed, revoked, or inactive key. |
401 | API_KEY_EXPIRED | Key's expiry has passed. Rotate. |
401 | CLIENT_INACTIVE | The account behind the key is disabled. Contact support. |
403 | MISSING_PERMISSION | Key is valid but the module isn't enabled for the account. |
429 | RATE_LIMIT_EXCEEDED | Per-minute rate limit exceeded. Back off and retry. |
All auth errors use the standard error envelope.