Errors
Errors are JSON (except the edge's own 413 and 404 pages) and carry the HTTP status that matters. Nothing fails silently: a rejected request tells you why. Responses from the synchronous operations carry an X-Curriculo-Request-Id header (requests rejected before they reach an operation, background-task calls and screening calls do not); quote it when you contact us.
Error formats
The shape tells you where the request stopped, not which operation you called. Both can come from most endpoints.
| Shape | Returned when | Statuses |
|---|---|---|
{"success": false, "error": "...", "message": "..."} | The gateway rejects the request before any processing: missing, invalid or expired key, no credit, suspended or unprovisioned account, rate limit, an unknown path. Every error from /screening-interview and from the task endpoints (/{op}/async, /{op}/tasks/{task_id}) also uses this shape. | 400, 401, 403, 404, 413, 429 |
{"detail": "..."} | The request reached processing and the operation itself refused or failed it: an unreadable document, a validation error, an unknown job_id, a timeout. "Upstream unavailable" with 503 also uses this shape. | 400, 404, 413, 422, 500, 503, 504 |
Check for detail first, then message, so one handler covers both:
body = resp.json()
reason = body.get("detail") or body.get("message") or body.get("error")For validation errors (422), detail is usually a list of objects, each naming the field in loc and the problem in msg.
In a list request, a failed item carries its own error inside results, and the HTTP status of the request stays 200. See Batching.
HTTP status codes
| Status | Meaning | What to do |
|---|---|---|
400 | The input is unusable: empty file, blank text, unreadable or password-protected document, blank job_details, a duplicate JSON key. For a recording task, not enough credit to reserve the 2-hour maximum. | Fix the payload, or add credit. Retrying identical bytes will fail identically. |
401 | "Missing API token…", "Invalid API token." (unknown or revoked key), "API token expired.", or "Unknown API endpoint" for a path under /public/ that does not exist. | Check the Authorization header, the key, and the path. |
403 | The key is valid but the account cannot serve traffic: no prepaid credit ("…Buy credits in the Console."), the account is suspended, or "Account provisioning incomplete". | Add credit in Console → Billing, or wait for provisioning to finish. If the account is suspended, contact us. |
404 | Unknown job_id, or one registered by a different account. Also an unknown task id, or a path outside /public/. | Register the job again; ids are scoped to the account that created them. Check the base URL. |
413 | Over a size ceiling on a synchronous call: request body, document, recording, batch length, or character count. | Split the workload, or send recordings by link. See request size limits. |
422 | Schema validation failed: a required field of /jobs/, /summary/, /translate/ or /prompt/ is missing or misnamed (a missing file on /parse/, /evaluate/ or /transcribe/ is a 400). Also a translation language outside the 202 supported languages. | Compare against the API reference. Field names are case-sensitive. See Languages. |
429 | Rate limit exceeded, or another request is still running on a balance under $1. | Back off and retry. Honour Retry-After when present. |
500 | Our failure. | Retry once. If it persists, contact us with the X-Curriculo-Request-Id. |
503 | A dependency is unavailable, the service is busy, or a feature is not enabled here (for example media transcription). | Retry with backoff. |
504 | Processing exceeded the 300-second ceiling. | Send fewer items or a smaller document, or use the async lane. |
Failed requests are never charged. A
4xxor5xxcosts you nothing, and neither does a failed background task.
Retry guidance
- Do not retry
400,401,403,404,413or422unchanged. Fix the request first. - Retry with backoff on
429and503. - Retry once on
500. - On
504, resend with fewer items or a smaller document. In a list request, resubmit only the items that returned a504entry. - Re-sending a single failed document is always safe. It cannot create duplicates or half-finished records.
Contact
Still stuck? Use the contact page or write to hello@curriculo.me with the time, the operation and the X-Curriculo-Request-Id.
Next steps
- Rate limits: ceilings and
Retry-After. - Batching: per-item errors inside a list.
Updated