> For the complete documentation index, see [llms.txt](https://docs.concurrence.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.concurrence.com/developer-guide/platform-api/platform-api/zoom-session-events.md).

# Zoom Session Events (SSE)

Real-time Server-Sent Event stream for live Zoom session bot status and transcript updates.

The Scribe API exposes a live event stream for active Zoom sessions. The stream delivers bot lifecycle updates and transcript segments in real time so the client does not need to poll.

## Opening the Stream

```
GET /sessions/{session_id}/events
```

The endpoint requires the same provider-JWT authentication used by other Scribe session endpoints. Because an `Authorization` header is required, use `fetch` streaming rather than the browser `EventSource` API.

The response content type is `text/event-stream`.

### Path Parameters

| Parameter    | Type          | Description                                                                                           |
| ------------ | ------------- | ----------------------------------------------------------------------------------------------------- |
| `session_id` | string (UUID) | The session to stream events for. Must be an active Zoom session owned by the authenticated provider. |

### Request Headers

| Header          | Required | Description                                                                                                                                         |
| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Authorization` | Yes      | Provider JWT bearer token.                                                                                                                          |
| `Last-Event-ID` | No       | The `id` of the last event the client received. When present, the server replays recent events from that offset so no frames are lost on reconnect. |

## Event Types

Each SSE frame is delivered as `event: <type>\ndata: <json>\n\n`. Frames include an `id` field that clients should store for reconnect replay.

| Event                  | Description                                                                                                                                         | Terminal                                |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| `bot_status`           | Bot lifecycle state change.                                                                                                                         | Yes, when `state` is `done` or `error`. |
| `transcript_segment`   | A finalized transcript utterance.                                                                                                                   | No                                      |
| `interim_transcript`   | An in-progress (not yet final) transcript hypothesis for the same ordinal. Replaced by the subsequent `transcript_segment` with the same `ordinal`. | No                                      |
| `transcript_finalized` | Emitted once when the full transcript is complete. Empty payload (`{}`).                                                                            | No                                      |
| `ping`                 | Keepalive frame with an empty payload (`{}`).                                                                                                       | No                                      |

### `bot_status` Payload

| Field    | Type           | Description                                                                                                                                        |
| -------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state`  | string         | One of: `joining`, `waiting_for_host`, `waiting_for_participant`, `playing_disclosure`, `listening`, `paused`, `idle`, `leaving`, `done`, `error`. |
| `reason` | string or null | A machine-readable reason on non-happy-path transitions (e.g. `join_timeout`, `upstream_unavailable`).                                             |

When `state` is `done` or `error`, the stream closes immediately after the frame. Clients should stop reconnecting.

### `transcript_segment` / `interim_transcript` Payload

| Field       | Type           | Description                                                                                    |
| ----------- | -------------- | ---------------------------------------------------------------------------------------------- |
| `ordinal`   | integer        | Monotonically increasing segment index. Use this to deduplicate or replace interim with final. |
| `speaker`   | string or null | Speaker label, when available.                                                                 |
| `text`      | string         | The transcript text.                                                                           |
| `timestamp` | string         | Timestamp of the utterance.                                                                    |

## Reconnect Behavior

If the connection drops, open a new `GET` request with `Last-Event-ID` set to the last received event `id`. The server replays recent events from that offset. The stream is stateless from the client's perspective - all replay state is managed server-side.

## Error Responses

| Status | Description                                                                                                                                                     |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401    | Missing or invalid authentication.                                                                                                                              |
| 403    | The authenticated provider does not own this session.                                                                                                           |
| 404    | No live Zoom event stream exists. Returned for non-Zoom sessions, unknown session IDs, sessions that have already completed, or sessions without an active bot. |
| 503    | The live event stream is temporarily unavailable. Retry after a short delay.                                                                                    |

If the upstream event source fails mid-stream, the server emits a terminal `bot_status` frame with `state: "error"` and `reason: "upstream_unavailable"`, then closes the stream. The client should reconnect with its stored `Last-Event-ID`.

## Example

```javascript
const response = await fetch(`/sessions/${sessionId}/events`, {
  headers: {
    'Authorization': `Bearer ${token}`,
    // Include on reconnect:
    // 'Last-Event-ID': lastEventId,
  },
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  // Parse SSE frames from buffer by splitting on double newlines
  // Store event id for reconnect
  // Handle bot_status, transcript_segment, interim_transcript,
  // transcript_finalized, and ping event types
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.concurrence.com/developer-guide/platform-api/platform-api/zoom-session-events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
