Skip to content
Listener.comDevelopers

Events API

List and fetch the events behind webhooks, for polling, backfills and reconciliation.

1 min read

Every change that produces a webhook also produces an event you can read through the API, whether or not you have an endpoint. Events are kept for 30 days.

Request
GET /v1/eventsList events, newest first.
GET /v1/events/{event_id}One event.
GET /v1/event-typesThe catalog of event types with descriptions and examples. No authentication.

Reading events needs the webhooks:read scope.

Filters#

Parameter
typeOne type (campaign.updated) or a whole domain (campaign.*).
created_gteCreated at or after this time (ISO 8601 or Unix seconds).
created_lteCreated at or before this time (ISO 8601 or Unix seconds).
limit, cursorStandard pagination.

Polling instead of webhooks#

If you cannot receive webhooks (a desktop tool, a locked-down network, a notebook), poll the Events API. Remember the newest created you processed and ask for everything since:

let since = await loadCheckpoint(); // e.g. '2026-10-14T09:00:00Z'

const qs = new URLSearchParams({ created_gte: since, limit: '100' });
const res = await fetch(`https://api.listener.com/v1/events?${qs}`, {
  headers: { Authorization: `Bearer ${process.env.LISTENER_API_KEY}` },
});
const { data } = await res.json();

// Newest first: process oldest first, skip ids you have already seen.
for (const event of data.reverse()) {
  if (await alreadyProcessed(event.id)) continue;
  await handle(event);
  since = event.created;
}
await saveCheckpoint(since);

Use created_gte (inclusive) together with id deduplication, so an event created in the same second as your checkpoint is never skipped. Page through with next_cursor when has_more is true.

Polling every minute or two is plenty: changes made in the apps are detected every five minutes.

Reconciliation#

Even with webhooks, run the same loop on a schedule (for example hourly over the last day). It catches anything your endpoint missed while it was down or disabled.