Live Server-Sent Events stream of a call's lifecycle
Opens a text/event-stream (SSE) connection that pushes call
lifecycle transitions (ringing, answered, completed, failed, …) as
they happen. Intended for the in-app dialer's live call view.
Past lifecycle events are also embedded inline on the Call resource
(Call.events) — this endpoint is only for the live tail; there is
no separate read endpoint for historical events.
For a call handled by an AI agent the same stream also carries the live transcript, as two additional event kinds:
transcript.turn— a complete, flushed turn ({kind, call_id, seq, role, text, final, occurred_at}). The durable copy of the same turns is onGET /v1/calls/{id}?transcript=1.transcript.delta— an incremental chunk of the turn being spoken right now (deltainstead oftext). Stream-only: partials are never persisted.
The stream opens with a : ready SSE comment the moment it
attaches — useful as a connection check, and ignorable by any
conforming SSE client.
A subscriber that joins mid-call is replayed the last 20 transcript events so it does not sit silent until the next turn.
Neither transcript kind is available as a workspace webhook — they
are per-call and far too chatty for HTTP fan-out. Read them here,
with an API key (calls.read) like any other call read. Note that a
browser EventSource cannot send an Authorization header, so an
API-key subscriber must be server-side (curl, fetch with a reader,
or any SSE client that sets headers).
The connection stays open until the call reaches a terminal state or the client disconnects.
The two id forms behave slightly differently by design. A session id
(HD_…) attaches immediately — the browser dialer knows it before
the call row exists, and subscribing early is the point, so no
existence check is made; the channel is always scoped to the calling
workspace, so an unknown session id simply yields a stream that never
emits. A call UUID is looked up, and 404s when this workspace owns no
such call. A call whose PBX session has not landed yet holds the
request open for a few seconds rather than failing, since origination
returns the UUID before the box calls back.
Authorization
bearerAuth Long-lived ES256 JWT minted from the dashboard (https://app.sautikit.com/developers/api-keys). Signed by the
platform keyring. Carries workspace_id and scopes claims;
revoked via the platform deny-list.
In: header
Path Parameters
The call's Sautikit UUID, or the PBX session id the same call
carries on the wire (HD_…, returned as session_id on
POST /v1/calls and on every webhook). Either form addresses
the same call.
Response Body
text/event-stream
application/json
application/json
curl -X GET "https://example.com/v1/calls/string/stream""string"{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ], "resolution": "string", "reason": "invalid_characters", "suggested_e164": "+254727524723" }}{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ], "resolution": "string", "reason": "invalid_characters", "suggested_e164": "+254727524723" }}Get one call by id GET
Previous Page
Check whether a destination is available before dialling GET
Says whether a call from one of your numbers to a destination would be accepted, rate-wise, before you place it. A dialler uses this to show "Calls to this destination are not available on your account" up front instead of letting the call ring into a refusal. It asks the same rate check the real dial does, so the answer matches. It is advisory: the check is repeated when the call is placed, and an unrated outbound call is refused immediately (the caller hears the message above, then the line is dropped), never connected. `from` must be an active number on the workspace.