Open in
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
| Method | Path | Description |
|---|---|---|
POST | /v1/calls/register-sip | Register a call and get a one-time SIP URI |
GET | /v1/sip-endpoints | List SIP endpoints |
POST | /v1/sip-endpoints | Create 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-password | Issue 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
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | integer | yes | Agent in your organization that answers the call |
to_number | string | no | E.164 number the caller dialed on your side; stored as the call's destination |
variables | object | no | Values for the agent prompt's {{placeholders}} |
Response (201)
| Field | Type | Description |
|---|---|---|
call_id | integer | Id the call will have in call history |
sip_uri | string | One-time SIP URI to dial: sip:c-<token>@sip.thunderphone.com. Treat it as a secret until used |
expires_at | string | When the URI stops working (5 minutes after registration) |
agent_id | integer | The answering agent |
to_number | string | null | The registered destination, if any |
The URI works for one call. After that call, or after expires_at, calls to it
are refused.
Errors
| Status | When |
|---|---|
400 | Unknown agent, to_number not in E.164 format, or invalid variables |
403 | Dashboard session below the admin role |
503 | SIP addresses are not available in this environment |
SIP endpoint object
| Field | Type | Description |
|---|---|---|
id | integer | Endpoint id |
name | string | Your label |
agent_id | integer | null | Agent that answers calls to the endpoint |
sip_uri | string | Permanent address: sip:agent-<id>-<letters>@sip.thunderphone.com |
auth | string | digest (username and password), ip_allowlist (source IP only, no password) or secret_address (the address is the secret, no password) |
username | string | null | SIP digest username; null unless auth is digest |
sip_uri | string | The SIP address. With secret_address, masked (sip:agent-12-…@…) |
secret_sip_uri | string | secret_address only, and only on create and rotate-password: the full address. Store it like a password |
password | string | Only in responses that issue one: create and rotate-password with digest, and an update that switches auth to digest |
allowed_source_cidrs | string[] | 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_numbers | string[] | Phone numbers a contact-center platform dials to reach the endpoint, as stored (see below). Empty for most endpoints |
srtp | string | Media encryption: disabled, optional or required. Always disabled with digest |
status | string | active, disabled (calls refused) or provisioning (setup in progress or failed; cannot receive calls) |
created_at | string | Creation time |
Create a SIP endpoint
POST /v1/sip-endpoints
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | integer | yes | Agent in your organization |
name | string | no | Label, up to 120 characters |
auth | string | no | digest (default), ip_allowlist or secret_address |
allowed_source_cidrs | string[] | with ip_allowlist | Up to 50 IPv4/IPv6 addresses or CIDR ranges |
dial_in_numbers | string[] | no | Up to 5 numbers the platform dials; ip_allowlist only (see Dial-in numbers) |
srtp | string | no | disabled (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
/16or narrower, or an IPv6 range of/48or 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
authset toip_allowlist. A number adds an address, not a credential: calls to it need the same allowed source, over TCP or TLS, as calls tosip_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-digit999…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,14155550142and4155550142count as the same number. - The call's destination in call history is the number in
X-Original-ToorDiversionwhen 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.
| Status | When |
|---|---|
400 | Unknown 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 |
403 | Dashboard session below the admin role |
409 | A dial-in number is already in use |
502 | The address could not be set up. Retry the request |
503 | SIP 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 validallowed_source_cidrsin the same request, unless the endpoint's current list already meets theip_allowlistrules. The password stops working. If the response is502, calls to the endpoint are refused until you send the same request again. - To
digest: the response includes a newpassword, 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 returns409unless the same request sends"dial_in_numbers": []and"srtp": "disabled"as needed. If the response is502, 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.