Event reference
Every webhook event type and the fields in its data.
Every delivery body is { type, created_at, data }. Subscribe an endpoint to the types you need; the Node SDK's verifyWebhook returns the event typed by type.
Endpoints in the Resend payload format receive only the events Resend also has (most email.* events, and domain.updated). The account.* events, including the usage alerts, go only to endpoints in the PadiMail format that subscribe to them.
Fields on every email event
Every email.* event has these in data, plus the fields listed under its type.
| Field | Type |
|---|---|
email_id | string |
recipient_id | string | null |
to | string | null |
from | string |
subject | string | null |
tags | object[] |
stream | "transactional" | "marketing" |
email.queued
We accepted the email and it's waiting its turn to send.
No fields beyond the common ones.
email.scheduled
The email was accepted with a scheduled_at time.
| Field | Type |
|---|---|
scheduled_at | string |
email.deferred
The email is waiting for a sending limit to open up. deferred_until is the earliest expected send time.
| Field | Type |
|---|---|
reason | "daily_limit" | "monthly_limit" | "no_credits" | "handle_warmup" | "sandbox_limit" |
deferred_until | string | null |
email.sent
We handed the email over for delivery. sent_via says whether it went through PadiMail or your connected Gmail.
| Field | Type |
|---|---|
sent_via | "padimail" | "gmail_fallback" |
email.delivered
The receiving server accepted the email.
| Field | Type |
|---|---|
smtp_response | string | null |
email.delivery_delayed
The receiving server deferred the email. We keep trying until it's delivered or bounces.
| Field | Type |
|---|---|
reason | string | null |
next_attempt_at | string | null |
email.bounced
The email couldn't be delivered. A hard bounce also suppresses the address.
| Field | Type |
|---|---|
bounce | { type, sub_type, diagnostic } |
email.complained
The recipient marked the email as spam. The address is suppressed.
| Field | Type |
|---|---|
feedback_type | string | null |
email.opened
The recipient opened the email (only with open tracking on; approximate because of mail privacy proxies).
| Field | Type |
|---|---|
user_agent | string | null |
ip_country | string | null |
email.clicked
The recipient clicked a link (only with click tracking on).
| Field | Type |
|---|---|
url | string |
user_agent | string | null |
email.suppressed
We didn't send to this recipient because the address is on your suppression list.
| Field | Type |
|---|---|
reason | "bounce" | "complaint" | "unsubscribe" | "manual" | "invalid" |
email.held
Content scanning held the email for review.
| Field | Type |
|---|---|
reason | string |
email.released
A held email was approved and is sending.
| Field | Type |
|---|---|
reason | string |
email.rejected
Content scanning or a review blocked the email. reason gives the general category.
| Field | Type |
|---|---|
reason | string |
email.failed
The email couldn't be sent, for example because it waited longer than 30 days.
| Field | Type |
|---|---|
reason | string |
email.canceled
The email was canceled before it was sent.
No fields beyond the common ones.
domain.verified
All the required DNS records for a domain were found.
| Field | Type |
|---|---|
domain_id | string |
name | string |
domain.failed
A domain's records weren't found within 72 hours, or stopped verifying.
| Field | Type |
|---|---|
domain_id | string |
name | string |
account.paused
Sending was paused, for example by an automatic brake on bounces or complaints.
| Field | Type |
|---|---|
reason | string |
account.resumed
Sending was resumed.
| Field | Type |
|---|---|
reason | string |
account.quota_reached
A daily, monthly, credit, warm-up or sandbox limit was reached. Sent once per limit window; waiting counts the emails waiting.
| Field | Type |
|---|---|
limit | "daily_limit" | "monthly_limit" | "no_credits" | "handle_warmup" | "sandbox_limit" |
resets_at | string | null |
waiting | integer |
account.usage_threshold
80% or 95% of the daily or monthly sending limit is used. Sent once per threshold and window, so you can upgrade or slow down before the limit.
| Field | Type |
|---|---|
alert_id | string |
window | "daily" | "monthly" |
threshold | integer |
used | integer |
limit | integer |
resets_at | string |
account.usage_spike
Sending in the last hour jumped far above normal (more than 5 times the hourly average of the last 7 days, and at least 200 emails), or bounce or complaint rates went over the warning levels. Sending isn't stopped; check for a bug or a leaked key.
| Field | Type |
|---|---|
alert_id | string |
reason | "volume" | "bounce_rate" | "complaint_rate" |
accepted_last_hour | integer |
baseline_per_hour | number | null |
delivered_last_hour | integer |
bounce_rate | number | null |
complaint_rate | number | null |
top_api_key_id | string | null |