Retries and redelivery
What Capa does when your server is down, how an endpoint pauses itself, and how to send missed events again.
Success and failure
A delivery succeeds on any 2xx. Anything else fails it: a 4xx, a 5xx, a timeout, a connection error, or a redirect. Redirects are not followed, since a redirect is how a signed request ends up somewhere it was not meant for.
Retries
Each delivery gets six attempts:
| Attempt that failed | Next attempt |
|---|---|
| 1 | in 1 minute |
| 2 | in 5 minutes |
| 3 | in 30 minutes |
| 4 | in 2 hours |
| 5 | in 6 hours |
| 6 | none. The delivery is exhausted |
The last attempt lands 8 hours 36 minutes after the first, so a receiver that comes back within a working day catches up on its own.
A delivery is pending, succeeded, failed (no more attempts are coming), exhausted (all six were used) or cancelled (the endpoint was paused, disabled or deleted while it waited). Each one is kept for 30 days with the request Capa sent and the answer it got, under the endpoint in Developers > Webhooks.
Auto-pause
An endpoint pauses itself when it reaches 25 failures in a row and the first of them is at least 24 hours old. Both conditions are needed: 25 failures in ten minutes is an outage, and an outage should not cost you the endpoint. Any single 2xx resets the count.
A paused endpoint delivers nothing, and what was queued for it is cancelled.
Sending events again
There are three ways, for three situations.
One delivery. Choose Redeliver on its row. Capa sends a new delivery with the same event id, so your receiver sees the same Idempotency-Key and can treat it as a repeat. A delivery still pending cannot be redelivered until it settles.
Everything that failed. When an endpoint has failed deliveries, a button above its deliveries offers to send them again, such as Redeliver 14 failed deliveries. It sends every failed and exhausted delivery in one action. A delivery that already has a redelivery waiting is skipped, so doing it twice sends nothing twice.
Everything missed while paused. Resume the endpoint. Capa turns it back on and tells you how many events it missed since it was paused, without sending them. Confirm, and those events are sent. Nothing is ever backfilled without that confirmation.
URL rules
httpsonly. A webhook body carries ids, titles and, with Include content data, your content. Over plainhttpanything on the path could read it.- No private addresses. When you save, Capa refuses a URL whose host is a private, loopback, link-local or other reserved address. On every delivery, Capa looks the host up again and refuses it if it resolves to one of those addresses. The connection goes only to the addresses that passed. A delivery refused this way pauses the endpoint. Fix the URL or its DNS, then resume.
- No credentials in the URL.
https://user:pass@host/is refused. Put credentials in a static header instead, where they are masked in every response.
Rotating the secret
Rotate an endpoint's secret from its menu. The new secret is shown once, and for the next 24 hours every delivery is signed with both secrets, newest first: t=…,v1=<new>,v1=<old>. A receiver that still holds the old secret keeps verifying, so update it any time inside that window. Deliveries already queued are signed with the new secret too, because signing happens when a request is sent.
Lost the secret? Rotate. A project owner can also reveal it, and every reveal is recorded in the audit log.
Who can do what
| Action | Needs |
|---|---|
| See endpoints, deliveries and the event list | every role, viewer included |
| Add, edit, pause, resume, rotate, test, delete, redeliver | the admin or developer role |
| Reveal a secret | the project owner |
Webhook endpoints are managed by signed-in people only. No API key can add or change one, since a key that could would be able to forward every content change to a URL of its choosing.