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

# Retries & Error Handling

## Acknowledging deliveries

Your endpoint must respond with a `2xx` status code within **30 seconds** to acknowledge receipt. Any other status code (or a timeout) is treated as a failure.

## Retry policy

When a delivery fails, Nexor retries with exponential backoff:

| Attempt   | Delay after failure |
| --------- | ------------------- |
| 1st retry | 1 minute            |
| 2nd retry | 5 minutes           |
| 3rd retry | 30 minutes          |

After 3 failed retries, the delivery is marked as `failed` and no further attempts are made.

Retries are only triggered for:

* **5xx** server errors
* **429** rate limit responses
* **Timeouts** (no response within 30s)
* **Network errors** (connection refused, DNS failure)

**4xx errors** (except 429) are **not retried**. They indicate a permanent client-side issue (bad URL, auth failure, etc.).

## Auto-disable

If a webhook accumulates too many consecutive failures, Nexor automatically disables it to prevent wasting resources. You can re-enable it from the dashboard, and the failure counter resets on re-enable.

## Delivery logs

Every delivery (successful or failed) is logged and visible in the dashboard under your webhook's **Deliveries** tab. Each log entry includes:

* Request URL, headers, and body
* Response status, headers, and body
* Duration in milliseconds
* Attempt number
* Error message (if failed)

## Idempotency

Your endpoint may receive the same event more than once (e.g. if your server responds slowly and Nexor retries). Use the `delivery_id` or `event_id` to deduplicate on your side:

```javascript theme={null}
const processedEvents = new Set();

app.post('/nexor-webhook', (req, res) => {
  const { event_id } = req.body;

  if (processedEvents.has(event_id)) {
    return res.status(200).send('Already processed');
  }

  processedEvents.add(event_id);

  // Process the event...
  res.status(200).send('OK');
});
```

**Tip:** For production use, store processed `event_id` values in a database or cache (e.g. Redis with TTL) instead of an in-memory Set.

## Testing

Use the **Test** button in the webhook dashboard to send a sample payload to your endpoint. Test payloads have `"test": true` in the body so you can distinguish them from real events.
