Reference · Errors
Errors
Two distinct failure surfaces: HTTP errors on the request itself, and per-document errors that surface as a failed job. Both carry a stable code so your recovery logic can switch on it.
Error shape
HTTP errors are returned as a JSON body with a string detail:
{ "detail": "UNSUPPORTED_FILE_TYPE: application/zip" }The portion before the colon is the stable code. Treat the portion after the colon as a human-readable hint that may change.
Per-document failures surface on the job itself:
{
"status": "failed",
"error": {
"code": "PDF_PASSWORD_PROTECTED",
"message": "Source PDF requires a password we don't have."
}
}HTTP errors
| Status | Code | How to recover |
|---|---|---|
| 400 | UNSUPPORTED_FILE_TYPE | Send PDF / image / PPTX. Convert first if your source is something else. |
| 400 | FILE_TOO_LARGE | Max 100 MB. Split the document upstream. |
| 400 | EMPTY_FILE | 0 bytes uploaded. Re-read the file before sending. |
| 400 | INVALID_OPTIONS_JSON | options field is not valid JSON. |
| 400 | INVALID_OPTIONS | JSON parsed but failed schema validation. Detail names the offending field. |
| 400 | INVALID_SCOPES | You requested API key scopes outside the allow-list. |
| 401 | MISSING_API_KEY | No Authorization header. |
| 401 | INVALID_AUTH_FORMAT | Header was present but not Bearer <token>. |
| 401 | INVALID_API_KEY | Bearer doesn't match a live key, or the key was revoked. |
| 402 | INSUFFICIENT_BALANCE | Lifetime free pages used up AND wallet balance below the minimum reserve. Top up in Billing. |
| 403 | INSUFFICIENT_SCOPE | Key lacks the scope this endpoint needs. Create a new key with broader scopes. |
| 404 | JOB_NOT_FOUND | Wrong job ID, or it belongs to a different customer. Same response either way. |
| 404 | API_KEY_NOT_FOUND | Tried to revoke a key that doesn't exist or is already revoked. |
| 409 | JOB_ALREADY_COMPLETED / FAILED / CANCELLED | Job is terminal; can't cancel. |
| 429 | RATE_LIMITED | Back off per Retry-After. Use idempotency keys to make retries safe. |
| 500 | INTERNAL_ERROR | Our fault. Safe to retry. Mail support if it persists. |
Per-document errors
Returned on the job's error.codewhen the file uploaded fine but extraction couldn't complete.
| Code | Cause | How to recover |
|---|---|---|
PDF_PASSWORD_PROTECTED | Source PDF is encrypted. | Decrypt before upload. |
PDF_MALFORMED | Header/xref unreadable. | Re-export the PDF. |
PPTX_MALFORMED | PPTX archive is corrupt. | Re-save as .pptx from PowerPoint or Keynote. |
PPTX_CONVERSION_UNAVAILABLE | Office conversion step couldn't run for this deck (typically an exotic .ppt shape we can't open). | Re-save as a modern .pptx. |
OCR_LOW_CONFIDENCE | Page-level signal: scan was too noisy for reliable OCR. The text is still returned but blocks carry verified: false. | Rescan at higher DPI, or filter by verified downstream. |
MULTI_COLUMN_AMBIGUOUS | Page-level signal: column detection wasn't confident. Reading order may not match the visual layout. | Use bbox coordinates if visual order matters. |
EXTRACTION_TIMEOUT | Worker hit the per-job time budget. | Split very large documents, or retry — many timeouts are transient. |
SERVICE_TEMPORARILY_UNAVAILABLE | Upstream model or infra blip. | Retry with backoff. Same Idempotency-Key keeps billing safe. |
EXTRACTION_FAILED | Generic fallback when none of the above matched. | Retry once; if it persists, send us the file. |
INTERNAL_ERROR | Worker crashed mid-pipeline. | Safe to retry with the same Idempotency-Key — you won't be double-billed. |
Recovery strategy
A simple rule that covers 95% of cases:
4xx= your fault. Fix the request; don't retry the same request unchanged.429and500= retry with exponential backoff, capped at ~5 attempts.- Job-level
failedwith a*_PROTECTED/*_MALFORMEDcode = fix the file. Retrying won't help. SERVICE_TEMPORARILY_UNAVAILABLE,EXTRACTION_TIMEOUT,INTERNAL_ERROR,EXTRACTION_FAILED= retry with the sameIdempotency-Key.
Need a code we haven't documented? Open an issue or mail support — we'll either add it here or fix the bug that caused it.
