Upload an audio file (mp3/wav) to play back on a call
Streams the uploaded file to Sautikit's object storage and returns a
signed storage.sautikit.com playback URL — the same branded-CDN
mechanism GET /v1/calls/{call_id}/recording uses for captured call
recordings. This is how you obtain a hosted URL for any "play a
recording" setting; there is no other supported way to hand us audio.
The returned url is what you pass on PUT /v1/numbers/{id}/routing
to every field that plays a recording:
voicemail.greeting_play_url— the voicemail greeting.queue.greeting_play_url— spoken once, as the caller joins.queue.hold_play_url— the hold loop. Sendqueue.hold_duration_secondsalongside it: no verb can cut a<Play>short, so the file's real length is what sets the queue's cadence, and a wrong value there turns a short clip into a rapid-fire callback loop.- the same
voicemail/queueblocks nested underforward.voicemail,queue.voicemailandinbound_agent.
Accepts multipart/form-data with a single file field. Only
audio/mpeg (mp3) and audio/wav (audio/wav, audio/wave,
audio/x-wav) are accepted — anything else is rejected with
uploads.unsupported_media. Max size 10 MiB
(uploads.too_large above that).
API-key callers need the numbers.claim scope; viewers are rejected.
The URL is presigned for 7 days (SigV4's maximum), but you do NOT need
to re-upload to keep a saved greeting working: a stored *_play_url
is re-signed automatically each time the call is rendered, so it keeps
playing indefinitely. The 7-day window only bounds the returned link
itself — treat it as expiring if you hand it to a browser or store it
somewhere outside a number's routing config.
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
Request Body
multipart/form-data
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/uploads/audio" \ -F file="string"{ "url": "http://example.com", "mime_type": "audio/mpeg", "size_bytes": 0}{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ] }}{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ] }}{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ] }}Disconnect the workspace's SIP trunk DELETE
Refused while any BYO numbers still ride the trunk — release them first.
List call detail records for the active workspace GET
Returns the workspace's call detail records, most-recent first. Cursor pagination via `cursor` (opaque, returned as `next_cursor` when more results exist). Filters: `status` (CSV), `direction`, `q` (substring on `remote_e164` or `session_id`), `from` / `to` (RFC3339 or unix seconds), `session_id` (exact match), `limit` (1–100, default 25). Also accepts a device credential (`Authorization: Device <secret>`). For a device principal, results are scoped to that device's own number and exclude broadcast/API-controlled originations — the same filter `GET /v1/devices/calls/stream` applies — so this list and that stream never disagree about what counts as the device's own call history.