# Error Handling

> Handle errors and implement retry logic for reliable ingestion.

URL: https://docs.reaktly.com/docs/integrations/error-handling

## HTTP Status Codes

| Code | Meaning | Action |
|---|---|---|
| `200` | Success — item queued | ✅ Continue |
| `400` | Bad request — validation error | Fix the payload |
| `401` | Unauthorized — invalid API key | Check your API key |
| `403` | Forbidden — insufficient scopes or expired key | Verify key has `iq:import` scope |
| `413` | Payload too large | Reduce batch size or content length |
| `429` | Rate limited | Back off and retry |
| `500` | Server error | Retry with exponential backoff |

## Retry Strategy

Implement exponential backoff with jitter for resilient integrations:

```ts
async function ingestWithRetry(payload: any, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch('https://api.reaktly.com/ingest', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.REAKTLY_API_KEY!,
      },
      body: JSON.stringify(payload),
    });

    if (response.ok) return response.json();

    const isRetryable = [429, 500, 502, 503].includes(response.status);
    if (!isRetryable || attempt === maxRetries) {
      throw new Error(`Ingestion failed: ${response.status}`);
    }

    const delay = Math.min(1000 * 2 ** attempt, 30000);
    const jitter = Math.random() * 1000;
    await new Promise(r => setTimeout(r, delay + jitter));
  }
}
```