Needs keys Saves one SIP trunk configuration (your carrier or PBX) that many numbers can share. Attach numbers with sip_trunk_id on Import phone number or Update phone number. The shared LiveKit inbound trunk, outbound trunk and dispatch rule are created when the first number is attached, so a new trunk has no numbers and no LiveKit IDs. LiveKit provisioning needs LIVEKIT_URL; without it, mock mode records the requests in List telephony operations.
Request#
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | No | Label for the trunk. Default SIP trunk. |
termination_uri |
string | Yes | Where outbound calls are sent, for example sip.example.com. |
sip_trunk_auth_username |
string | No | Digest username Tried presents on outbound calls. |
sip_trunk_auth_password |
string | No | Digest password for outbound calls. Stored encrypted and never returned. |
transport |
string | No | TCP, UDP or TLS. Default TCP. |
media_encryption |
string | No | disabled, allowed or required. Default allowed. |
allowed_inbound_addresses |
string[] | No | Source IPs or CIDRs allowed to send inbound INVITEs (your PBX or carrier). Default []. |
inbound_auth_username |
string | No | Digest username your carrier must present on inbound INVITEs. |
inbound_auth_password |
string | No | Digest password for inbound INVITEs. Stored encrypted and never returned. |
Example request#
curl -X POST https://api.tried.com.au/create-sip-trunk \
-H "Authorization: Bearer $TRIED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Melbourne PBX",
"termination_uri": "pbx.example.com:5061",
"transport": "TLS",
"sip_trunk_auth_username": "tried",
"sip_trunk_auth_password": "s3cret-pass",
"allowed_inbound_addresses": ["203.0.113.10/32"]
}'const res = await fetch("https://api.tried.com.au/create-sip-trunk", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRIED_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Melbourne PBX",
termination_uri: "pbx.example.com:5061",
transport: "TLS",
sip_trunk_auth_username: "tried",
sip_trunk_auth_password: "s3cret-pass",
allowed_inbound_addresses: ["203.0.113.10/32"],
}),
});
const trunk = await res.json();import os, requests
res = requests.post(
"https://api.tried.com.au/create-sip-trunk",
headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
json={
"name": "Melbourne PBX",
"termination_uri": "pbx.example.com:5061",
"transport": "TLS",
"sip_trunk_auth_username": "tried",
"sip_trunk_auth_password": "s3cret-pass",
"allowed_inbound_addresses": ["203.0.113.10/32"],
},
)
trunk = res.json()Response#
201 Created
{
"sip_trunk_id": "sip_trunk_5c1e8a92d4f70b36a1e9c4d2",
"name": "Melbourne PBX",
"termination_uri": "pbx.example.com:5061",
"sip_trunk_auth_username": "tried",
"transport": "TLS",
"media_encryption": "allowed",
"allowed_inbound_addresses": ["203.0.113.10/32"],
"inbound_auth_username": null,
"phone_numbers": [],
"livekit_inbound_trunk_id": null,
"livekit_outbound_trunk_id": null,
"livekit_dispatch_rule_id": null,
"last_modification_timestamp": 1792396800000
}| Field | Type | Description |
|---|---|---|
sip_trunk_id |
string | Trunk ID, sip_trunk_ plus 24 hex characters. |
phone_numbers |
string[] | Numbers attached to the trunk. |
livekit_inbound_trunk_id |
string or null | Shared LiveKit inbound trunk. null until a number is attached. |
livekit_outbound_trunk_id |
string or null | Shared LiveKit outbound trunk. |
livekit_dispatch_rule_id |
string or null | Shared LiveKit dispatch rule. |
last_modification_timestamp |
integer | Last change, Unix ms. |
Passwords are never returned.
Errors#
| Status | When |
|---|---|
400 |
Body validation failed, for example termination_uri: Required. |
401 |
Missing or invalid API key. |
403 |
The key's IP allowlist or scopes reject the request. This route needs the numbers scope. Members get The member role is read-only. |
429 |
Rate limit exceeded. See Rate limits. |
See Errors for the body format.