---
title: "List events for an email message"
method: GET
path: "/email_messages/{email_id}/events"
tags: ["Email Messages"]
---

# List events for an email message

`GET /email_messages/{email_id}/events`

## Request

- Base URL: `https://api.telnyx.com/v2`
- URL: `https://api.telnyx.com/v2/email_messages/{email_id}/events`
- Auth: HTTP bearer

Lists events for a single message sorted oldest first by `occurred_at asc, id asc`.
The legacy `/v2/emails/{id}/events` GET route is a backward-compatible alias.

For compatibility, each event carries the legacy
customer-visible `event_type` (`email.`-prefixed), the additive
`canonical_event_type` (`email.`-prefixed), and the deprecated
`type` duplicate — whose value keeps the exact legacy format:
the bare stored event name, never `email.`-prefixed. Gateway
rejections render `email.failed` + canonical `email.gw_reject`; MTA
expirations render `email.bounced` + canonical `email.expired`;
every unchanged outcome carries identical `event_type` and
`canonical_event_type` values (and `type` keeps the stored name).

## Path parameters

- `email_id` string, uuid, required

## Query parameters

- `page_size` integer
- `page_cursor` string

## Response `200`

Paginated list of message events.

- MessageEventListResponse
  - `data` MessageEvent[], required
    - `type` 'queued' | 'deferred' | 'scheduled' | 'cancelled' | 'sandbox' | 'sending' | 'sent' | 'failed' | 'delivered' | 'bounced' | 'complained' | 'suppressed' | 'rejected' | 'opened' | 'clicked' | 'unsubscribed' | 'daily_limit_exceeded' | 'scan_deferred' | 'quarantined' | 'quarantine_released' | 'quarantine_release_dispatched' | 'quarantine_rejected' | 'quarantine_expired' | 'gw_reject' | 'injection_timeout' | 'expired', required: Bare stored event names returned by message history. In addition to the normal send and delivery lifecycle, polling can expose suppression, scan, and quarantine lifecycle rows. Sharp canonical names gw_reject, injection_timeout, and expired distinguish gateway rejection, ambiguous injection timeout, and MTA expiration. The failed and bounced names remain valid for system/admin failures and hard bounces respectively. Existing stored rows retain their original names.
    - `event_type` string, required: Legacy customer-visible event name, prefixed with `email.`. Gateway rejections render `email.failed`; MTA expirations render `email.bounced`. Webhook subscription allowlists match the legacy name.
    - `canonical_event_type` string, required: Additive canonical outcome name, prefixed with `email.`. Gateway rejection is `email.gw_reject`, ambiguous injection timeout is `email.injection_timeout`, and MTA expiration is `email.expired`. Unchanged outcomes retain their names. Existing stored rows are translated only when recorded payload evidence proves the outcome; a legacy failed row is not guessed or sharpened.
    - `occurred_at` string, date-time, required
    - `payload` object
  - `meta` EmailPaginationMeta, required
    - `page_size` integer, required
    - `page_cursor` string: Cursor for the next page, when more results are available.

## Other responses

- `401`: Not authorized (10006).
- `404`: Resource not found (10001).

## Changes

- **2026-10-15** `a72569d69430`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/team-telnyx/apis/telnyx-api/changes/email_messages/:email_id/events/get.md)

---

[API](https://skmtc.dev/team-telnyx/apis/telnyx-api.md) - [All operations](https://skmtc.dev/team-telnyx/apis/telnyx-api/llms.txt) - [OpenAPI document](https://skmtc.dev/team-telnyx/apis/telnyx-api/revisions/0f17b8167873?raw)
