Skip to main content

accountDeleted

The accountDeleted webhook event is triggered when an email account is removed from EmailEngine. It is the final event in the account lifecycle and means the account configuration and its cached data have been deleted.

When This Event is Triggered​

The accountDeleted event fires when:

  • An account is deleted via the Delete Account API
  • An account is removed through the admin interface

Both paths go through the same deletion routine. The account record, its stored credentials, mailbox listing, cached message index, queued outbound messages and access tokens are removed from Redis first, then the main process sends this webhook and tells the worker that held the connection to tear it down.

This is the one event that is still delivered for an account that no longer exists. Every other webhook is dropped when its account cannot be found at delivery time.

Payload Schema​

Top-Level Fields​

FieldTypeRequiredDescription
serviceUrlstring or nullYesThe configured EmailEngine service URL. null when the serviceUrl setting is empty
accountstringYesThe account ID of the deleted account
datestringYesISO 8601 timestamp when the webhook was generated
eventstringYesAlways accountDeleted
dataobjectYesEvent data object

Event Data Fields (data object)​

FieldTypeRequiredDescription
accountstringYesThe account ID, the same value as the top-level account field

There is no event ID in the body. EmailEngine sends it in the X-EE-Wh-Event-Id request header, which is what to deduplicate on. See Delivery and Retries.

Example Payload​

{
"serviceUrl": "https://emailengine.example.com",
"account": "user123",
"date": "2025-10-17T14:32:45.892Z",
"event": "accountDeleted",
"data": {
"account": "user123"
}
}

Example Payload (Without Service URL)​

When no service URL is configured:

{
"serviceUrl": null,
"account": "gmail-user456",
"date": "2025-10-17T16:45:00.000Z",
"event": "accountDeleted",
"data": {
"account": "gmail-user456"
}
}

Handling the Event​

A failed or timed-out delivery is retried, so the same event can arrive more than once. Make the handler tolerate an account that is already gone from your records:

async function handleAccountDeleted(event, headers) {
const { account, date } = event;
const eventId = headers['x-ee-wh-event-id'];

const accountRecord = await db.accounts.findUnique({
where: { emailEngineId: account }
});

if (!accountRecord) {
// Already removed by an earlier delivery of this event
return;
}

await db.accounts.delete({
where: { emailEngineId: account }
});

await auditLog.create({
event: 'account_deleted',
account,
timestamp: date,
eventId
});
}

Event Sequence​

When an account is deleted, you receive only:

  1. accountDeleted - Account is removed (this event)

No other events follow, because the account no longer exists. Events for the same account that were still queued when it was deleted are dropped rather than delivered.

Complete Account Lifecycle​

A typical complete account lifecycle includes:

  1. accountAdded - Account is registered
  2. authenticationSuccess - Account successfully authenticates
  3. accountInitialized - Initial mailbox sync is complete
  4. (Account is active, various message and mailbox events may occur)
  5. accountDeleted - Account is removed (final event)

Important Considerations​

Data Already Deleted​

When you receive the accountDeleted webhook, the account data has already been removed from EmailEngine. Get Account returns a 404 for it. If you need account metadata for cleanup purposes, store it in your own database when the account is created.

Timing​

The webhook is queued as part of the deletion, so it arrives as soon as delivery succeeds. There is no delay between the deletion and the notification other than queue and network time.

See Also​