Developers

Get missed events

Webhooks are best-effort: a long enough outage on your side, a misconfigured TLS cert, or a 5xx blip during a retry window can leave a delivery permanently failed. Plan for it — combine the Dashboard's delivery log with a periodic reconcile against the REST API and your handlers will never drift from the source of truth.

What "missed" means

A delivery is failed while Stridge is still retrying it (Retries) and permanently failed once the retry budget is exhausted. Once permanently failed, Stridge stops attempting that delivery; the event itself is not lost — it stays queryable through the REST API and replayable from the Dashboard.

Common reasons a delivery exhausts retries:

  • Your server returns 5xx for the entire retry window (deploy, dependency outage).
  • The endpoint URL is wrong or no longer resolving (DNS, TLS cert expired).
  • A signature mismatch causes your handler to reject every retry (see Verify signature).
  • Your handler timed out under load; the retry policy gave up before recovery.

Inspect failed deliveries

In the Dashboard under Webhooks → Deliveries, filter by status failed to see every delivery that exhausted retries — including the response code your server returned, the request body, and the signature headers. This is the first place to look when an event you expected didn't land.

Replay a delivery

From the same Deliveries view, opening a failed row exposes a Replay action that re-sends the exact same envelope (same id, same payload) to your subscriber. Because your handler is already keyed by webhook-id, replays are safe — a successful redelivery is a no-op for any envelope you already processed.

Tip

Replay is the fast path while you are debugging a broken handler — fix the bug, deploy, then replay the failed deliveries to catch up. For a backlog larger than a handful of events, reconcile via REST instead.

Reconcile against the REST API

For systems where missing an event is unacceptable — settlements, deposits — run a periodic job that lists the underlying resource from the REST API and reconciles it against what your database has marked as processed. The webhook stream becomes the fast path; the reconcile is the safety net.

A workable shape:

Pick a high-watermark cursor

Persist the last created_at (or last id) you successfully processed for each resource — deposits, settlements, transactions.

Page forward from the cursor

Once an interval (every 5–15 minutes for hot resources; hourly for cold), list the resource from the API filtered by created_at >= cursor and walk every page.

Upsert what is new

For each row you have not processed, run the same handler logic the webhook would have triggered — keyed by the resource id so replays are idempotent.

Advance the cursor

Only after the page is fully processed; never before, or a crash mid-page will drop events.

The REST endpoints to reconcile against are the same ones you would use for a one-off lookup — see the API Reference for the per-resource list endpoints (GET /v1/deposits, GET /v1/settlements, and so on).

Build for replays

Whether an event arrives once, three times via retry, or twice via reconcile-on-top-of-webhook, your handler should produce the same end state. The contract is non-negotiable:

  • Key everything by event id, not arrival timewebhook-id for live events, the resource id (deposit.id, settlement.id) for reconciles.
  • Make state transitions idempotentdeposit.confirmed arriving twice should not double-credit a balance.
  • Keep a processed-events table — even a simple (event_id, processed_at) row per webhook is enough to turn duplicate deliveries into no-ops.
Was this page helpful?