---
title: "Stream events (SSE)"
method: GET
path: "/v1/events/stream"
tags: ["Events"]
---

# Stream events (SSE)

`GET /v1/events/stream`

## Request

- Base URL: `https://api.mails.ai`
- URL: `https://api.mails.ai/v1/events/stream`
- Auth: HTTP bearer

**Requires scope:** `read`. Server-Sent Events live tail. Each event is a frame `id: <event_id>`, `event: <type>`, `data: <json>`. The stream also says where it is, in an `id:` line with no data (`id: evt_…~<number>`), when the connection opens and after each batch of events. That is its position, and what to resume from: a browser's EventSource sends it back as `Last-Event-ID` by itself, and any other client passes the last one it read as `?since=`. Without `since` or a `Last-Event-ID` header the stream starts at the newest event: it sends what happens from then on, never the workspace's history; `since=0` replays the whole history first. The connection self-closes after ~50s; reconnect to continue. Events arrive in id order, except one whose row was written late: it is sent after newer ones rather than skipped, and a reconnect from the position still gets it. Delivery is at least once: an event can arrive a second time after a reconnect, so de-duplicate by its `id`. Resuming from a bare event id (`since=evt_…`) starts after that id: it does not get an event written late with a smaller id, and after such an event it sends the newer ones again.

## Query parameters

- `since` string
- `event_types` string

## Response `200`

An SSE stream (`text/event-stream`).

## Other responses

- `401`: Missing or invalid API key.
- `403`: The API key lacks the required scope (`insufficient_scope`), or the token belongs to an app connected by sign-in and this operation is closed to connected apps (`connected_app_not_allowed`).
- `500`: Internal server error.

---

[API](https://skmtc.dev/mails/apis/mails-ai-api.md) · [All operations](https://skmtc.dev/mails/apis/mails-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mails/apis/mails-ai-api/revisions/4d4930a8c33b?raw)
