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

# Delivery and retries

> What a 2xx means, the exact retry schedule, rate caps, dead-lettering, and how to read the delivery log.

## What this lets you do

Know exactly how Traceten delivers events to your endpoint, so you can build a handler that never loses data and debug one that does.

## What counts as delivered

Traceten sends each event as an HTTPS `POST` with a JSON body and waits up to **10 seconds** for a response.

* **Any 2xx status** (200, 201, 202, 204, ...) counts as delivered. The response body is ignored.
* **Anything else fails the attempt**: a non-2xx status, a timeout, a TLS error, or a connection failure. Redirects are not followed; a 3xx is a failure.

Return the 2xx before doing real work. Parse, verify the signature, enqueue, respond. A handler that processes inline will eventually exceed the 10-second budget under load and turn healthy traffic into retries.

## Retry schedule

A failed attempt is retried with exponential backoff. Each delivery gets one initial attempt plus up to five retries:

| Attempt | Delay after previous failure |
| ------- | ---------------------------- |
| 1       | immediate                    |
| 2       | 1 minute                     |
| 3       | 5 minutes                    |
| 4       | 30 minutes                   |
| 5       | 2 hours                      |
| 6       | 12 hours                     |

After the sixth attempt fails, the delivery is marked **failed** (dead-lettered) and is not retried again. Failed deliveries stay visible in the delivery log for the retention window so you can see what you missed. Traceten does not automatically disable an endpoint, no matter how many deliveries fail; a broken endpoint keeps accumulating failed deliveries until you fix or disable it.

Two consequences worth designing for:

* **Retries mean at-least-once delivery.** If your endpoint returns a 500 after processing, or times out while succeeding, you will see the same delivery again. The envelope `id` is stable across retries of the same delivery; deduplicate on it.
* **Retries mean out-of-order arrival.** A retried event from an hour ago can land after a fresh one. Order by the envelope `created` timestamp or the `data.timestamp`, not by arrival.

One exception: `webhook.ping` test deliveries get a single attempt and never enter this schedule. A failed ping is terminal; re-send it from the dashboard instead.

## Rate cap

Each endpoint is capped at **100 deliveries per second** to protect your infrastructure. Deliveries over the cap are deferred and sent as capacity frees up; they are not counted as failures and do not consume retry attempts. The exception is `webhook.ping`: a rate-capped ping is not deferred but marked `failed`, since a test that arrives later is not a useful test.

## Delivery log

Every delivery is recorded and retained for **30 days**. In the dashboard, open **Settings → Webhooks** and select an endpoint to see its log. There is one entry per delivery, updated in place as it is retried: each entry shows the event type, current status (`pending`, `retrying`, `succeeded`, or `failed`), the number of attempts made, the most recent response status code, and (on failure) a short snippet of your endpoint's response.

`webhook.ping` deliveries, both the automatic registration ping and **Send test event**, appear in the same log with a **Test** badge. They are terminal after their single attempt: `succeeded` or `failed`, never `retrying`. A ping that was deferred by the rate cap is recorded as `failed` rather than re-sent.

Use the log to answer the usual questions:

* **"Did you send it?"** Find the delivery by event type and time. If it is there, check its status and attempt count.
* **"Why did it fail?"** The recorded status code and response snippet show what your endpoint returned on the most recent attempt.
* **"What did I miss while I was down?"** Filter for failed deliveries during the outage window.

## Handler checklist

1. Accept `POST` with a JSON body over HTTPS.
2. [Verify the signature](/webhooks/verify-signatures) against the raw body before parsing.
3. Return a 2xx within 10 seconds; queue heavy work.
4. Deduplicate on the envelope `id`.
5. Tolerate out-of-order arrival; order by `created` when it matters.
6. Ignore unknown event types and unknown fields instead of erroring.

## Next

* [Set up an endpoint](/webhooks/setup)
* [Event reference](/webhooks/events)
* [Verify signatures](/webhooks/verify-signatures)
