API Reference
Calls

Mint a short-lived WebRTC PBX token for the browser softphone

POST
/v1/webrtc/token

Requests a workspace-scoped WebRTC bearer token from the PBX. The token is returned as-is from the PBX; the caller passes it to the in-browser softphone SDK to register. Short-lived (typically 60–300 s); renew before expiry.

Optional body fields (client_name, role) are forwarded to the PBX and reflected in token claims; both may be omitted. Every body field is optional, but the request body itself must be valid JSON — send at least {} (an empty body is rejected 400 validation.bad_request).

To bind the token to one of your DIDs (so the WebRTC session routes through that number), pass either tenant_number_id (the internal number id) or phone_number (the DID in E.164). The backend resolves the number's PBX sip-profile and embeds it as the token's sip.id claim. Omit both to mint a non-DID-bound token, in which case the PBX assigns sip.id "default". When both are supplied, tenant_number_id wins.

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

Request Body

application/json

All fields optional; send {} at minimum.

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

curl -X POST "https://example.com/v1/webrtc/token" \  -H "Content-Type: application/json" \  -d '{    "phone_number": "+254712345678",    "role": "agent"  }'
{  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3ZTRhMWYxMi05ZDYyLTRmOWEtOWQyZi0xYjJlNmMxYzhhM2E6bWVtLTQyIiwicm9sZSI6ImRpYWxlciJ9.sig",  "endpoint": "wss://webrtc.example.com",  "protocol": "wss",  "clientName": "agent-42",  "sipProfile": {    "id": "sp_9f2c1a"  },  "turnServer": {    "iceServers": [      {        "urls": "turn:turn.cloudflare.com:3478?transport=udp",        "username": "<short-lived>",        "credential": "<short-lived>"      }    ]  },  "expiresIn": 900}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}

Fetch the recording resource for a call (redirect or status) GET

Returns the recording asset for the given call in one of three ways depending on the recording's lifecycle state: - **302** — recording is ready; `Location` header carries a 15-minute presigned Sautikit CDN URL. The response body is empty. The client can pass `Location` directly to `<audio src=...>` — audio bytes do NOT flow through the API process. The Sautikit URL is the only URL ever surfaced; the raw PBX URL is never exposed. - **202** — recording capture is still in progress (`status: pending`). The client should wait `retry_after_seconds` before re-polling (also reflected in the `Retry-After` response header). Error code: `recording_not_ready`. - **410** — the asset has been pruned per the workspace's storage-tier retention policy and is permanently unavailable. Error code: `recording_unavailable`. - **404** — the call does not exist, belongs to a different workspace, or was never configured for recording. Cross-tenant existence is not leaked. Error code: `recording_not_found`. Workspace isolation: `call_id` must belong to the active workspace; otherwise the endpoint returns 404.

Send a control command to a conference room on the PBX POST

Dispatches one of the allowlisted PBX conference commands (`kill`, `mute`, `unmute`, `tmute`, `deaf`, `undeaf`, `kick`, `hup`, `lock`, `unlock`, `hold`, `unhold`, `play`, `dtmf`, `relate`) to the named room. The room must belong to the active workspace. Unknown commands are rejected with 400.