Skip to content
SIP.IO
DocsStart free

Public API (v1)

The public REST API is served at https://api.sip.io/v1. It’s JSON in and out, authenticated with an API key or session token, and authorized by scope. The account is always taken from your credential, never a path or query parameter.

Terminal window
curl https://api.sip.io/v1/whoami -H 'x-api-key: sk_…'
# → { "accountId": "acc_acme", "scopes": ["*"], "via": "key" }

The surface is large, grouped below by resource area. Every path takes the credential’s account implicitly; scopes are shown per row (* on a key or token grants all of them).

Identity & account

Method · PathScopeNotes
GET /v1/whoamianyWho the credential is.
GET /v1/scopesopenThe catalog of grantable scopes, no key needed.
GET /v1/accountanyName, status, timezone, language, voice gender, ringback country, recording retention, CAC ceilings.
PATCH /v1/accountaccountSelf-service update: { name?, timezone?, language?, voice_gender?, tone_country?, recording_retention_days?, allow_free_caller_id? }. Never settable here: id, status, parent_id, billing (admin-only).
GET|POST|DELETE /v1/keyskeysSelf-service API keys: list (no secrets shown), mint { label?, scopes? } (secret shown once), revoke.
GET /v1/usageusageSpend/minutes/call-count from the CDR, ?since=&until=&daily=1 for a daily series.
GET /v1/balanceusageAccount financial statement: status, rate plan, month-to-date spend.

Calls

Method · PathScopeNotes
GET /v1/callscdrCall records; ?since=&until=&limit=&cursor=&format=csv, keyset-paginated.
POST /v1/callscallsClick to call: { to, from?, callerId?|cidPoolId?, agentCallerId?, screenPop? }. 409 if the agent’s already on a call.
GET /v1/calls/minecallsThe caller’s own current call id (for a softphone app).
GET /v1/calls/{id}/tracecdrThe full flow-node execution trace for a call, the debugger view.
GET/POST /v1/calls/{id}/ivr , /ivr/selectcallsVisual IVR: read the live menu a call is waiting on, or submit a selection that advances the same flow.
POST /v1/calls/{id}/controlcallsLive-call control: { action: hold|unhold|mute|unmute|hangup|dtmf|park, digits? }. id: "mine" for your own call.
POST /v1/calls/{id}/transfercallsBlind, attended, or 3-way transfer: { action, target, mode? }.
POST /v1/calls/{id}/supervisecallsSupervisor listen / whisper / barge into a live agent call.
POST /v1/calls/{id}/recordingrecordingsMid-call recording control: { action: pause|resume|stop|start } (the PCI-sensitive-segment control).
POST /v1/cac/resetcdrClear this account’s leaked concurrency counters.

Agents & queues

Method · PathScopeNotes
GET /v1/agentsagentsLive agent presence, ?userId=.
POST /v1/agents/stateagentsDrive an agent: { userId, event, queues? }.
GET|POST /v1/queues, /{id}queuesList + rolling KPIs (?since=) / one queue, create, update, delete.
GET|POST /v1/queues/{id}/members, DELETE .../{userId}queuesQueue membership.
POST /v1/queues/{id}/options, DELETE .../{digit}queuesIn-queue DTMF options.
GET /v1/livecdrLive account snapshot (agents, in-progress calls, CAC counters, queue configs), a real-time debugging view.

Numbers, extensions & routing config

Method · PathScopeNotes
GET|POST /v1/numbers, /{id}numbersYour DIDs: route target, fax mode, business hours.
GET|POST /v1/extensions, /{id}extensionsInternal short codes.
GET|POST /v1/ring-groups, /{id}ringgroupsRing groups, members replace as a set on each write.
GET|POST /v1/schedules, /{id}schedulesBusiness-hours schedules, rules replace as a set on each write.
GET|POST /v1/users, /{id}, /{id}/devicesusersUsers/agents/extensions and their SIP devices.
GET|POST /v1/devices, PATCH|DELETE /{id}usersSIP devices (password → ha1, never stored plaintext).

Flows

Method · PathScopeNotes
GET|POST /v1/flows, GET /{id}flowsCall flows: publish: true is lint-gated, a failing lint returns 422.
POST /v1/flows/validateflowsLint a flow graph without saving, the editor’s live check.
POST /v1/flows/{id}/testflowsRun a simulated call through a flow, { from?, to?, digits?, vars? } → the routing trace.

Recordings, voicemail & media

Method · PathScopeNotes
GET /v1/recordings, /{id}, /play, /download, DELETErecordingsCall recordings; every access is logged.
GET|POST /v1/voicemails, /{id}voicemailMailboxes, PIN stored as a secret reference.
GET /v1/voicemails/mwivoicemailMessage-waiting summary.
GET /v1/voicemails/{id}/messages, .../{msgId}/audio, PATCH|DELETE .../{msgId}voicemailThe message inbox: list, stream/download, mark read, delete.
GET|POST /v1/media, GET|DELETE /{id}mediaPrompts/MOH/greetings: upload (raw audio body), play/download, delete.
GET|POST /v1/faxes, GET|DELETE /{id}faxFax over IP: send, list, download/render, delete.

Transcription & summarization

Method · PathScopeNotes
POST /v1/recordings/{id}/transcriberecordingsTranscribe a recording: { language?, summarize? }.
POST /v1/recordings/{id}/summarizerecordingsSummarize an already-transcribed recording on its own.
GET /v1/recordings/{id}/transcriptrecordingsText, language, and summary (?words=1 for word/speaker-level detail).
GET /v1/transcriptsrecordingsList transcripts, filterable, cursor-paginated.
POST /v1/transcripts/batchrecordingsBatch-transcribe by recording ids or a date range, processed in the background.
GET|PUT|DELETE /v1/transcription/configrecordingsBring your own AI provider (any OpenAI-standard transcription or LLM endpoint); your key is encrypted at rest.

Messaging

Method · PathScopeNotes
GET|POST /v1/channels, /{id}channelsMessaging channels (SMS/WhatsApp/RCS senders); secrets shown once.
GET /v1/conversations, /{id}, POST .../replymessagingThe omnichannel inbox.
POST /v1/messagesmessagingSend a message, starts or continues a conversation.
GET|POST /v1/templates, /{id}, POST .../submitmessagingWhatsApp/RCS templates, including Meta submission.

Contacts, scripts & custom fields

Method · PathScopeNotes
GET|POST /v1/contacts, /{id}contactsPhonebook: CNAM, reverse lookup, screen-pop source.
GET /v1/directorycontactsInternal directory, ?digits= for dial-by-name.
GET|POST /v1/scripts, /{id}, GET .../renderscriptsThe call-script store (SIP.IO stores the blob, your app renders it).
GET|POST /v1/fields, /{id}, GET /v1/calls/{id}/fieldsfieldsCustom fields captured by a flow’s collect node, for screen-pop/CDR enrichment.

Conferences & softphone

Method · PathScopeNotes
GET|POST /v1/conferences, /{id}, POST .../controlconferencesConference bridges: create, moderate (mute/kick/lock), delete.
POST /v1/softphone/tokensoftphoneMint an ephemeral WebRTC SIP credential for an embedded softphone.

Compliance & outbound

Method · PathScopeNotes
GET|POST|DELETE /v1/dncdncDo-not-call list.
/v1/campaigns…campaignDialer campaigns: create, contacts, start, pause, disposition, KPIs.

Webhooks & events

Method · PathScopeNotes
GET|POST|DELETE /v1/webhooks, POST .../testwebhooksSubscriptions.
GET /v1/webhooks/eventswebhooksThe catalog of subscribable event types with sample payloads.
GET /v1/webhooks/deliverieswebhooksThe delivery log: status, attempts, last error.
POST /v1/events/ticketeventsMint a single-use ticket for the realtime event-stream WebSocket.

Microsoft Teams Direct Routing

Method · PathScopeNotes
GET|POST /v1/teams, GET|PATCH|DELETE /{id}teamsTenant management: create returns the DNS records to add.
GET /v1/teams/{id}/dns, /cert, /health, /cdrsteamsDNS verification, certificate status, live SBC health, call records.
POST /v1/teams/{id}/provisionteamsRun or resume provisioning.
POST /v1/teams/{id}/status-tokenteamsRotate the tenant’s shareable public-status link.

Reporting & analytics

Method · PathScopeNotes
GET /v1/reports/queues, GET /v1/metrics/queuesreportsQueue rollup reports, 15-minute and daily grain.
GET /v1/reports/agentsreportsAgent rollup reports: occupancy, utilization, time-in-state.
GET /v1/reports/teams, GET|POST /v1/agent-teams, /{id}reportsGroup agents into teams for team × queue rollups.
GET /v1/reports/pausesreportsAgent pause time broken down by reason.
GET /v1/live/queues, /v1/live/agents, /v1/live/interactionsreportsREST snapshots of live queue health, agent state, and in-progress interactions, an alternative to the WebSocket wallboard for consumers that want a poll instead of a live socket.

Reseller / operator

Method · PathScopeNotes
GET /v1/accountsaccountsThe subaccounts under your management (reseller/operator only).
GET /v1/logscdrRecent flow-node events across your calls, ?limit=&level=.
Terminal window
# create a webhook subscription
curl -X POST https://api.sip.io/v1/webhooks \
-H 'x-api-key: sk_…' -H 'content-type: application/json' \
-d '{ "url": "https://acme.com/hooks/sipio", "events": "call.started,call.ended" }'
Terminal window
# update account settings (only the fields you send are changed)
curl -X PATCH https://api.sip.io/v1/account \
-H 'x-api-key: sk_…' -H 'content-type: application/json' \
-d '{ "tone_country": "GB", "recording_retention_days": 90 }'

The spec is published at GET /v1/openapi.json (OpenAPI 3.0, no auth). Point your generator at it for a typed client in any language. Security schemes: apiKey (x-api-key) and bearer (JWT).

Terminal window
curl https://api.sip.io/v1/openapi.json -o sipio-openapi.json

Mutating requests (POST/PATCH/DELETE) accept an Idempotency-Key header. Send the same key on a retry (e.g. after a timeout) and you get back the original stored response instead of creating a duplicate:

Terminal window
curl -X POST https://api.sip.io/v1/queues \
-H 'x-api-key: sk_…' -H 'content-type: application/json' \
-H 'Idempotency-Key: 3f29a1e0-…' \
-d '{ "name": "Support" }'

A replayed response carries an idempotency-replayed: true header so you can tell it apart from a fresh one. Keys are held for 24 hours.

List endpoints that return large result sets (like GET /v1/calls) are keyset-paginated (stable and cursor-based, with no offset drift). When a page is full, the response includes a next_cursor; pass it back as ?cursor= (with the same limit) to get the next page. A response without a next_cursor is the last page.

Terminal window
curl 'https://api.sip.io/v1/calls?limit=500&cursor=…' -H 'x-api-key: sk_…'

The authed /v1 surface is limited to 100 requests / 60s per API key (per-IP for unkeyed requests), enforced by a layered edge gate plus a precise quota. Over the limit returns 429 with a Retry-After header:

{ "ok": false, "error": "rate_limited", "hint": "100 requests / 60s", "retry_after_sec": 42 }

The open /v1 index and /v1/openapi.json are not rate-limited.

Responses are JSON. Errors are uniform:

StatusBody
401{ "ok": false, "error": "unauthorized" }: missing/invalid credential.
403{ "ok": false, "error": "forbidden", "need": "<scope>" }: credential lacks the scope.
404{ "ok": false, "error": "not_found" }.
429{ "ok": false, "error": "rate_limited", "retry_after_sec": … }: see Rate limits.

The /v1 surface above is live, including write CRUD across the resource model (numbers, extensions, ring groups, schedules, users, devices, queues, flows, voicemail, media, conferences), Idempotency-Key support on mutating requests, and keyset pagination. A few narrower resources (SIP domains, call forwards, trunks, outbound routes, number transforms, policies) are still config-managed rather than /v1-exposed. Published SDKs and an MCP server generated from the OpenAPI spec are on the roadmap.