> ## Documentation Index
> Fetch the complete documentation index at: https://docs.docintell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Handle API errors gracefully

All DocIntell API errors follow RFC 7807 (Problem Details) format for consistent handling.

## Error Response Format

```json theme={null}
{
  "error": "machine_readable_code",
  "message": "Human-readable description",
  "details": {}
}
```

## HTTP Status Codes

| Code  | Description       | When Used                          |
| ----- | ----------------- | ---------------------------------- |
| `400` | Bad Request       | Invalid input                      |
| `401` | Unauthorized      | Missing/invalid API key            |
| `403` | Forbidden         | Valid auth, but action not allowed |
| `404` | Not Found         | Resource doesn't exist             |
| `409` | Conflict          | Resource already exists            |
| `413` | Payload Too Large | File exceeds limit                 |
| `422` | Unprocessable     | Validation error                   |
| `429` | Too Many Requests | Rate limit exceeded                |
| `500` | Internal Error    | Server error                       |
| `503` | Unavailable       | Dependency failure                 |

## Common Errors

### Authentication Errors (401)

```json theme={null}
{
  "error": "invalid_api_key",
  "message": "The provided API key is invalid or has been revoked"
}
```

**Fix:** Check your API key and ensure it has the `Bearer ` prefix.

### Rate Limit Errors (429)

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit: 100 documents/hour. Retry after 3600 seconds",
  "retry_after": 3600
}
```

**Fix:** Wait for the `retry_after` duration, or upgrade your plan.

### Validation Errors (400)

```json theme={null}
{
  "error": "invalid_file_type",
  "message": "Only PDF files are supported. Received: image/jpeg"
}
```

**Fix:** Ensure you're uploading PDF files only.

### Not Found Errors (404)

```json theme={null}
{
  "error": "job_not_found",
  "message": "Job ID not found or does not belong to your tenant"
}
```

**Fix:** Verify the ID and ensure it belongs to your tenant.

## Retry Strategy

Implement exponential backoff for transient errors (429, 5xx):

```mermaid theme={null}
flowchart LR
    A["Request"] --> B{"Success?"}
    B -->|Yes| C["Done"]
    B -->|No| D{"Retryable?"}
    D -->|"4xx (not 429)"| E["Fail"]
    D -->|"429 or 5xx"| F["Wait (backoff)"]
    F --> G{"Max retries?"}
    G -->|No| A
    G -->|Yes| E
```

```python theme={null}
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=30)
)
def upload_document(file_path):
    response = requests.post(
        "https://api.docintell.com/v1/documents",
        headers={"Authorization": f"Bearer {API_KEY}"},
        files={"file": open(file_path, "rb")}
    )

    if response.status_code == 429:
        raise Exception("Rate limited")
    if response.status_code >= 500:
        raise Exception("Server error")

    return response.json()
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Check Status Codes" icon="circle-check">
    Always check HTTP status codes before parsing response body
  </Card>

  <Card title="Log Errors" icon="file-lines">
    Log the full error response including `details` for debugging
  </Card>

  <Card title="Implement Retries" icon="rotate">
    Use exponential backoff for 429 and 5xx errors
  </Card>

  <Card title="Handle Gracefully" icon="hand">
    Show user-friendly messages, not raw error responses
  </Card>
</CardGroup>
