Skip to main content
GET
/
v1
/
identities
/
{handle}
/
events
Pull events
curl --request GET \
  --url https://api.inboxbase.ai/v1/identities/{handle}/events \
  --header 'Authorization: Bearer <token>'
{
  "identity": "<string>",
  "events": [
    {
      "seq": 123,
      "id": "<string>",
      "ts": 123,
      "data": {},
      "convId": "<string>",
      "tsIso": "2023-11-07T05:31:56Z"
    }
  ],
  "cursor": 123,
  "hasMore": true
}
Same data as the webhooks stream, served pull-mode for environments that can’t expose a public URL — agents, MCP servers, dev environments behind a firewall. Each event carries the same seq and id as the matching webhook delivery, so you can mix push and pull and dedup trivially.

The cursor

seq is a monotonic per-identity integer. It strictly increases and is never reused. Pass cursor from the response back as since on the next call:
let cursor = 0;
while (running) {
  const r = await fetch(
    `https://api.inboxbase.ai/v1/identities/${handle}/events?since=${cursor}&timeoutMs=25000`,
    { headers: { Authorization: `Bearer ${KEY}` } },
  ).then((r) => r.json());
  for (const ev of r.events) await handle(ev);
  cursor = r.cursor;
}
The same event is never returned twice on the same connection.

Long-poll

timeoutMs is the long-poll window, capped at 25 seconds. With long-poll on, the call returns as soon as a new event lands; if nothing arrives within the window, you get an empty response and you call again immediately. The loop above doesn’t busy-wait — the long-poll absorbs idle time.

When hasMore: true

If your limit was smaller than the number of events available beyond your since cursor, hasMore is true on the response. Loop without long-polling until hasMore: false, then resume long-polling from there.

Recovery from missed webhooks

If you also use webhooks and your receiver was down, this endpoint is how you backfill. Walk from the last seq you persisted; both delivery modes share the cursor.
let cursor = await db.getLastWebhookSeq(handle);
for (;;) {
  const r = await fetch(
    `https://api.inboxbase.ai/v1/identities/${handle}/events?since=${cursor}&limit=200`,
    { headers: { Authorization: `Bearer ${KEY}` } },
  ).then((r) => r.json());
  for (const ev of r.events) await handle(ev);
  cursor = r.cursor;
  if (!r.hasMore) break;
}
await db.setLastWebhookSeq(handle, cursor);
See Reacting to replies for the full push/pull pattern.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

handle
string
required

Identity handle, URL-encoded.

Example:

"alice.acme@inboxbase.ai"

Query Parameters

since
integer<int64>
default:0

Cursor. Returns events with seq > since. Default 0 walks the whole log.

types
string

CSV of event types to filter on.

Example:

"email.replied,email.no_reply"

limit
integer
default:50

Maximum events per response, 1..200.

Required range: 1 <= x <= 200
timeoutMs
integer
default:0

Long-poll window. Hold the connection up to this many milliseconds for new events when the response would otherwise be empty. Capped at 25,000.

Required range: 0 <= x <= 25000

Response

Events page.

identity
string
required
events
object[]
required
cursor
integer<int64>
required

Last seq returned. Pass back as since on the next call.

hasMore
boolean
required

true when more events were available beyond limit.