Skip to main content
The events feed, GET /v1/webhooks/events, returns the events of the last 72 hours that matched a subscription of your account. Use it to catch up after your endpoint was down, and as a scheduled safety net beside your subscriptions. This page says what the feed holds and what it does not, how to walk it, and where its limits are.

What the feed holds

The feed returns one item per event_id, whatever the outcome of the deliveries of that event. Each item is the event exactly as delivered: the same event_id, event_type, created_at, trace_id and data, with data.metadata and data.line_metadata always present. See the envelope. The feed does not hold every change of your account:
  • Only the events that matched an active subscription when they occurred. An event is in the feed only if, at that moment, it matched at least one subscription of your account that was active and not suspended. An account without a subscription has an empty feed.
  • Not what a suspended or inactive subscription missed. Those events were not recorded: the feed cannot recover them, unless another active subscription of your account matched them.
  • Not the events of a deleted subscription. The events that only a deleted subscription received leave the feed.
  • Not the probes. A webhook.test request never appears in the feed.
  • Not beyond 72 hours. An event leaves the feed 72 hours after its last delivery.
The feed is therefore not a replacement for a subscription, and not a complete history. For the changes that produce no event, see What events do not announce. The operation accepts an account API key. A line-scoped key is not restricted here: it reads the events of every line of the account, message content included. Items can carry personal data: message text, handles, contact names and attachment file names. Do not copy them into logs, tickets or other tools.

Parameters

since and until are timestamps in ISO 8601, in UTC, ending with Z, such as 2026-10-08T12:00:00Z. An offset such as +02:00, a missing Z or a date without a time returns 400 validation_failed. A since later than until returns an empty page.

Walking the feed

Items are returned newest first. There is no oldest-first order.
See Cursors for the rules shared by the list operations.

Unknown event types

Ignore response fields, enum values and event types you do not know. When the feed returns an event type your code does not handle, count the event as processed and skip it: do not stop the walk.

A scheduled catch-up poll

Your subscriptions are the main path. A poll on a schedule is a safety net for the deliveries your endpoint did not process: an outage of your endpoint, a deployment, a request your code refused.
1

Note the time

Note the time the poll starts, from a clock synchronized with UTC.
2

Walk the window

Read the feed with since set to the start time of the previous poll minus an overlap, such as 10 minutes. Walk every page until has_more is false. The overlap absorbs a difference between your clock and the clock of iSnap. It costs nothing, because you deduplicate.
3

Process what you have not seen

Deduplicate on event_id, against the same store as your receiver. The feed is newest first: process the oldest event first. Order events by the timestamps inside data, not by arrival.
4

Store the start time

Store the time you noted, once the walk is complete. It is the since of the next poll.
The limits of this safety net:
  • It recovers only what the feed holds. It does not recover the events of a period in which your subscription was suspended or inactive, nor an event that was lost before it was recorded, nor a change that produces no event. After such a period, reconcile from the resource operations.
  • It needs an active subscription that matches the events you want. With no subscription, the feed is empty.
  • It reaches back 72 hours. If the poll stops for longer, the older events are gone.
The samples run one poll. Run them on your scheduler, and keep the processed event ids and the start time of the previous poll in your own storage. The iterator of the SDK does not expose the cursor: an interrupted walk starts again from the first page. The feed is a read. Retry a 429 after Retry-After seconds. Retry a 500 or a 503 up to 2 times, with exponential backoff. Do not retry any other 4xx: fix the request. The SDK applies its own retries: see SDK errors and retries.