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

# Delivery & Retries

> Understand how webhook deliveries work, including retries and failure handling

## Delivery Format

Each webhook delivery is an HTTP POST request with the following headers:

| Header                  | Description                                                                                                          |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `Content-Type`          | `application/json`                                                                                                   |
| `User-Agent`            | `paywise-webhooks/1.0`                                                                                               |
| `X-Paywise-Signature`   | HMAC SHA-256 signature (see [Signature Verification](/api-docs/case-management-api/webhooks/signature-verification)) |
| `X-Paywise-Event`       | The event type (e.g. `mandate.created`)                                                                              |
| `X-Paywise-Delivery-ID` | Unique ID for this delivery attempt                                                                                  |

## Payload Structure

```json theme={null}
{
  "event": "mandate.created",
  "timestamp": "2026-04-24T10:30:45.123456Z",
  "data": {
    "company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "access_mode": "production",
    ...
  }
}
```

| Field              | Type   | Description                                        |
| ------------------ | ------ | -------------------------------------------------- |
| `event`            | string | The event type that triggered this webhook         |
| `timestamp`        | string | ISO 8601 timestamp of when the event was processed |
| `data`             | object | Event-specific payload                             |
| `data.company_id`  | string | UUID of the company this event belongs to          |
| `data.access_mode` | string | `test` or `production`                             |

## Success Criteria

A delivery is considered **successful** when your endpoint returns any HTTP status code in the **2xx range** (200–299).

<Tip>
  Return HTTP 200 as quickly as possible. If you need to do heavy processing, acknowledge the webhook immediately and process the event asynchronously.
</Tip>

## Timeouts

paywise waits up to **30 seconds** for a response. If your endpoint does not respond within this window, the delivery is marked as failed and may be retried.

Redirects are **not followed** — your endpoint must return a 2xx response directly.

## Retry Logic

Failed deliveries are automatically retried with exponential backoff:

| Attempt   | Delay After Failure |
| --------- | ------------------- |
| 1st retry | 1 minute            |
| 2nd retry | 5 minutes           |
| 3rd retry | 15 minutes          |

After 3 failed retry attempts, the delivery is permanently marked as `failed`.

## Delivery Statuses

| Status     | Description                              |
| ---------- | ---------------------------------------- |
| `pending`  | Delivery created, awaiting first attempt |
| `success`  | Endpoint returned a 2xx response         |
| `retrying` | Delivery failed but will be retried      |
| `failed`   | All retry attempts exhausted             |

## Auto-Disable

Webhook endpoints track the number of **consecutive failures** across all deliveries. When the failure count reaches the configured threshold (default: **50**), the endpoint is automatically disabled.

* **Disabled endpoints** stop receiving events entirely
* **Re-enabling** an endpoint (via API or dashboard) resets the failure counter to 0
* You can configure the threshold via the `max_consecutive_failures` field (1–1000)

<Info>
  A single successful delivery resets the consecutive failure counter to 0. The auto-disable only triggers after an unbroken streak of failures.
</Info>

## Idempotency

Each delivery includes a unique `idempotency_key` derived from the webhook endpoint, event type, and timestamp. If you receive a delivery with the same idempotency key twice (which should be rare), you can safely skip the duplicate.

The delivery ID is also sent in the `X-Paywise-Delivery-ID` header for tracking purposes.

## Best Practices

1. **Respond quickly** — Return HTTP 200 immediately and process events asynchronously
2. **Verify signatures** — Always validate the `X-Paywise-Signature` header before processing
3. **Handle duplicates** — Use the delivery ID or idempotency key to detect and skip duplicates
4. **Monitor failures** — Check your endpoint's failure count regularly via the API or dashboard
5. **Use test mode** — Verify your integration using test events before subscribing to production events
