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.
Delivery Status Values
| Status | Meaning |
|---|---|
pending |
Queued or waiting for next retry |
success |
Accepted by your endpoint (2xx) |
failed |
All 5 attempts exhausted |