import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const stream = client.events.stream({
onEvent: (event) => console.log(event.type, event.id),
});
// later: stream.abort();from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
client.stream_events(
on_event=lambda e: print(e["type"], e["id"]),
)curl 'https://api.mails.ai/v1/events/stream' \
-H "Authorization: Bearer $MAILS_API_KEY"200 text/event-stream
An SSE stream (text/event-stream).200 An SSE stream (text/event-stream).
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.Stream events (SSE)
import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const stream = client.events.stream({
onEvent: (event) => console.log(event.type, event.id),
});
// later: stream.abort();from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
client.stream_events(
on_event=lambda e: print(e["type"], e["id"]),
)curl 'https://api.mails.ai/v1/events/stream' \
-H "Authorization: Bearer $MAILS_API_KEY"200 text/event-stream
An SSE stream (text/event-stream).200 An SSE stream (text/event-stream).
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.Query Parameters
Where to resume: the last position the stream gave (evt_…~<number>), or an event id (evt_…) to start after that id. Not a time. 0 replays the whole history. Falls back to the Last-Event-ID header; with neither, or empty, the stream starts at the newest event.
Comma-separated event-type filter. * for all.
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.
Was this page helpful?