Skip to content
emailkit
Esc
navigateopen⌘Jpreview
On this page

Recover missed events

Replay missed provider events through your existing hooks with sync().

Server was down? Webhook never arrived? sync() asks the provider for the events from that window and runs them through your existing hooks, oldest first. No separate recovery code path — the same hooks handle live and replayed events.

const result = await emailkit.sync({
  emailDriver: "resend",
  since: outageStartedAt,
});
const result = await emailkit.domains.sync({
  emailDriver: "mailgun",
  domain: "mg.example.com",
  since: outageStartedAt,
});
const result = await emailkit.mailboxes.sync({
  emailDriver: "outlook",
  mailbox,
  auth,
  since: outageStartedAt,
});

The result tells you how many events were replayed and syncedFrom — how far back the provider could actually look. Pass until to limit the range and signal to cancel a long sync.

Replays are safe by design

Sync can deliver events your app already saw. The same rules that make webhooks safe make sync safe:

  • Save received mail by messageId so an existing message updates instead of duplicating.
  • Ignore repeated eventId values when present.
  • Pass a context flag to skip side effects you don’t want during recovery, like auto-replies:
await emailkit.sync({
  emailDriver: "aiinbx",
  since,
  context: { replay: true },
});

Continue after a failure

If one of your hooks throws mid-sync, emailkit tells you where to pick up:

import { EmailKitSyncError } from "emailkit";

try {
  await emailkit.sync({ emailDriver: "resend", since });
} catch (error) {
  if (error instanceof EmailKitSyncError) {
    await emailkit.sync({
      emailDriver: "resend",
      since: error.lastEventTimestamp ?? since,
    });
  }
}

What each provider can replay

Provider Scope Recoverable history
Resend Account Inbound email
AIInbx Account Inbound email
Mailgun Account or domain Inbound and tracking events within retention
Gmail Mailbox Inbound mailbox history
Outlook Mailbox Received mailbox messages

Last updated on July 24, 2026

Was this page helpful?