> ## Documentation Index
> Fetch the complete documentation index at: https://ara-90a60a07.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Events reference

> How to read a Session's events from GET /events: the cursor, long polling, deduplication by id, and ordering by position.

`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](https://ara-90a60a07.mintlify.site/docs/build/chat-ui-api.md).

## 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.

```text theme={null}
GET .../events?after_seq=0&wait_ms=20000   -> items, next_seq=57, status=running
GET .../events?after_seq=57&wait_ms=20000  -> items=[], next_seq=57, status=running   (waited)
GET .../events?after_seq=57&wait_ms=20000  -> items=[...], next_seq=61, status=exit
```

## 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`:

| Type | Content |
| - | - |
| `status` | Lifecycle changes. `text` and `data` are null without `sessions:debug`. |
| `assistant` | A reply the agent wrote. `text` holds it. |
| `reasoning` | The agent's reasoning, when the model shares it. |
| `tool_use` | A tool call, with its input in `data`. |
| `tool_result` | A tool's result, with its output in `data`. |

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](https://ara-90a60a07.mintlify.site/docs/build/chat-ui-api.md) 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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.