Appearance
Error Handling
Standard HTTP status codes are used to indicate success or failure.
Status Codes
| Code | Meaning | When |
|---|---|---|
200 | Success | Text anonymization completed |
202 | Accepted | File upload accepted for processing |
400 | Bad Request | Missing or invalid parameters |
401 | Unauthorized | Invalid or missing bearer token |
403 | Forbidden | Evaluation request limit (1,000) reached |
404 | Not Found | Job ID does not exist or expired |
422 | Unprocessable Entity | Request body validation failure |
429 | Too Many Requests | Evaluation rate limit (30/min) exceeded |
500 | Internal Server Error | Unhandled server error |
All error responses return JSON with a detail field.
Specific Errors
400 — Bad Request
json
{"detail": "text field is required"}json
{"detail": "Unsupported file type. Supported types: pdf, docx, csv, excel"}json
{"detail": "Uploaded file is empty"}401 — Unauthorized
json
{"detail": "Bearer token missing"}json
{"detail": "Invalid bearer token"}Occurs when:
- No
Authorization: Bearer <token>header is provided - The token's signature is invalid, or the token has expired
- An evaluation token has been revoked
403 — Evaluation Limit Reached
json
{"detail": "Evaluation request limit reached (1000). Contact techsupport@questa.solutions for a license."}Returned when an evaluation token has used its 1,000 lifetime requests. The token will no longer process anonymization requests — contact techsupport@questa.solutions for a self-hosted license. Only the hosted demo's evaluation tokens are capped; self-hosted instances have no request limit.
404 — Not Found
json
{"detail": "Job not found"}Occurs when:
- The
job_iddoes not exist - The job has expired (results retained for 1 hour)
422 — Validation Error
json
{
"detail": [
{
"loc": ["body", "text"],
"msg": "field required",
"type": "value_error.missing"
}
]
}429 — Rate Limit
Evaluation tokens are limited to 30 requests per minute. Exceeding that returns 429 with a Retry-After header indicating how many seconds to wait:
json
{"detail": "Rate limit exceeded. Try again in 42 seconds."}Back off and retry after Retry-After seconds. Only /anonymize/text and the file-upload endpoints count toward the rate limit. Self-hosted instances do not rate-limit.
500 — Internal Server Error
json
{"detail": "Internal server error"}For file processing, errors during background processing are captured in the job's error field:
json
{
"status": "failed",
"progress": 50,
"error": "Failed to extract text from PDF: file appears to be scanned/image-based",
"created_at": 1678886400.0
}Error Handling (Python)
python
import time
def anonymize_with_retry(client, payload, max_retries=3):
for attempt in range(max_retries):
try:
response = client.post("/anonymize/text", json=payload)
if response.status_code == 200:
return response.json()
if response.status_code == 401:
raise PermissionError("Bearer token is missing or invalid")
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 5))
time.sleep(retry_after)
continue
if response.status_code >= 500:
time.sleep(2 ** attempt)
continue
response.raise_for_status()
except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)Error Handling (JavaScript)
javascript
async function anonymizeWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.ok) return response.json();
if (response.status === 401) {
throw new Error("Bearer token is missing or invalid");
}
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "5");
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
if (response.status >= 500 && attempt < maxRetries - 1) {
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
continue;
}
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
}