# Webhooks
Source: https://nordvec.com/docs/guides/webhooks#retries-and-failure

## Retries and failure [#retries-and-failure]

Your endpoint has **10 seconds** to respond, connection setup included. A
response with a 2xx status counts as delivered; anything else, including a
timeout or a redirect (deliveries never follow redirects), counts as a failure
and is retried. The one exception is **410 Gone**: it tells us the route was
removed on purpose, so that delivery is not retried and the endpoint is
disabled at once, with an `endpoint.disabled` event (reason `gone`) to the
workspace's other endpoints and an email to every owner and admin. A 410 in
answer to Send test event or Resend delivery fails only that delivery.
Respond 2xx as soon as you have durably accepted the event, and do the heavy
processing asynchronously.

A failed delivery is retried on this schedule:

| Attempt | Delay after the previous failure |
| ------- | -------------------------------- |
| 1 | immediate |
| 2 | 5 seconds |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 5 hours |
| 7 | 10 hours |
| 8 | 10 hours |

That is 8 attempts over roughly 27.5 hours, so a full-day outage on your side
does not lose events. Each delay carries up to 20% random jitter in either
direction, which prevents synchronized retry bursts against a recovering
endpoint. If your endpoint returns a `Retry-After` header, the requested delay
is honored within limits: it is clamped between the scheduled delay and twice
the scheduled delay. Responses with status 429 and timed-out attempts wait at
least 60 seconds before jitter is applied, so never less than 48 seconds,
regardless of how early the schedule slot falls.

### Auto-disable [#auto-disable]

An endpoint that keeps failing is eventually disabled rather than hammered
forever:

- When deliveries have been failing for 30 minutes, a `delivery.failing`
  event fires once (delivered to the workspace's other endpoints) and every
  workspace owner and admin gets an in-app notification. This is the early
  warning; a blip that a success closes within those 30 minutes raises
  nothing.
- As the failure window runs on, the warning escalates: at **3 days** and
  again at **4.5 days** every owner and admin gets an in-app notification and
  an email naming the time after which the endpoint is disabled if deliveries
  are still failing. Each warning reaches each person once per failure window.
- A successfully delivered event resets the failure window. A test event
  does not: it proves the endpoint answers, not that it processes events. If
  a warning had already gone out, a `delivery.recovered` event fires and
  owners and admins get an in-app notification that the endpoint recovered.
- After **5 days** of consecutive failures, the endpoint is disabled: an
  `endpoint.disabled` event fires (again, to other endpoints), and every
  workspace owner and admin is emailed.

The disable needs a failed delivery after the final warning. If nothing was
sent to the endpoint by the time the final warning named, the next failure
raises a fresh final warning instead, and the endpoint is disabled only if
deliveries are still failing 12 hours later.

Switching an endpoint off yourself fires `endpoint.disabled` with reason
`manual` to the workspace's other endpoints. A disabled endpoint receives no
further deliveries, and its send-test and resend actions are blocked. Once
your receiver is healthy again, re-enable the
endpoint from workspace settings (click its status badge): re-enabling clears
the failure history, so the endpoint starts a fresh 5-day window, and an
`endpoint.enabled` event fires to the workspace's other endpoints. Events that
occur while an endpoint is disabled are recorded in its delivery log with the
**dropped** status instead of being sent. After re-enabling, use **Send test
event** to confirm the endpoint is reachable, then **Replay undelivered** to
catch up on everything the outage cost in one action.