Delivery, retries and endpoint health
This page is what happens on our side: how an endpoint becomes live, what we do when yours is slow or down, when we stop trying, and what we can see when you ask for help.
Endpoint lifecycle
| Status | Meaning | What is delivered |
|---|---|---|
Pending | Registered, not yet proven | Verification pings only |
Active | A verification ping succeeded | Every subscribed event |
Disabled | Switched off, by you, by us, or automatically after sustained failure | Nothing. No delivery records are created while disabled |
A new endpoint starts Pending. Changing its URL returns it to Pending and re-runs verification, so the new URL must be live before you ask for the change. Re-enabling a disabled endpoint does not re-verify it: a URL that was verified resumes as Active, one that was not returns to Pending. Either way it gets a clean five-day window (below).
Verification
Verification sends a real signed delivery of type endpoint.verification.v1 (see Webhook events). Any 2xx within 15 seconds verifies the endpoint and flips it to Active.
| Attempts | 3 |
| Schedule | Immediately, then after 1 minute, then after 5 minutes |
| After 3 failures | Verification is Failed and the endpoint stays Pending. Ask us to re-run it once your endpoint is ready |
| Re-run cooldown | One minute between requests |
Failed pings do not count towards the circuit breaker or auto-disable. An endpoint that has never worked is not a broken endpoint, it is one that is not finished yet.
What counts as delivered
| Response | Result |
|---|---|
Any 2xx | Delivered. The body is ignored |
3xx | Failed. We never follow redirects. The signature covers the host and path, so a redirected request could not verify anyway |
4xx, 5xx | Failed |
| No response within 15 seconds | Failed, recorded as a timeout |
| TLS or DNS failure | Failed, recorded as a transport error |
| Host resolves to a private, loopback, link-local or otherwise non-public address | Blocked, recorded as blocked:<reason>; no request is made |
That last row is a delivery-time check, not just a registration-time one: we resolve your host, refuse non-public addresses, and connect to the address we vetted, so a DNS record that changes between check and connect cannot redirect a delivery inside a private network.
Retries
Failures are retried on a fixed ladder, counted from the failed attempt:
| After attempt | Next attempt in |
|---|---|
| 1 | 30 seconds |
| 2 | 5 minutes |
| 3 | 30 minutes |
| 4 | 2 hours |
| 5 | 5 hours |
| 6 and after | 8 hours |
Only age ends an event delivery, not a count of attempts: we keep retrying on that ladder until the delivery is five days old, then mark it Failed and stop. A delivery that is sitting in the ladder still appears in diagnostics, and the event stays readable from GET /v1/events for 90 days either way.
One delivery is in flight per endpoint at a time, oldest first. Two consequences worth designing for:
- Your endpoint never sees a burst of parallel connections from us, however big your backlog is.
- A slow endpoint slows its own queue and nobody else's, and since attempts are serialised per endpoint, a single very slow handler is the most effective way to build a backlog.
There is no ordering guarantee between events. Retries, replays and independent scheduling all reorder. Use occurredAt and a fetch from the API to work out the current state of anything you care about.
When an endpoint keeps failing
Degraded (circuit breaker)
After 10 consecutive failed attempts the endpoint's breaker opens and it is marked Degraded. While it is open we stop working through the queue and send one probe every 5 minutes instead. The first probe that succeeds closes the breaker, resets every pending delivery for that endpoint to due-now, and the queue drains in order.
Degraded is a health signal, not a status change: the endpoint is still Active and still subscribed. Verification pings never open the breaker.
Auto-disable
If an endpoint has undelivered events and goes five days without a single successful delivery, we disable it automatically. The disable reason is recorded as AutoDisabledDeliveryFailure and your IFX Payments representative is the one who re-enables it.
The five-day clock is anchored on the later of: the oldest undelivered event, the last time the endpoint went Active, and the last successful delivery. So a re-enabled endpoint gets a fresh window rather than being disabled again immediately by old backlog.
While an endpoint is disabled no delivery records are created at all. Events are still recorded, which is what makes recovery possible:
- We re-enable the endpoint.
- We ask for a missed-deliveries replay, which creates deliveries for the events that were never given one (1000 oldest per run).
- Those deliveries go out through the normal dispatcher, signed, on the normal ladder.
Replays
A delivered or failed delivery can be replayed on request. A replay:
- sends the same body, byte for byte, with the same envelope
id; - increments
Webhook-Attempt; - carries a fresh signature with a current
created.
So a replay looks exactly like a duplicate to your receiver, which is precisely why de-duplicating on the envelope id matters. Every replay is recorded in an audit log with who asked for it.
What we can see when you call support
Quote the Webhook-Delivery-Id. Against it we can see:
| Delivery list | Every delivery to your endpoints, newest first, filterable by event type, status and date |
| Attempt log | Per attempt: number, when it was sent, your response code, latency, and the error text. No payloads |
| Endpoint health | Breaker state, consecutive failures, last attempt, last success, last failure, last response code, pending backlog |
| Missed deliveries | The events your endpoint was never given a delivery for, with a count and a preview |
| Actions | Re-run verification, replay one delivery, replay missed deliveries |
Retention is 90 days for deliveries and attempt logs, matching the events window. Ask before that runs out.
Limits and numbers in one place
| Request timeout | 15 seconds |
| Success | Any 2xx |
| Redirects followed | None |
| Retry ladder | 30s, 5m, 30m, 2h, 5h, then every 8h |
| Delivery gives up after | 5 days from the event |
| Verification attempts | 3 (immediately, 1m, 5m) |
| Verification re-run cooldown | 1 minute |
| Breaker opens after | 10 consecutive failures |
| Probe interval while degraded | 5 minutes |
| Auto-disable after | 5 days without a success |
| Concurrent deliveries per endpoint | 1 |
| Endpoints per auth group | 10 |
| URL length | 500 characters |
| Delivery and event retention | 90 days |
Signature created tolerance | ±5 minutes. Enforce it |
| Key set cache lifetime | 300 seconds, with ETag |
Updated about 2 months ago