Contact

Errors

The /v1 API returns standard HTTP status codes. Error responses are plain text describing the failure — not a structured JSON envelope today. Programmatic clients should branch on the status code, then surface the body text to the caller.

Status codes

StatusMeaningTypical causes
200Success
201CreatedReturned by POST /v1/corpora, POST /v1/voices
202Accepted (async)Returned by background-job launchers like POST /v1/ingest and POST /v1/corpora/{id}/commit when the work is queued for async execution
400Bad requestMalformed JSON, validation failures, unsupported combinations of fields. The body explains which field failed
401UnauthorizedX-API-Key header missing, malformed, revoked, or unknown
403ForbiddenKey is valid but not permitted for this resource (cross-environment access, missing role)
404Not foundResource does not exist, or exists in a different environment than the calling key
410GoneEndpoint has been retired (see for example the retired SSE ingest path; the body explains where to go instead)
413Payload too largeIngest payload exceeds the per-request size limit; split into smaller requests
429Too many requestsRate limit exceeded. See Rate limits for the ceiling on each dimension (RPM + TPM + burst) and how to read the governor state
500Internal errorUnexpected server-side failure. Retry idempotent operations; report non-idempotent failures

Retrying

  • 400, 401, 403, 404, 410, 413 — do not retry. The request will fail the same way every time. Fix the request and resend.
  • 429 — retry after the window indicated by the Retry-After header, or poll the rate-limits endpoint to see when capacity returns.
  • 500 — safe to retry for idempotent operations (search, list, fingerprint-dedup ingest). Exponential backoff recommended: 1s, 2s, 4s, up to a short cap.

Body shape

Error bodies are plain-text strings, not JSON. Example:

$ curl -i -H "X-API-Key: bad-key" https://api.enscrive.io/v1/corpora
HTTP/1.1 401 Unauthorized

invalid api key

Structured JSON error envelopes are on the roadmap but are not yet live. Program against the status code; treat the body as human-readable diagnostic context.

Async job errors

Endpoints that launch background jobs (POST /v1/ingest, POST /v1/corpora/{id}/commit, POST /v1/evals/run-campaign, …) return a 202 Accepted with a job_id. The job itself can still fail later. Poll the job via GET /v1/jobs/{id} and branch on its terminal status:

StatusMeaning
pendingQueued, not yet running
runningIn progress
succeededCompleted successfully
failedTerminal failure; inspect error_message and, for batch work, failed_document_ids
cancelledCancelled by operator
abandonedExplicitly abandoned after running, typically due to upstream provider issues (see Jobs)

See Jobs for the full state machine and retry/abandon semantics.