Documentation Index
Fetch the complete documentation index at: https://docs.doclo.ai/llms.txt
Use this file to discover all available pages before exploring further.
When an API request fails, the response includes an error object with a code and message.
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description of the error"
}
}
Some errors include additional details:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": {
"field": "input.document.base64",
"reason": "Invalid base64 encoding"
}
}
}
HTTP Status Codes
| Status | Meaning | Common Causes |
|---|
| 400 | Bad Request | Invalid JSON, missing required fields |
| 401 | Unauthorized | Missing or invalid API key |
| 402 | Payment Required | Insufficient credits |
| 403 | Forbidden | API key lacks required scope |
| 404 | Not Found | Flow or execution doesn’t exist |
| 409 | Conflict | Execution already cancelled |
| 422 | Unprocessable Entity | Valid JSON but invalid data |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
| 503 | Service Unavailable | Maintenance or overload |
Error Codes Reference
Authentication Errors
| Code | Status | Description |
|---|
UNAUTHORIZED | 401 | Missing or invalid authorization header |
INVALID_API_KEY | 401 | API key is malformed or revoked |
FORBIDDEN | 403 | API key missing required scope |
Example:
{
"error": {
"code": "FORBIDDEN",
"message": "API key missing required scope: flows:execute"
}
}
Fix: Generate a new API key with the required scopes in the Dashboard.
Validation Errors
| Code | Status | Description |
|---|
INVALID_INPUT | 400 | Request body is invalid JSON |
VALIDATION_ERROR | 422 | Request data fails validation |
MISSING_REQUIRED_FIELD | 422 | Required field not provided |
INVALID_DOCUMENT | 422 | Document data is corrupted or unsupported |
Example:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid document format",
"details": {
"field": "input.document.mimeType",
"reason": "Unsupported format: image/svg+xml",
"supported": ["application/pdf", "image/png", "image/jpeg", "image/webp"]
}
}
}
Fix: Check the request body matches the expected schema. Ensure documents are in supported formats.
Resource Errors
| Code | Status | Description |
|---|
FLOW_NOT_FOUND | 404 | Flow ID doesn’t exist or isn’t accessible |
EXECUTION_NOT_FOUND | 404 | Execution ID doesn’t exist |
VERSION_NOT_FOUND | 404 | Requested flow version doesn’t exist |
Example:
{
"error": {
"code": "FLOW_NOT_FOUND",
"message": "Flow 'invoice-extractor' not found"
}
}
Fix: Verify the flow ID is correct. Use GET /flows to list available flows.
Billing Errors
| Code | Status | Description |
|---|
INSUFFICIENT_CREDITS | 402 | Not enough credits for this operation |
SUBSCRIPTION_REQUIRED | 402 | Feature requires paid subscription |
Example:
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits. Required: 10, Available: 3"
}
}
Fix: Purchase more credits or upgrade your plan in the Dashboard.
Execution Errors
| Code | Status | Description |
|---|
EXECUTION_FAILED | 500 | Flow execution failed |
EXECUTION_TIMEOUT | 504 | Execution exceeded time limit |
ALREADY_CANCELLED | 409 | Execution was already cancelled |
NOT_CANCELLABLE | 409 | Execution already completed or failed |
Example:
{
"error": {
"code": "ALREADY_CANCELLED",
"message": "Execution exec_abc123 was already cancelled"
}
}
Rate Limit Errors
| Code | Status | Description |
|---|
RATE_LIMITED | 429 | Too many requests |
CONCURRENT_LIMIT | 429 | Too many concurrent executions |
Example:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 30 seconds"
}
}
Fix: Implement exponential backoff. Check X-RateLimit-Reset header for when to retry.
Server Errors
| Code | Status | Description |
|---|
INTERNAL_ERROR | 500 | Unexpected server error |
SERVICE_UNAVAILABLE | 503 | Service temporarily unavailable |
PROVIDER_ERROR | 502 | Upstream provider (LLM/OCR) error |
Example:
{
"error": {
"code": "PROVIDER_ERROR",
"message": "OCR provider temporarily unavailable"
}
}
Fix: Retry with exponential backoff. If persistent, check the status page.
Error Handling Best Practices
Retry Logic
Implement retries with exponential backoff for transient errors:
async function callAPI(request: Request, maxRetries = 3): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(request);
if (response.ok) {
return response;
}
const { error } = await response.json();
// Don't retry client errors (except rate limits)
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
throw new Error(error.message);
}
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
throw new Error('Max retries exceeded');
}
Idempotency
Use idempotency keys to safely retry failed requests:
const response = await fetch('https://app.doclo.ai/api/v1/flows/invoice/run', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
idempotencyKey: `invoice-${documentId}-${Date.now()}`,
input: { document: { base64: documentData } }
})
});
Error Logging
Log errors with context for debugging:
try {
const result = await runFlow(flowId, input);
} catch (error) {
console.error('Flow execution failed', {
flowId,
errorCode: error.code,
errorMessage: error.message,
requestId: error.requestId,
timestamp: new Date().toISOString()
});
}
Next Steps
Run Flow
Execute flows with proper error handling
SDK Client
Use the SDK for automatic retries