ThunderPhone v3 is live.Self-serve, from 2¢/min.Read the announcement

Calls

SIP Addresses

Register one-time SIP URIs for calls, and manage permanent SIP endpoints that route to an agent.

Reach an agent over SIP without a phone number. For how and when to use each kind, see Connect over SIP.

Endpoints

MethodPathDescription
POST/v1/calls/register-sipRegister a call and get a one-time SIP URI
GET/v1/sip-endpointsList SIP endpoints
POST/v1/sip-endpointsCreate a SIP endpoint (returns its password once)
GET/v1/sip-endpoints/{id}Get a SIP endpoint
PATCH/v1/sip-endpoints/{id}Update name, agent, authentication, source-IP allowlist, dial-in numbers, SRTP or status
DELETE/v1/sip-endpoints/{id}Delete a SIP endpoint
POST/v1/sip-endpoints/{id}/rotate-passwordIssue a new password, or a secret_address endpoint's new address (returned once)

Creating, updating and deleting require an organization API key, or a dashboard session with the admin role or higher.

Register a call

POST /v1/calls/register-sip

Request fields

FieldTypeRequiredDescription
agent_idintegeryesAgent in your organization that answers the call
to_numberstringnoE.164 number the caller dialed on your side; stored as the call's destination
variablesobjectnoValues for the agent prompt's {{placeholders}}

Response (201)

FieldTypeDescription
call_idintegerId the call will have in call history
sip_uristringOne-time SIP URI to dial: sip:c-<token>@sip.thunderphone.com. Treat it as a secret until used
expires_atstringWhen the URI stops working (5 minutes after registration)
agent_idintegerThe answering agent
to_numberstring | nullThe registered destination, if any

The URI works for one call. After that call, or after expires_at, calls to it are refused.

Errors

StatusWhen
400Unknown agent, to_number not in E.164 format, or invalid variables
403Dashboard session below the admin role
503SIP addresses are not available in this environment

SIP endpoint object

FieldTypeDescription
idintegerEndpoint id
namestringYour label
agent_idinteger | nullAgent that answers calls to the endpoint
sip_uristringPermanent address: sip:agent-<id>-<letters>@sip.thunderphone.com
authstringdigest (username and password), ip_allowlist (source IP only, no password) or secret_address (the address is the secret, no password)
usernamestring | nullSIP digest username; null unless auth is digest
sip_uristringThe SIP address. With secret_address, masked (sip:agent-12-…@…)
secret_sip_uristringsecret_address only, and only on create and rotate-password: the full address. Store it like a password
passwordstringOnly in responses that issue one: create and rotate-password with digest, and an update that switches auth to digest
allowed_source_cidrsstring[]Source IP ranges allowed to call. With digest, empty means any source with valid credentials. Checked for TCP/TLS calls only: an endpoint with an allowlist refuses UDP calls
dial_in_numbersstring[]Phone numbers a contact-center platform dials to reach the endpoint, as stored (see below). Empty for most endpoints
srtpstringMedia encryption: disabled, optional or required. Always disabled with digest
statusstringactive, disabled (calls refused) or provisioning (setup in progress or failed; cannot receive calls)
created_atstringCreation time

Create a SIP endpoint

POST /v1/sip-endpoints

FieldTypeRequiredDescription
agent_idintegeryesAgent in your organization
namestringnoLabel, up to 120 characters
authstringnodigest (default), ip_allowlist or secret_address
allowed_source_cidrsstring[]with ip_allowlistUp to 50 IPv4/IPv6 addresses or CIDR ranges
dial_in_numbersstring[]noUp to 5 numbers the platform dials; ip_allowlist only (see Dial-in numbers)
srtpstringnodisabled (default), optional (SRTP when the caller offers it) or required (calls without SRTP fail). optional and required need ip_allowlist

Returns 201 with the endpoint object, including password for a digest endpoint, or secret_sip_uri for a secret_address endpoint. An ip_allowlist or secret_address endpoint has no username or password.

allowed_source_cidrs entries are normalized and deduplicated. 0.0.0.0/0 and ::/0 are refused (they are not an allowlist). With digest, use [] to allow any source with valid credentials.

With ip_allowlist, the list is the only check on who can call, so it must contain at least one entry and every entry must be:

  • an IPv4 range of /16 or narrower, or an IPv6 range of /48 or narrower;
  • public: private, loopback, link-local, shared (100.64.0.0/10), documentation, reserved and multicast ranges are refused;
  • outside ThunderPhone's and LiveKit's own addresses.

An ip_allowlist endpoint accepts calls over TCP (port 5060) or TLS (port 5061) only. Calls over UDP are refused, because a UDP source address can be forged.

Dial-in numbers

Some contact-center platforms (Five9, NICE CXone, Zoom Contact Center) send a call to a phone number and can't dial the agent-… user of sip_uri. List the numbers they dial in dial_in_numbers; a call to sip:<number>@sip.thunderphone.com then reaches the endpoint like a call to its sip_uri.

  • Only with auth set to ip_allowlist. A number adds an address, not a credential: calls to it need the same allowed source, over TCP or TLS, as calls to sip_uri.
  • At most 5. Each is 6 to 15 digits with an optional leading +. Spaces, dashes and parentheses are removed; the number is otherwise stored as written, so enter it the way the platform dials it (Zoom's 15-digit 999… numbers have no +). Numbers that differ only in the + count once.
  • A number can't be on another SIP endpoint, in any organization, or be a ThunderPhone phone number. +14155550142, 14155550142 and 4155550142 count as the same number.
  • The call's destination in call history is the number in X-Original-To or Diversion when the platform sends one, otherwise the dial-in number.

srtp set to optional or required also needs ip_allowlist; a digest endpoint takes only disabled. Platforms that need SRTP, such as Zoom Contact Center and Talkdesk, authenticate by source IP. Use SRTP with TLS.

StatusWhen
400Unknown agent, invalid field, invalid CIDR, an ip_allowlist list that is missing or breaks the rules above, an invalid dial-in number or more than 5, or dial-in numbers or SRTP with digest
403Dashboard session below the admin role
409A dial-in number is already in use
502The address could not be set up. Retry the request
503SIP addresses are not available in this environment

After a 502, create the endpoint again. A leftover endpoint in provisioning never received a password, cannot receive calls and is removed automatically; don't wait for it to become active.

List and get SIP endpoints

GET /v1/sip-endpoints returns 200 with {"results": [...]}, newest first. GET /v1/sip-endpoints/{id} returns one endpoint; an unknown id, or one in another organization, returns 404. Read responses never include password.

Update a SIP endpoint

PATCH /v1/sip-endpoints/{id} accepts any of name, agent_id, auth, allowed_source_cidrs, dial_in_numbers, srtp and status (active or disabled). Returns the endpoint object. Changing the agent or the allowlist takes effect for the next call. Changing status, auth, dial_in_numbers or srtp returns 409 while the endpoint is still provisioning.

dial_in_numbers replaces the whole list; send [] to remove every number. The same rules as on create apply, and a number already in use returns 409 with nothing changed. If the response is 502, the new list is saved but calls to a newly added number fail until you send the same request again. Changing srtp behaves the same way. Setting dial_in_numbers or turning srtp on for a digest endpoint returns 400.

Changing auth:

  • To ip_allowlist: send a valid allowed_source_cidrs in the same request, unless the endpoint's current list already meets the ip_allowlist rules. The password stops working. If the response is 502, calls to the endpoint are refused until you send the same request again.
  • To digest: the response includes a new password, returned only once; the username stays the same. The allowlist is kept unless you change it in the same request. An endpoint with dial-in numbers or SRTP returns 409 unless the same request sends "dial_in_numbers": [] and "srtp": "disabled" as needed. If the response is 502, nothing changed and the endpoint still accepts calls by source IP only.

Setting auth to the value it already has issues no new password; use rotate-password for that. A secret_address endpoint can't switch to another auth, and no endpoint can switch to secret_address (409): create a new endpoint instead.

Rotate the password

POST /v1/sip-endpoints/{id}/rotate-password returns the endpoint object with a new password. The old password stops working immediately. An ip_allowlist endpoint has no password and returns 409. A secret_address endpoint gets a new address instead, in secret_sip_uri; the old address stops working immediately.

Delete a SIP endpoint

DELETE /v1/sip-endpoints/{id} returns 204. Calls to the address are refused from then on. Call history is kept. It returns 409 while the endpoint is still provisioning; an endpoint whose setup failed is removed automatically, usually within an hour.