Skip to main content

Event Replay Troubleshooting

When a webhook misses an event or your downstream system loses state, replay is the recovery tool. This page covers the operator-facing how-to: where to replay from, what to check first, and the common pitfalls that turn a quick fix into a slow one.

For the conceptual model, see Replay mechanics.

Decide before you replay

Before triggering a replay, answer two questions:

  1. Did the event actually fire? Check the engagement events list scoped to the inbox. If the event is not there, replay will not help; the underlying message did not produce that event.
  2. Did the original delivery succeed or fail on the receiving end? Check the deliveries log. A delivery that returned 200 but did not change downstream state is a bug in your handler, not a missed event. Fix the handler, then replay.

Replaying a successful delivery is harmless if your handler is idempotent (and it should be). But it is wasted work if the real fix is on your side.

Replay from the console

For one-off recovery, the dashboard is fastest. Open the inbox, find the failed delivery in the deliveries log, click Replay. The dashboard sends to the original URL by default, with a toast confirming the new attempt.

Replay via API

For programmatic recovery:

curl -X POST https://getmail.bot/v1/events/$EVENT_ID/replay \
-H "Authorization: Bearer $MAILBOT_API_KEY"

To replay against a different URL (staging, a temporary debugging endpoint, a new consumer):

curl -X POST https://getmail.bot/v1/events/$EVENT_ID/replay \
-H "Authorization: Bearer $MAILBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target_url": "https://staging.example.com/webhooks/mailbot"}'

The override URL receives a payload signed with the same secret as the original webhook. If your staging endpoint uses a different secret, you have two options:

  • temporarily relax verification on staging
  • spin up a debug receiver that logs but does not verify (dev only)

Do not push the production secret to staging just to make replay work. Use the override pattern.

Bulk replay

There is no single bulk-replay endpoint. List the events you want, then replay each:

const events = await mailbot.events.list({
inbox_id: 'inb_xxx',
event_type: 'message.received',
since: '2026-04-15T00:00:00Z',
until: '2026-04-15T23:59:59Z',
});

for (const event of events) {
await mailbot.events.replay(event.event_id);
await new Promise((r) => setTimeout(r, 100)); // gentle pacing
}

The 100ms pacing is for your endpoint, not mailbot. If your endpoint has a tight per-second limit, slow this down accordingly.

Common pitfalls

Replaying without checking idempotency

If your handler is not idempotent, replay will double-write. Double-counts in lead scoring, duplicate Slack notifications, duplicate database rows. Fix the handler first.

Forgetting that retention is bounded

Event payloads are retained for 90 days for replay. After that, the event metadata stays in the audit log but the body is gone. If you need replay capability beyond 90 days, mirror events to your own storage on first receipt.

Treating replay as a side effect for the message

Replay re-fires the event to your endpoint. It does not re-send the email. To re-send a message, use Send message to a fresh send, not replay. Replay does not produce a new Message-ID; the original one remains.

Misreading the deliveries log

The deliveries log shows attempts at the delivery level, not the event level. One event can have multiple delivery rows (initial + retries + replays). Filter by event_id to see all attempts for a given event.

Replaying into a misconfigured staging

If staging cannot verify the signature, your replay will look like a 401 in the deliveries log. That is staging being correct, not mailbot being wrong. Configure staging with the right secret (or relax verification temporarily).

Audit trail

Every replay attempt is recorded in the audit log. Each entry includes:

  • the original event_id
  • the timestamp of the replay
  • the destination URL (original or override)
  • the response status returned by the endpoint
  • the API key that triggered the replay

Use List audit log when you need a forensic view of who replayed what and when.

Recipe: recover a missed batch

A complete recovery walk-through:

  1. Identify the window. When did the endpoint go down? When did it come back?
  2. List failed deliveries for that window in the deliveries log.
  3. Confirm the events still exist within the 90-day retention window.
  4. Verify the handler is idempotent before replaying.
  5. Replay, paced. Walk the list, replay each, pace at your endpoint's rate limit.
  6. Confirm downstream state. Spot-check that the events that were missed now show their effects in your system.