Events and SSE
The full event catalog, payload shape, and the live wait streams.
The Agent API can tell you when things happen. You can subscribe to events over a webhook (see the Webhooks page) or wait on them live over Server-Sent Events (SSE). There are 15 subscribable events.
The event catalog
| Event | Scope | Carries an id? |
|---|---|---|
recording.started | Record | No (null today) |
recording.stopped | Record | Yes, meeting id |
recording.paused | Record | Yes, meeting id |
recording.resumed | Record | Yes, meeting id |
recording.failed | Record | Sometimes, may be null |
recording.stop_failed | Record | Sometimes, may be null |
job.submitted | Read | Yes, job id |
job.completed | Read | Yes, job id |
job.failed | Read | Yes, job id |
job.cancelled | Read | Yes, job id |
job.paused | Read | Yes, job id |
job.resumed | Read | Yes, job id |
summary.completed | Read | Sometimes, meeting id or null |
summary.failed | Read | Sometimes, meeting id or null |
transcript.updated | Read | Sometimes, null when idle |
meeting.* is not a real scope
Subscribing to meeting.* is rejected with 400 and the message unknown event: <name>. There are no meeting.* events, on webhooks or SSE.
resource_id can be null
resource_id can be null on any event; delivery is best-effort. recording.started is always null today. transcript.updated is null when no recording is live. Do not block waiting for an id that may not come.
job.paused can arrive twice
A single pause may deliver job.paused up to twice for one pause: a transitional event, then a settled one. Treat it as an observability signal, not a counter.
Event payload
Every event on the SSE stream is a thin JSON object:
{
"event": "job.completed",
"resource_id": "<id or null>",
"timestamp": "<iso8601>",
"message": "<optional>",
"still_recording": true
}message and still_recording are optional and not present on every event. Webhook delivery adds a delivery_id to this same shape; the SSE stream does not.
Waiting live (SSE)
There is no generic all-events stream. Two long-poll endpoints each stream exactly one event then close, or time out:
| Endpoint | Scope | Resolves on | Default timeout |
|---|---|---|---|
GET /v1/jobs/:id/wait | Read | job.completed, job.failed, or job.cancelled | 300 seconds |
GET /v1/recording/wait?until=started | Record | recording.started or recording.failed | 30 seconds |
GET /v1/recording/wait?until=stopped | Record | recording.stopped or recording.stop_failed | 3600 seconds |
The maximum timeout for either endpoint is 3600 seconds. At the deadline, the stream emits a synthesized timeout event and closes. Pausing and resuming are not terminal states and never end a wait.
These are the HTTP-layer defaults. The MCP wait tools use their own, shorter bound (see the AI Assistants tools page). Do not confuse the two.
curl -N "http://127.0.0.1:8420/v1/jobs/JOB_ID/wait" -H "Authorization: Bearer $MEETILY_PRO_TOKEN"Prefer push? Use webhooks
For delivery instead of blocking, register a webhook. See Webhooks.
Last updated on
