API Reference
Calls

Place an outbound call via the PBX

POST
/v1/calls

Places an outbound call from a workspace number (from) to one or more destination numbers (to). The call is dialed immediately and the response returns before the remote party answers — poll GET /v1/calls/{id} or subscribe to call.answered / call.completed webhooks for final status.

A wallet pre-flight check fires before the PBX is contacted: if the workspace balance is zero the request is rejected 402 (wallet.insufficient_balance) without a PBX leg being created.

Idempotency & correlation: the Idempotency-Key header scopes deduplication — repeated requests with the same key within the active leg's lifetime return the original response. The header value is also forwarded to the PBX as its clientRequestId, but the PBX does not reliably echo it back on callbacks — correlate on the call_id / session_id returned by this endpoint instead (they appear on call.completed / call.failed webhook payloads as call_id / pbx_call_id).

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

Header Parameters

Idempotency-Key?string

Client-supplied idempotency key. Reusing the same key for the same workspace within a live leg returns the original call row instead of a duplicate dial.

Lengthlength <= 64

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

curl -X POST "https://example.com/v1/calls" \  -H "Content-Type: application/json" \  -d '{    "from": "+254712345678",    "to": [      "+254700000001"    ]  }'
{  "call_id": "9d2b1f53-8c0e-4f1d-9a6b-5d3a8c47e9f0",  "session_id": "HD_1a2b3c",  "status": "ringing"}
{  "error": {    "code": "validation.bad_request",    "message": "`from` is required",    "request_id": "req-a1b2c3d4"  }}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string"  }}
{  "error": {    "code": "wallet.insufficient_funds",    "message": "Unable to place call. Insufficient balance on your account. Top up to continue.",    "request_id": "req-a1b2c3d4"  }}
{  "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"  }}