Skip to main content

Webhooks

Webhooks

WildDuck includes a webhook system for real-time event notifications. When events occur (new messages, authentication attempts, account changes, etc.), WildDuck sends HTTP POST requests to registered webhook URLs.

How It Works

The webhook system is built on BullMQ (Redis-based job queue):

  1. An event occurs in WildDuck (e.g. a new message arrives)
  2. The event is published to the webhook queue in Redis
  3. The webhook worker picks up the event and delivers it to all matching webhook subscriptions
  4. Failed deliveries are retried with exponential backoff

At least one WildDuck instance must have webhooks.enabled = true in its configuration, otherwise events will pile up in the Redis queue.

Managing Webhooks

Webhooks are managed via the HTTP API:

  • GET /webhooks - List all webhook subscriptions
  • POST /webhooks - Register a new webhook
  • DELETE /webhooks/:webhook - Delete a webhook

Creating a Webhook

When creating a webhook, specify:

  • url - The endpoint URL (supports http://, https://, smtp://, and smtps:// schemes)
  • type - Array of event type filters
  • user (optional) - Limit the webhook to events for a specific user

Webhook subscriptions can match:

  • Exact event names like user.created
  • * to match all events
  • Namespace wildcards like user.* and user.delete.*

Global vs User Webhooks

  • Global webhooks - Receive events for all users (created without a user parameter)
  • User-specific webhooks - Only receive events for a specific user

Delivery Format

Every delivered webhook payload includes these top-level fields:

FieldTypeNotes
idstringWebhook delivery id, generated at delivery time. Format is <objectId>:<n>.
evstringEvent name.
timenumberUnix timestamp in milliseconds, added when the event is published.

Notes:

  • Top-level MongoDB ObjectId values are serialized to 24-char hex strings before queueing.
  • Webhook subscriptions can match exact event names, *, or namespace wildcards like user.* and user.delete.*.
  • The payload reference below reflects the webhook payloads emitted by this checkout of WildDuck.
  • mfa.webauthn.removed is intended to exist, but in this checkout it is broken by a constant name typo in lib/events.js and does not currently deliver.

Event Payload Reference

address.user.created

Returned data:

FieldType
userstring
addressstring
valuestring

address.user.deleted

Returned data:

FieldType
userstring
addressstring
valuestring

address.forwarded.created

Returned data:

FieldType
addressstring
valuestring

address.forwarded.deleted

Returned data:

FieldType
addressstring
valuestring

address.domain.renamed

Returned data:

FieldType
previousstring
currentstring

asp.created

Returned data:

FieldType
userstring
aspstring
descriptionstring

asp.deleted

Returned data:

FieldType
userstring
aspstring
descriptionstring

autoreply.user.enabled

Returned data:

FieldType
userstring

autoreply.user.disabled

Returned data:

FieldType
userstring

cert.created

Returned data:

FieldType
certstring
servernamestring
fingerprintstring

cert.updated

Returned data:

FieldType
certstring
servernamestring
fingerprintstring

cert.deleted

Returned data:

FieldType
certstring
servernamestring
fingerprintstring

dkim.created

Returned data:

FieldType
dkimstring
domainstring
selectorstring
fingerprintstring

dkim.updated

Returned data:

FieldType
dkimstring
domainstring
selectorstring
fingerprintstring

dkim.deleted

Returned data:

FieldType
dkimstring
domainstring
selectorstring
fingerprintstring

domainalias.created

Returned data:

FieldType
domainaliasstring
aliasstring
domainstring

domainalias.deleted

Returned data:

FieldType
domainaliasstring
aliasstring
domainstring

filter.created

Returned data:

FieldType
userstring
filterstring

filter.deleted

Returned data:

FieldType
userstring
filterstring

forward.added

Returned data:

FieldTypeNotes
userstringPresent for user-level and filter-level forwards.
typestringuser or filter.
targetstringForward target value.
filterstringPresent only when type is filter.

When type is filter, filter is the filter id as a string.

mailbox.created

Returned data:

FieldType
userstring
mailboxstring
pathstring

mailbox.renamed

Returned data:

FieldType
userstring
mailboxstring
previousstring
currentstring

mailbox.deleted

Returned data:

FieldType
userstring
mailboxstring
pathstring

marked.spam

Returned data:

FieldTypeNotes
userstringUser id.
mailboxstringMailbox id.
messagenumberMessage UID in the mailbox, not the MongoDB message id.
fromobjectPresent when parsed from the message. Usually { name, address }.
toarrayOptional decoded recipient list.
ccarrayOptional decoded recipient list.
bccarrayOptional decoded recipient list.
messageIdstringOriginal Message-ID header value.
subjectstringMessage subject.
datestringISO timestamp from internal message date.
verificationResultsobjectOptional authentication verification details.
bimiobjectOptional BIMI details when available.

from fields:

FieldType
namestring
addressstring

to, cc, and bcc array item fields:

FieldType
namestring
addressstring

verificationResults fields:

FieldType
tlsobject or boolean
spfstring or boolean
dkimstring or boolean
dmarcobject

verificationResults.tls fields when present as an object:

FieldType
namestring
versionstring

verificationResults.dmarc fields:

FieldType
domainstring or boolean
policystring

bimi fields when present:

FieldType
certifiedboolean
urlstring
imagestring
typestring

marked.ham

Returned data:

Payload is the same as marked.spam.

mfa.totp.enabled

Returned data:

FieldType
userstring

mfa.totp.disabled

Returned data:

FieldType
userstring

mfa.custom.enabled

Returned data:

FieldType
userstring

mfa.custom.disabled

Returned data:

FieldType
userstring

mfa.webauthn.registered

Returned data:

FieldType
userstring
credentialobject

credential fields:

FieldType
idstring
rawIdstring
descriptionstring
authenticatorAttachmentstring

mfa.disabled

Returned data:

FieldType
userstring

user.created

Returned data:

FieldType
userstring
usernamestring
namestring
addressstring

user.password.changed

Returned data:

FieldType
userstring

user.delete.started

Returned data:

FieldTypeNotes
userstring
resultobjectDelete scheduling result.

result fields:

FieldType
userstring
addressesobject
deleteAfterstring
taskstring

result.addresses fields:

FieldType
deletednumber

user.delete.completed

Returned data:

FieldTypeNotes
userstring
resultobjectFinal deletion summary.

result fields are built step-by-step during task execution and can include:

FieldType
userstring
mailboxesobject
filtersobject
autorepliesobject
addressregisterobject
messagesobject
taskstring

These nested objects typically contain counters like deleted, and on partial failures may include error.

result.mailboxes fields:

FieldType
deletednumber
errorstring

result.filters fields:

FieldType
deletednumber
errorstring

result.autoreplies fields:

FieldType
deletednumber
errorstring

result.addressregister fields:

FieldType
deletednumber
errorstring

result.messages fields:

FieldType
deletednumber
errorstring

user.delete.cancelled

Returned data:

FieldTypeNotes
userstring
resultobjectRestore summary.

result fields can include:

FieldType
userstring
usernamestring
storageUsednumber
tagsarray
deletedstring
addressesobject

addresses may include:

FieldType
recoverednumber
mainstring

Delivery and Retry

Webhook deliveries use HTTP POST. If the endpoint returns a non-2xx status code or the request times out, the delivery is retried with exponential backoff.