Skip to content

Webhook events

Every event has the same envelope. data always holds the four fields below, plus the ones of its type.

{
"type": "email.bounced",
"timestamp": "2026-09-30T12:00:03.000Z",
"data": {
"email_id": "em_4b9b3c1f0a2e7d5c9e8f1a2b",
"from": "hello@example.com",
"recipient": "old.address@example.org",
"subject": "Your September invoice",
"bounce": {
"type": "hard",
"response": "550 5.1.1 User unknown",
"asynchronous": false,
"reporting_mta": null
},
"suppressed": true
}
}
Field Type Description
type string One of the types below.
timestamp string When the event happened, ISO 8601 in UTC.
data.email_id string The id of the email.
data.from string The sender address.
data.recipient string The recipient this event is about. An email to three recipients produces three sets of events.
data.subject string The subject of the email.

Emails sent with a test key produce no event.

The recipient’s mail server accepted the email.

Field Type Description
data.smtp.host string or null The server that accepted it.
data.smtp.response string Its answer, such as 250 2.0.0 OK.

The recipient’s server refused the email for now, or sent a delay notice later. MailPush keeps trying for 72 hours.

Field Type Description
data.attempt number or null The attempt that was refused. null for a delay notice.
data.next_attempt_at string or null When the next attempt is planned.
data.smtp object Present for a refusal during sending: host and response.
data.report object Present for a delay notice: status, diagnostic and reporting_mta.

The recipient’s server refused the email permanently, during sending or in a bounce message received afterwards.

Field Type Description
data.bounce.type string hard (the address does not exist), mailbox_full, policy (the server blocks the sender or the content), message_too_large or unknown.
data.bounce.response string The server’s answer.
data.bounce.asynchronous boolean true when the bounce arrived after the server first accepted the email.
data.bounce.reporting_mta string or null The server that reported an asynchronous bounce.
data.suppressed boolean true for a hard bounce: the address joins your suppression list.

The recipient reported the email as spam, and their mailbox provider told MailPush.

Field Type Description
data.complaint.feedback_type string Usually abuse.
data.complaint.user_agent string or null The provider’s reporting system.
data.suppressed boolean Always true: the address joins your suppression list.

Not every provider reports complaints. Gmail does not send them per recipient.

MailPush could not send the email to this recipient: the email could not be signed, or the server kept refusing it temporarily for 72 hours.

Field Type Description
data.reason string Why it failed.

The email was not sent to this recipient because the address is on your account’s suppression list.

Field Type Description
data.suppression.reason string hard_bounce or complaint.

The tracking image of the email was loaded. Sent only when the email tracks opens, at most once an hour per recipient.

Field Type Description
data.machine boolean true when software loaded the image rather than the recipient. Leave those out of your statistics.
data.machine_reason string or null apple_privacy (Apple Mail’s prefetch) or scanner. null when machine is false.

A tracked link of the email was followed. Sent only when the email tracks clicks, at most once a minute per link.

Field Type Description
data.url string The original address of the link.
data.machine boolean true when a security scanner or a robot followed the link.
data.machine_reason string or null scanner, too_fast (less than 5 seconds after delivery) or burst (another link followed within 1 second). null when machine is false.

A click by the recipient also dates opened_at in GET /v1/emails/:id, but sends no email.opened event.

Sent when you click the test button on an endpoint’s page.

Field Type Description
data.webhook_id string The id of the endpoint.
data.message string A fixed sentence.