Errors
Error format, status codes and the codes you should handle.
Every failed request returns a JSON body with one error object:
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "email must be an email",
"param": "candidate.email",
"request_id": "req_…"
}
}Branch on code, not on message. Messages are written for people and may change. param names the offending field when there is one.
Types
type | Status | Meaning |
|---|---|---|
invalid_request_error | 400, 404, 409, 413, 422 | Something about the request is wrong. Fix it before retrying. |
authentication_error | 401 | The key is missing, malformed or revoked. |
permission_error | 403 | The key lacks a scope, or your organisation is out of credits. |
idempotency_error | 409 | An idempotency key clash. |
rate_limit_error | 429 | Too many requests. Wait Retry-After seconds. |
api_error | 500 | Our fault. Safe to retry with the same idempotency key. |
Codes
| Status | code | What to do |
|---|---|---|
| 400 | parameter_invalid | Fix the field named in param. |
| 400 | invalid_request | Read the message; the request is not valid in this state (for example, extending a completed invitation). |
| 400 | export_too_large | Narrow the export's filters below 50,000 rows. |
| 401 | invalid_api_key | Check the key and its prefix. |
| 403 | missing_scope | Add the scope to the key, or use another key. |
| 403 | credits_exhausted | Live mode only. Buy or request more credits. |
| 404 | resource_missing | The id does not exist in this mode. |
| 404 | recording_not_available | The session has no recording yet, or never will. |
| 404 | error_file_not_available | The import had no skipped rows. |
| 409 | candidate_has_sessions | A candidate who was ever invited cannot be deleted. |
| 409 | candidate_exists_in_other_mode | The email already belongs to a candidate in the other mode. |
| 409 | import_already_committed | The import has already started. |
| 409 | conflict | The request clashes with the current state. |
| 409 | idempotency_key_in_use | The first request with this key is still running. Retry shortly. |
| 409 | idempotency_key_reused | The key was used for a different request. Use a new key. |
| 413 | file_too_large | Files are capped at 10 MB. |
| 422 | unprocessable | The file could not be read. |
| 429 | rate_limited | Back off. |
| 500 | internal_error | Retry with backoff. If it persists, contact support with the request_id. |
Retrying safely
Retry 429, 500 and network errors with exponential backoff, and send the same Idempotency-Key on every attempt so a POST never runs twice. Do not retry other 4xx errors unchanged. The TypeScript SDK does all of this for you.