Retries & Replays
The webhook dispatcher retries on transient failures and gives up on permanent ones. This page covers the exact behaviour so your endpoint can plan for it.
Retry schedule
Total retry window: ~21 minutes. After that the event is marked
gave_up in our audit log and no further attempts are made.
What triggers a retry
Why 4xx doesn't retry
Most 4xx responses indicate your endpoint is broken in a way time won't fix:
- 401/403 — wrong shared secret
- 404 — endpoint doesn't exist
- 405 — wrong HTTP method
- 422 — payload schema mismatch
If your endpoint needs time to recover (e.g. you just deployed +
the route 404s for 30 seconds), respond with 503 instead of 404
during the deploy window. We'll retry.
Idempotency
Every webhook attempt carries a unique X-Splashify-Delivery-ID
header. Even retries of the same event have a fresh delivery ID.
To dedup at your end, key off mail.messageId + eventType:
const key = `${body.mail.messageId}:${body.eventType}`;
const inserted = await db.events.insertOne({
_id: key,
...body,
receivedAt: new Date(),
}, { ignoreDuplicates: true });
if (!inserted.insertedCount) {
return res.status(200).end(); // already processed, ack
}
// ... processThe combination is unique per event — even if we retry due to your
500 response, the second delivery has the same mail.messageId +
eventType and your insert dedups it.
Manual replay
For events that gave up (your endpoint was down for >21 minutes), contact support to replay them. We retain the full event log for 30 days and can re-fan-out a specific window.
Self-serve replay is on the roadmap — POST /partner/email/events/replay
with a time range + optional event-type filter.
Inspecting webhook delivery state
To see whether an event was delivered to a destination:
curl 'https://api.splashifypro.com/api/v1/partner/email/events?day_bucket=2026-05-03' \
-H "Authorization: Bearer $SPLASHIFY_API_KEY"Response includes per-destination delivery status (delivered, failed, gave_up) so you can see which webhooks landed.
Common reasons for repeated failures
- Endpoint times out > 10 seconds. Your handler should ack ASAP (write to a queue, return 200) and process async.
- Endpoint behind Cloudflare with bot protection. Bot challenges
return 403 to our requests — whitelist our user-agent
(
Splashify-Pro-Webhook/1.0) or our outbound IP range. - HTTPS cert expired. We don't disable cert verification. Renew + monitor.
- Wrong secret. If you rotated the secret in the panel but didn't roll it on your endpoint, every signature check returns 401.