Skip to content

The email object

This page documents the email object's fields and the lifecycle a message moves through after it's accepted.

Fields

The object returned by GET /v1/emails/{id}.

A send returns only { object, id } — echoing the whole message back would just hand you a copy of what you sent. Fetch the object when you want it.

FieldTypeDescription
objectstringAlways "email".
idstringMessage identifier — a UUID. Stable for the life of the message; used in the dashboard and in webhook events.
message_idstring | nullThe RFC Message-ID handed to the recipient's server — the id that appears in the recipient's headers. null until the message is actually sent. Distinct from id.
tostring[]Recipients, always an array.
fromstringThe sender address, as submitted.
created_atstringISO 8601 timestamp of when SendGrail accepted the request.
subjectstringThe subject line.
htmlstring | nullThe HTML body, or null if the message was sent text-only.
textstring | nullThe plain-text body, or null if the message was sent HTML-only.
bccstring[]Blind-carbon-copy recipients — [] when not supplied.
ccstring[]Carbon-copy recipients — [] when not supplied.
reply_tostring[]Reply-To addresses — [] when not supplied.
headersobject | nullThe custom headers object, or null when none were supplied.
last_eventstringThe message's current lifecycle state — see below.
scheduled_atstring | nullISO 8601 send time for a scheduled message; null for immediate sends.
tagsarrayThe { name, value } labels sent with the message; [] when none were supplied.
suppressed_reasonstringOnly present when last_event is suppressed — one of bounce, complaint, manual, unsubscribe.
attachmentsarrayPresent when the message carried files: filename, content_type and size for each. Never the bytes — download them with List attachments.

POST /v1/emails/batch returns a trimmed object per item — id and last_event (plus suppressed_reason when relevant).

GET /v1/emails omits html and text: a page of a hundred bodies would be megabytes you didn't ask for.

Lifecycle

last_event is one value at a time. The send response gives you the initial state; it changes as delivery progresses, and you observe later changes through webhooks or the dashboard.

ValueStageMeaning
queuedinitialAccepted and waiting to be handed to AWS SES — usually under a second.
scheduledinitialHeld until scheduled_at. Becomes queued at the due time. Can still be rescheduled or cancelled.
cancelledterminalA scheduled message you cancelled before it went out. Nothing was sent.
suppressedinitial · terminalA recipient was on your suppression list. The message was recorded but never sent.
sentafter dispatchHanded to AWS SES for delivery.
delayedafter dispatchAWS SES couldn't deliver yet (recipient mailbox full, greylisting, a transient error) and is retrying. Resolves to delivered, or bounce once SES gives up.
deliveredterminalThe recipient's mail server accepted the message. Also set when an open or click is recorded, since engagement proves delivery.
bounceterminalThe message was returned as undeliverable.
complaintterminalThe recipient marked the message as spam.
failedterminalSendGrail could not send the message (validation or AWS-side error).
rejectedterminalAWS SES dropped the message before delivery (its own suppression list, content scan, size limit).

Typical successful path:

queued ──▶ sent ──▶ delivered

A scheduled message begins one step earlier:

scheduled ──▶ queued ──▶ sent ──▶ delivered

A slow recipient server passes through delayed before settling:

queued ──▶ sent ──▶ delayed ──▶ delivered

And the unhappy endings:

queued ──▶ sent ──▶ bounce
queued ──▶ sent ──▶ complaint
queued ──▶ failed

last_event vs. webhook event names

last_event carries bounce and complaint. The matching webhook events are named email.bounced and email.complained — past tense. Same lifecycle event, two naming conventions.

Observing changes

The token API does not have a "retrieve email" endpoint — once a message is accepted, watch its progress one of two ways:

  • Webhooks — SendGrail posts an event to your URL each time a tracked message changes state. This is the right choice for programmatic reactions.
  • Dashboard — the Emails view shows every message with its current state and a full event timeline.

Transactional email on your own domain.