Skip to content

Retry Behaviour

Delivery Lifecycle

Event Created → Delivery Queued (attempt 0) → Attempt 1
                                                    ↓ failure
                                              Wait 30s → Attempt 2
                                                              ↓ failure
                                                      Wait 60s → Attempt 3
                                                                      ↓ failure
                                                              Wait 120s → Attempt 4
                                                                              ↓ failure
                                                                      Wait 240s → Attempt 5 → Failed ✗

Retry Schedule

Attempt Delay after previous failure Total elapsed
1 Immediate 0s
2 30 seconds 30s
3 60 seconds 1.5 min
4 120 seconds 3.5 min
5 240 seconds 7.5 min

After 5 failures the delivery is permanently failed. No further automatic retries occur.

Receiver Timeout

Your endpoint must respond within 10 seconds. The delivery function uses a hard AbortController timeout — after 10s the request is cancelled, counted as a failure, and the retry schedule proceeds.

Return a 2xx status immediately and process asynchronously if your handler is slow.

What Counts as Failure

Scenario Result
HTTP 2xx Success
HTTP 4xx or 5xx Failure — will retry
No response within 10s Failure — will retry
Connection refused / DNS error Failure — will retry

4xx retries

Even 4xx responses trigger retries. If you receive a delivery you can't process, return 200 to acknowledge it and handle it internally.

Test Endpoint vs Real Deliveries

POST /v1/agency/webhooks/config/test sends a synchronous one-shot delivery — it does not create a delivery log entry and does not retry on failure. Use it only to confirm your endpoint is reachable and your signature verification is correct.

Manual Replay

Replay any delivery via the agency portal or the API:

curl -X POST https://api.fixify.co.za/v1/agency/webhooks/deliveries/{id}/replay \
  -H "authorization: <token>"

Replay resets status to pending, attempt to 0, and re-enqueues immediately. The payload is immutable — the same event data is re-sent with a fresh timestamp and fresh HMAC signature.

Idempotency

Use webhookId as an idempotency key. The same delivery may arrive more than once across retries and replays.

if (await alreadyProcessed(payload.webhookId)) {
  return res.status(200).send('ok');
}

Delivery Status Values

Status Meaning
pending Queued or waiting for next retry
success Accepted by your endpoint (2xx)
failed All 5 attempts exhausted