Event feed

Poll the same events instead of receiving them. For anyone behind NAT, on a function with no public URL, or who would rather reconcile on a schedule.

GET /email/events

Returns { data, has_more, next_cursor }. Each item in data is byte-for-byte the object a webhook would POST — same envelope, same data — so moving from webhooks to polling does not change your parser. Scope: events:read.

Store next_cursor, sleep, and call again with cursor=<the stored value> to get what happened since. When has_more is false you are caught up.

Deduplicate by id, exactly as with webhooks: the id is derived from the event, so re-reading a page gives you the same ids.

Parameters

ParameterWhat it does
since / untilISO 8601 window over the event time. since is inclusive, until is exclusive.
typesComma-separated event names (message.delivered,message.bounced). An unknown name is refused with the list of valid ones.
cursorOpaque value from next_cursor. An invalid one starts from the beginning instead of failing.
limitPage size. 100 by default, 1000 maximum.

Events come back oldest first, ordered by the moment they happened — polling moves forward in time. Only events with a public name are returned; internal processing states are not part of the contract. How far back the feed reaches is your plan’s retention.