Skip to main content
GET /v3/organizations/{orgId}/sessions/{sessionId}/events returns a Session’s activity in pages. It is a poll, not a stream: each call returns the events after a cursor, and with wait_ms it waits for the next one.

What you will have

  • A loop that reads every event exactly once in transcript order.
  • A rule for handling the same event coming back on a later page.

Prerequisites

Create or open a Session, and have an API key with sessions:read. See Build a chat UI on the API.

The cursor

Start with after_seq=0. Each response returns:
  • items: the events after the cursor, in ascending seq.
  • next_seq: the last item’s seq, or the same cursor when items is empty.
  • session: the current status (running, exit, error or suspended) and outcome.
Pass next_seq as the next after_seq. Stop when a page’s items is empty and session.status is no longer running. Add wait_ms (for example 20000) so an empty page waits for the next event instead of returning at once.

The same event can come back

A streamed event (a reply, reasoning, or a tool’s live output) keeps its id. Each time its content grows, it returns with a higher seq. So a poller can receive one id on more than one page. Keep the copy of each id with the highest seq. That copy has the most complete content.

Order by position, not seq

seq is a delivery cursor. It is not the order things happened in. Sort by position to get the transcript:
  • position is the seq an event first appeared at.
  • It never changes for an event, and no two events in a Session share one.
A streamed reply can therefore show a higher seq than an event that happened after it. Sorting by seq would put it in the wrong place.

Numbers are not counts

seq and position jump by about 4.29 billion (2^32) when a follow-up, a retry, or a machine change starts a new attempt. They also have gaps where an event is hidden. Compare them and sort with them. Do not count with them or show them to a person.

Event types

Each event has a type: Without sessions:debug, data carries a fixed set of fields (for example tool, input, content, is_error, duration_ms). An owner or admin with sessions:debug gets the full diagnostic projection. To read only the conversation, add view=conversation. It returns only assistant, reasoning, tool_use and tool_result events, and it does not move the cursor.

Working code

The chat UI sample implements this: a Map keyed by id that keeps the highest seq, a cursor loop with wait_ms, and a sort by position.

Check it works

Run the sample with a Session that answers one question. The reply prints once, in order, even though the poll saw the reply more than once while it grew.