Appearance
Webhook events
This is the reference for the events SendGrail delivers to your webhooks. For setting one up and verifying signatures, see the Webhooks guide.
Envelope
Every webhook request body has the same three top-level fields:
json
{
"type": "email.delivered",
"created_at": "2026-05-21T21:02:38+00:00",
"data": { }
}| Field | Description |
|---|---|
type | The event type — one of the values below. |
created_at | ISO 8601 time the event was generated. |
data | Event-specific payload. Email events and domain events have different data shapes. |
The event type is also in the Sendgrail-Event-Type request header.
Email events
Fired as a message moves through its lifecycle.
| Type | Fired when |
|---|---|
email.sent | SendGrail handed the message to AWS SES. |
email.delivery_delayed | The recipient's server temporarily deferred the message; SES keeps retrying. |
email.delivered | The recipient's mail server accepted the message. |
email.opened | The recipient opened the message (requires open tracking). |
email.clicked | The recipient clicked a tracked link (requires click tracking). |
email.bounced | The message was returned as undeliverable. |
email.complained | The recipient marked the message as spam. |
email.failed | SendGrail could not send the message. |
email.rejected | AWS SES dropped the message before delivery (e.g. its own suppression list, a content scan, or a size limit). |
email.suppressed | A send was blocked because a recipient was on your suppression list. |
email.scheduled | Reserved — a scheduled send is queued for a future time. Subscribable but not yet emitted. |
email.received | Reserved — an inbound message arrived. Subscribable but not yet emitted. |
Email event data
json
{
"type": "email.delivered",
"created_at": "2026-05-21T21:02:38+00:00",
"data": {
"email_id": "a7e2b91c-4d63-4f8a-b0e5-1c9d3f6a2b74",
"from": "Acme <hello@example.com>",
"to": ["recipient@example.org"],
"subject": "Your receipt",
"status": "delivered",
"sent_at": "2026-05-21T21:02:36+00:00"
}
}| Field | Description |
|---|---|
email_id | The message UUID from the original send response. Use it to correlate the event. |
from | Sender address. |
to | Recipient addresses. |
cc | Carbon-copy recipients — present only when the message had cc. |
bcc | Blind-carbon-copy recipients — present only when the message had bcc. |
subject | Message subject. |
status | The message status at the time of the event. |
sent_at | When the message was sent, or null if it hadn't been sent yet. |
tags | The tags supplied at send time — present only when non-empty. Useful for routing events to downstream handlers. |
detail | Optional. Extra context for the event — see below. |
The detail field
Some events include a detail object:
email.bounced/email.complained— the relevant sub-payload from AWS SES, when available (bounce type, diagnostic information, and similar).email.suppressed— the suppressionreasonthat blocked the send:
json
{
"type": "email.suppressed",
"created_at": "2026-05-21T08:12:32+00:00",
"data": {
"email_id": "3f5c9a1e-8b2d-4e6f-9a1c-7d4b2e8f0a63",
"from": "Acme <hello@example.com>",
"to": ["bounced@example.org"],
"subject": "Your receipt",
"status": "suppressed",
"sent_at": null,
"detail": { "reason": "bounce" }
}
}Domain events
Fired when a domain on your account changes.
| Type | Fired when |
|---|---|
domain.created | A domain was added to your account. |
domain.updated | A domain's status changed — for example, it became verified. |
domain.deleted | A domain was removed from your account. |
Domain event data
json
{
"type": "domain.updated",
"created_at": "2026-05-21T09:30:00+00:00",
"data": {
"domain_id": 12,
"name": "mail.example.com",
"region": "us-east-1",
"status": "verified",
"verified_at": "2026-05-21T09:30:00+00:00"
}
}| Field | Description |
|---|---|
domain_id | The domain's numeric id. |
name | The domain name. |
region | The AWS region the domain sends from. |
status | pending, verified or failed. |
verified_at | When the domain verified, or null if it isn't verified. |
Contact events
| Type | Fired when |
|---|---|
contact.created | A contact was added to your audience. |
contact.updated | A contact's details or subscription changed. |
contact.deleted | A contact was removed. |
Contact event data
json
{
"type": "contact.created",
"created_at": "2026-05-21T09:30:00+00:00",
"data": {
"contact_id": "contact_9fQ2xL7mA0bWpK3sYd8V",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Doe",
"subscribed": true
}
}| Field | Description |
|---|---|
contact_id | The contact's public id. |
email | The contact's email address. |
first_name / last_name | Present when set, otherwise null. |
subscribed | Whether the contact is currently subscribed. |
Choosing events
You select which event types a webhook receives when you create or edit it. Subscribe only to what you act on — a webhook that just records deliveries doesn't need domain.*, and one that watches for problems may only want email.bounced, email.complained and email.failed.
Not included
Open and click events are not delivered over webhooks — they're visible only in the dashboard. See Open & click tracking.