My App
Webhooks

Retries & Replay

Retry policy, dead-letter semantics, and manual replay — per-delivery and replay-since-history — for recovering from receiver outages.

Retries & Replay

Emofy gives your receiver multiple chances to accept a delivery, and gives you tools to catch up after a longer outage.

Retry schedule

AttemptDelay from previous
1immediate
2~1s
3~3s
4~9s
5~27s

Retries trigger on 5xx responses or request timeouts (not 4xx — those indicate receiver misconfiguration, not unavailability).

After attempt 5 fails, the delivery is marked dead_lettered and stops retrying automatically. It remains visible in the delivery log viewer and can be manually replayed.

Per-delivery manual replay

From the developer portal delivery log, any failed or dead_lettered delivery shows a Replay button (gated by webhooks:replay permission). A new delivery row is created with is_manual_retry=true, and the original row's error message is annotated with the new delivery id for traceability.

API:

POST /api/developer/apps/:appId/webhooks/:id/deliveries/:deliveryId/replay

Replay-since-history

If your receiver was down for hours, replaying each delivery individually is tedious. Use replay-since to re-fire every event from the outbox matching your webhook's subscribed events since a given timestamp.

POST /api/developer/apps/:appId/webhooks/:id/replay-since
Content-Type: application/json

{
  "fromTimestamp": "2026-04-17T00:00:00Z",
  "dryRun": true
}

With dryRun: true (default), Emofy returns:

{
  "matchedCount": 147,
  "earliestEventId": "wob_...",
  "latestEventId": "wob_..."
}

Call again with "dryRun": false to actually enqueue the matched events. The response returns a replayBatchId (rbt_*) which stamps every resulting delivery row for correlation in the log viewer.

Rate limit: 1 replay-batch per webhook per 5 minutes. Subsequent calls return 429 REPLAY_RATE_LIMITED with a retryAfter field.

Retention horizon: 30 days. Events older than 30 days have been swept from the outbox and are not replayable.

Tips

  • Test with dryRun first. A single replay-since can re-fire thousands of events — verify the match count before committing.
  • Make replay idempotent on your side. Receivers MUST dedupe on X-Emofy-Delivery-Id; manual replays produce new delivery ids, so the timestamp + payload may appear to repeat.
  • Don't replay success deliveries. The API rejects these — if your system lost the result after acknowledging a successful delivery, you need your own replay mechanism, not Emofy's.

Dead-letter clean-up

Dead-lettered deliveries remain in the log indefinitely (30-day outbox retention applies only to the replay eligibility window — the delivery row itself is kept). You can filter the log viewer by status=dead_lettered to triage what needs replay after a long outage.

On this page