API Reference
Calls

Get the call's active supervision

GET
/v1/calls/{call_id}/supervision

supervision is null when no supervisor is on the call.

Who can call this: a signed-in workspace owner or admin, or a member holding the Supervisor licence — or an API key or OAuth token with the calls.read scope. Seeing who is listening in on a call is itself treated as supervisory access.

Authorization

bearerAuth
AuthorizationBearer <token>

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

call_id*string

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. A call outside the active workspace returns 404, never 400 — a malformed id (neither form) is the only case that returns 400.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/calls/string/supervision"
{  "supervision": {    "supervision_id": "3f1c2a9e-6b7d-4e2a-9f0b-1c2d3e4f5a6b",    "call_id": "9d2b1f53-8c0e-4f1d-9a6b-5d3a8c47e9f0",    "session_id": "HD_24d73b4518bc",    "supervisor_leg_id": "sv_8f2c1a",    "mode": "whisper",    "announce": "agent",    "supervisor": {      "type": "client",      "identity": "agent-supervisor-1",      "label": "Amina (QA)"    },    "notify_agent": true,    "state": "connected",    "connected_at": "2026-09-29T09:21:18.442Z",    "created_at": "2026-09-29T09:21:13.987Z"  }}
{  "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"  }}
{  "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"  }}

Terminate an active call POST

Requests termination of an in-progress call via the PBX. The browser SDK dials directly over WebRTC; this server-side endpoint is the control-plane hangup used to force-end a live call. Workspace isolation: `call_id` must belong to the active workspace, otherwise this endpoint returns 404 (cross-tenant existence is not leaked). Idempotent: if the PBX reports the call already ended, the request still succeeds. Addressable by either the Sautikit call row UUID (the `call_id` from `POST /v1/calls` / the `id` from `GET /v1/calls`) or the PBX session id (`HD_…`) the same call carries on the wire — the server resolves the stored PBX session itself either way.

Put a supervisor on a live call POST

Rings a supervisor onto an answered, in-progress call in `listen` (hear only), `whisper` (hear both sides, and be heard by the agent only) or `barge` (hear and speak to both sides) mode. Only an ordinary two-party call can be supervised — AI-agent calls, conference sessions and callers still waiting in a queue all return `calls.unsupported_call_type`. A `client` or `sip` target that is not registered, or a `client` target that resolves to a different workspace, returns `calls.supervisor_unreachable`. A muted supervisor is never heard by the agent or caller, even in `whisper` or `barge` — muting the leg (locally, on the supervisor's own device) always wins over the mode. One supervisor per call, enforced by a database constraint: starting a second one returns `calls.supervision_in_progress` naming the current supervisor. If a `DELETE` on this same call raced the request and won, this returns `calls.supervision_stopped`. Mode changes only ever happen through this API — the PBX switches the leg via an internal command, so a supervisor's own handset DTMF does no such thing, and every `mode_changed` event this produces carries `source: "api"`. Billed per minute from the supervisor leg's connect to its end: KES 0.50/min for a `client` or `sip` supervisor, the workspace's normal outbound rate for a `phone` supervisor (rated off the supervised call's own number). A ringing or failed leg is never billed. Progress and billing both arrive asynchronously as `call.supervision.*` webhooks; this call only returns the leg's initial `connecting` state. **Who can call this:** a signed-in workspace owner or admin, or a member holding the Supervisor licence — or an API key or OAuth token with the `calls.supervise` scope. A device (handset) credential can never supervise calls.