API Reference
Calls

Put a supervisor on a live call

POST
/v1/calls/{call_id}/supervision

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.

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.

Header Parameters

Idempotency-Key?string

Retrying the same key returns the same supervision instead of starting a second leg.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/calls/string/supervision" \  -H "Content-Type: application/json" \  -d '{    "mode": "listen",    "supervisor": {      "type": "client"    }  }'
{  "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"  }}
{  "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"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string",    "details": [      "string"    ],    "resolution": "string",    "reason": "invalid_characters",    "suggested_e164": "+254727524723"  }}