Guides
Error Codes
All errors return a consistent JSON body with a machine-readable error code and a human-readable message.
Error Response Format
error response
{
"detail": {
"error": "quota_exceeded",
"message": "Monthly extraction quota reached. Upgrade your plan to continue.",
"retry_after": null
}
}Note:Always check the
error field rather than parsing message — messages may change, error codes are stable.Authentication Errors
| HTTP | Code | Description | Fix |
|---|---|---|---|
401 | invalid_api_key | API key is missing, malformed, or revoked | Check key starts with af_ and is not expired |
401 | invalid_credentials | Email not found during login | Sign up first or check for typos |
403 | forbidden | API key does not have permission for this resource | Check your plan tier |
Request Errors
| HTTP | Code | Description | Fix |
|---|---|---|---|
400 | bad_request | Malformed JSON or invalid multipart form | Check your request body format |
422 | invalid_file | File type not supported or exceeds 10 MB | Use PDF, PNG, JPG, WEBP, TIFF, BMP, HEIC, HEIF — max 10 MB |
422 | validation_error | Missing required fields or invalid parameters | Check required parameters |
500 | extraction_failed | Document could not be parsed — too blurry or corrupted | Use a higher quality scan |
Quota & Rate Limit Errors
| HTTP | Code | Description | Fix |
|---|---|---|---|
429 | quota_exceeded | Monthly extraction quota reached | Upgrade plan or wait for monthly reset |
429 | rate_limit_exceeded | Too many requests in the time window | Respect Retry-After header |
Handling Errors in Code
error_handling.py
import requests
def extract_document(file_path, api_key):
try:
with open(file_path, "rb") as f:
resp = requests.post(
"https://api.documentflowai.com/v1/extract",
headers={"Authorization": f"Bearer {api_key}"},
files={"file": f},
timeout=30,
)
if resp.status_code == 200:
return resp.json()
error = resp.json().get("detail", {})
code = error.get("error", "unknown")
if resp.status_code == 401:
raise Exception(f"Auth failed: {code}")
elif resp.status_code == 402:
raise Exception("Quota exceeded — upgrade your plan")
elif resp.status_code == 429:
retry_after = resp.headers.get("Retry-After", 60)
raise Exception(f"Rate limited — retry after {retry_after}s")
elif resp.status_code == 422:
raise Exception(f"Extraction failed: {error.get('message')}")
else:
raise Exception(f"Unexpected error {resp.status_code}: {code}")
except requests.Timeout:
raise Exception("Request timed out — document may be too large")