Drıftstack docs
Docs

Replaying webhook deliveries

Driftstack retries failed webhook deliveries 5 times with exponential backoff before parking them in the DLQ. When your endpoint goes down for a brief outage and you fix it, you can re-fire any delivery yourself rather than emailing support.

Replay a delivery

POST /v1/webhook-deliveries/:deliveryId/replay

Resets the delivery to pending; Driftstack re-sends it within about a minute (up to 60 seconds). If its endpoint is paused, the delivery is held until you resume the endpoint.

Scoped to the effective account: the delivery must belong to a webhook endpoint your own account owns, or one owned by the account you are acting as via X-Driftstack-Account. Replay re-fires the delivery, so it counts as a write — acting as a team owner requires admin on that team, and without the header your key needs account_owner. Returns the updated delivery.

Request body: {} (empty).

Response (200):

{
  "id": "wdl_00000000-0000-4000-8000-000000000001",
  "webhook_id": "whk_00000000-0000-4000-8000-000000000099",
  "event_id": "00000000-0000-4000-8000-0000000000aa",
  "event_type": "session.completed",
  "status": "pending",
  "attempts": 0,
  "next_attempt_at": "2026-05-08T10:00:00Z",
  "last_response_status": null,
  "last_response_excerpt": null,
  "last_error": null,
  "delivered_at": null,
  "created_at": "2026-05-08T09:00:00Z"
}

Typical flow

  1. Your endpoint goes down at 10:00 — Driftstack retries each delivery on the backoff schedule (1m, 5m, 15m, 30m, 60m). It stays down past the last retry, so ~2 hours later the deliveries land in DLQ (status: "dlq").
  2. You fix your endpoint at 13:00.
  3. List the DLQ deliveries: GET /v1/webhooks/:webhookId/deliveries?status=dlq
  4. Replay each one: POST /v1/webhook-deliveries/:deliveryId/replay. Within a minute Driftstack re-sends them and (if your endpoint is healthy) marks them delivered.

SDK examples

TypeScript:

const dlq = await client.webhooks.listDeliveries('whk_xxx', { status: 'dlq' });
for (const delivery of dlq.data) {
  await client.webhooks.replayDelivery(delivery.id);
}

The same call iterates lazily across all pages:

for await (const delivery of client.webhooks.iterateDeliveries('whk_xxx', { status: 'dlq' })) {
  await client.webhooks.replayDelivery(delivery.id);
}

Python:

for delivery in client.webhooks.iterate_deliveries("whk_xxx", status="dlq"):
    client.webhooks.replay_delivery(delivery.id)

Go:

page, err := client.Webhooks.ListDeliveries(
    ctx,
    "whk_xxx",
    &driftstack.ListDeliveriesQuery{Status: driftstack.DeliveryDLQ},
)
if err != nil {
    return err
}
for _, delivery := range page.Data {
    if _, err := client.Webhooks.ReplayDelivery(ctx, delivery.ID); err != nil {
        return err
    }
}

Errors

  • 404 Not Found — the delivery id is unknown, or the delivery belongs to an endpoint that isn’t yours. (We return 404 not 403 so the endpoint doesn’t leak the existence of other accounts’ deliveries.)
  • 409 Conflict — the delivery is being attempted right now (status: "in_flight"). Check its status again in a few minutes: if it hasn’t been delivered by then, replay it.
  • 400 Bad Request — the delivery id is malformed (must be wdl_<uuid>).
  • 429 Too Many Requests — the global rate limit, or the limit that replays and test sends share (10 at once, then 10 a minute per account, on every plan); wait for the Retry-After seconds and retry.

Audit

Every customer-initiated replay records a webhook_delivery.replayed entry in your account’s audit log, which you read in the Driftstack dashboard. The payload includes endpoint_id and event_type for cross-reference.