Events & Lifecycle
Understand how Postject tracks the delivery lifecycle of every email from queue to inbox.
Event Lifecycle
Every email sent through Postject generates a series of events as it moves through the delivery pipeline. The following diagram shows the possible paths a message can take:
Queued → Sent → Delivered
↘ Bounced
↘ Complained
↘ Rejected
↘ Failed
Supplementary: Opened, ClickedThe happy path is Queued, then Sent, then Delivered. At any point after being sent, a message may instead bounce, receive a complaint, or fail. If a message is rejected before it ever leaves Postject (e.g., suppressed address), it moves directly to Rejected without a Sent event. Supplementary events like Opened and Clicked may occur after delivery but do not change the message status.
Event Types
The following table describes every event type that Postject tracks:
| Event Type | Description |
|---|---|
sent | The message was successfully transmitted to the recipient's mail server via Amazon SES. |
delivered | The recipient's mail server confirmed successful receipt of the message. |
bounced | The message was rejected by the recipient's mail server. Metadata includes the bounce type (hard or soft) and diagnostic code. |
complained | The recipient reported the email as spam. The address is automatically added to the suppression list for the stream. |
rejected | The message was rejected before sending. Common reasons: suppressed address, unverified sender identity, or account-level sending limits. |
failed | The message could not be sent due to an internal processing error. The event metadata contains diagnostic information. |
opened | The recipient opened the email. Tracked via an invisible pixel embedded in the HTML. May not fire if images are blocked. |
clicked | The recipient clicked a link in the email. Tracked via link wrapping. Metadata includes the original URL that was clicked. |
SES Integration
Postject uses Amazon SES as its underlying mail transport. Delivery events are received via Amazon SNS notifications, which Postject processes and maps to its own event types in real time.
The following table shows how SES event types map to Postject event types:
| Amazon SES Event | Postject Event |
|---|---|
Send | sent |
Delivery | delivered |
Bounce | bounced |
Complaint | complained |
Reject | rejected |
Rendering Failure | failed |
Open | opened |
Click | clicked |
Processing Latency
SES notifications are typically received within seconds of the event occurring. Postject processes these notifications in real time and updates the message status and event history immediately. Webhook notifications for these events are dispatched as soon as processing is complete.
Terminal vs Supplementary Events
Postject categorizes events into two groups based on how they affect the message status:
Terminal Events
Terminal events update the message's status field to reflect the final delivery outcome. Once a terminal event occurs, the message status is considered resolved.
deliveredbouncedcomplainedrejectedfailedSupplementary Events
Supplementary events are tracked in the message's event history but do not change the message status. These events provide engagement data and are available via the API and webhooks.
openedclickedFor example, a message with status delivered may later receive opened and clicked events, but its status remains delivered.
Get Stream Events
Returns the most recent events for a given message stream, ordered by timestamp (newest first). Each event includes its parent message object for context. Returns the last 50 events by default. Requires JWT Bearer authentication.
[
{
"id": "evt_m3n4o5p6q7r8",
"type": "opened",
"timestamp": "2025-07-15T15:10:22.000Z",
"metadata": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
"ipAddress": "203.0.113.42"
},
"message": {
"id": "msg_01hy4z8k2a3b4c5d",
"to": "alice@example.com",
"subject": "Your order has been shipped",
"status": "delivered"
}
},
{
"id": "evt_g7h8i9j0k1l2",
"type": "delivered",
"timestamp": "2025-07-15T14:32:03.789Z",
"metadata": {
"smtpResponse": "250 2.0.0 OK",
"processingTimeMs": 2333
},
"message": {
"id": "msg_01hy4z8k2a3b4c5d",
"to": "alice@example.com",
"subject": "Your order has been shipped",
"status": "delivered"
}
},
{
"id": "evt_s9t0u1v2w3x4",
"type": "bounced",
"timestamp": "2025-07-15T14:28:02.100Z",
"metadata": {
"bounceType": "Permanent",
"bounceSubType": "General",
"diagnosticCode": "smtp; 550 5.1.1 The email account does not exist"
},
"message": {
"id": "msg_02iz5a9l3b4c5d6e",
"to": "invalid@example.com",
"subject": "Password reset request",
"status": "bounced"
}
},
{
"id": "evt_a1b2c3d4e5f6",
"type": "sent",
"timestamp": "2025-07-15T14:28:00.892Z",
"metadata": {
"sesMessageId": "010201900a1b2c3d-4e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b-000000"
},
"message": {
"id": "msg_02iz5a9l3b4c5d6e",
"to": "invalid@example.com",
"subject": "Password reset request",
"status": "bounced"
}
}
]