SIP Trunks

Last updated October 13, 2026

SIP trunks to upstream carriers and PBXs (REGISTER or static peering)

# GET /sip/trunks

List configured SIP trunks

Responses

200 List of trunks
FieldTypeDescription
trunksarray[object]required
# POST /sip/trunks

Create a SIP trunk (REGISTER or static peering)

Creates a typed SIP trunk. For type: "sip_register", VoiceBlender begins REGISTERing to the supplied registrar URI with digest auth, refreshes before expiry, and routes inbound INVITEs that arrive on that peer's socket plus outbound INVITEs whose from matches the AOR through the trunk. Set sip_register.outbound_proxy to send both the REGISTER and those INVITEs via a next-hop proxy instead of straight at the registrar; the Request-URI and digest authentication still target registrar_uri. It defaults to SIP_OUTBOUND_PROXY and is resolved at creation time, so the trunk snapshot reports the hop actually in effect. For type: "ip_ip", VoiceBlender peers with a fixed upstream without registering: the trunk is active at once, outbound INVITEs placed through it (by trunk_id on POST /v1/legs, or by a from matching ip_ip.aor) are routed at ip_ip.peer_uri with the trunk's optional digest credentials, and inbound INVITEs whose source address falls in ip_ip.inbound_sources are tagged with the trunk. Set ip_ip.options_ping_interval_seconds to health-check the peer with OPTIONS and receive sip.trunk_up / sip.trunk_down events.

Request Body

FieldTypeDescription
typeenumrequiredTrunk type discriminator. `sip_register` REGISTERs to an upstream registrar; `ip_ip` peers with a fixed upstream without registering.
Values: sip_register, ip_ip
app_idstringoptionalApplication identifier carried through to every event emitted by this trunk.
sip_registerobjectoptionalRequired when type == "sip_register". Configures the outbound REGISTER (registrar URI, AOR, digest credentials, expiry).
registrar_uristringrequiredUpstream registrar SIP URI (e.g. "sip:pbx.example.com:5060" or "sips:pbx.example.com:5061"). Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Note that "transport" is a URI parameter (";"), not a URI header ("?") — RFC 3261 section 19.1.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's REGISTER and for outbound INVITEs placed from its AOR, attached as a loose `Route` header (the Request-URI is left unchanged, and digest auth still targets `registrar_uri`). E.g. "sip:edge.example.com:5060;transport=tcp". Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `registrar_uri`.
aorstringrequiredAddress-of-record this trunk REGISTERs (e.g. "sip:alice@pbx.example.com"). Becomes the From URI on outbound REGISTER, and the From / P-Asserted-Identity host on outbound INVITEs placed `from` this AOR.
usernamestringoptionalDigest auth username. Defaults to the AOR user-part when empty.
passwordstringrequiredDigest auth password. Required. Never returned in any response.
contact_userstringoptionalOverride the user-part of the Contact header sent in REGISTER. Defaults to the AOR user-part.
expires_secondsintegeroptionalRequested registration lifetime in seconds. Clamped to [SIP_OUTBOUND_REGISTRATION_MIN_EXPIRES_SECONDS, SIP_OUTBOUND_REGISTRATION_MAX_EXPIRES_SECONDS]. Default: SIP_OUTBOUND_REGISTRATION_DEFAULT_EXPIRES_SECONDS (3600).
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` registrar or outbound proxy whose certificate is self-signed, privately signed, or carries no SAN (`x509: certificate relies on legacy Common Name field`). Scoped to that peer's hostname — every other TLS peer is still verified in full, unlike the server-wide `SIP_TLS_INSECURE_SKIP_VERIFY`. Ignored (with a logged warning) when the next hop is not TLS, or when it is named by IP literal: such a dial sends no SNI and cannot be told apart from any other, so use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there. Prefer `SIP_TLS_CA_FILE` when the peer's CA can simply be trusted.
ip_ipobjectoptionalRequired when type == "ip_ip". Configures static peering with a fixed upstream (peer URI, optional digest credentials, inbound source addresses, OPTIONS health check).
peer_uristringrequiredSIP URI of the peer (e.g. "sip:203.0.113.10:5060" or "sips:sbc.carrier.example:5061"). Outbound calls placed through this trunk are routed here: with a loose `Route` header when the call's Request-URI names another host, and with none when it already targets the peer. Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Any user part is ignored. When the host is an IP literal it is also matched against the source of inbound INVITEs.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's outbound INVITEs and OPTIONS pings. When set, the INVITE carries a single loose `Route` naming the proxy, so the peer is only reached if the call's Request-URI names it. Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `peer_uri`. A proxy is never treated as an inbound source — list its address in `inbound_sources` if the peer's calls arrive through it.
aorstringoptionalOptional identity this trunk presents (e.g. "sip:acme@carrier.example"). An outbound call whose `from` matches it, as a full URI or by user-part, is placed through this trunk without naming `trunk_id`; its host becomes the From / P-Asserted-Identity realm when `from` names none. Also used to tell apart several trunks that share an inbound source, by the To header.
usernamestringoptionalDigest auth username for outbound INVITEs the peer challenges. Requires `password`. Defaults to the `aor` user-part when a password is set.
passwordstringoptionalDigest auth password for outbound INVITEs the peer challenges. Optional — omit for a peer that authenticates by source address. Never returned in any response.
inbound_sourcesarray[string]optionalIP addresses and CIDR ranges (IPv4 or IPv6) that inbound INVITEs from this peer arrive from, e.g. ["198.51.100.0/24", "203.0.113.7"]. An inbound call whose source address falls in one is tagged with this trunk's `trunk_id` and inherits its `app_id`; when several trunks match, the longest prefix wins. This is a matching rule, not an access list: calls from other addresses are still accepted. The `peer_uri` host is included automatically when it is an IP literal; hostnames are never resolved. At most 64 entries; a /0 range is rejected.
options_ping_interval_secondsintegeroptionalSeconds between OPTIONS health checks sent to the peer; 0 (the default) disables them. With checks on, the trunk's status follows the peer — `active` when it answers, `failed` when it does not — and `sip.trunk_up` / `sip.trunk_down` are published on each change. Any reply counts as up, including 404 or 405, except 408 and 5xx other than 501; no reply within 5 seconds counts as down. With checks off the trunk stays `active`. Status is informational: calls are attempted on a `failed` trunk too. 0
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` peer or outbound proxy whose certificate is self-signed or privately signed. Scoped to that peer's hostname — every other TLS peer is still verified in full. Ignored (with a logged warning) when the next hop is not TLS or is named by IP literal; use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there.

Responses

202 Trunk accepted. A `sip_register` trunk REGISTERs asynchronously; an `ip_ip` trunk is active immediately.
FieldTypeDescription
idstringrequired
typestringrequired
statusstringrequired
400 Invalid JSON, missing or invalid field, or unknown type
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# GET /sip/trunks/{id}

Get a single SIP trunk

Parameters

NameInTypeDescription
idpathstringrequiredLeg ID

Responses

200 Trunk view
FieldTypeDescription
idstringrequired
typestringrequired
app_idstringoptional
statusstringrequired
last_errorstringoptional
created_atstringrequired
sip_registerobjectoptional
registrar_uristringrequired
outbound_proxystringoptional
aorstringrequired
usernamestringoptional
contact_uristringoptional
requested_expires_secondsintegerrequired
granted_expires_secondsintegeroptional
last_registered_atstringoptional
next_refresh_atstringoptional
call_idstringoptional
cseqintegeroptional
source_addressstringoptional
tls_insecure_skip_verifybooleanoptional
ip_ipobjectoptional
peer_uristringrequired
outbound_proxystringoptional
aorstringoptional
usernamestringoptional
inbound_sourcesarray[string]required
options_ping_interval_secondsintegeroptional
last_ping_atstringoptional
last_ping_status_codeintegeroptional
tls_insecure_skip_verifybooleanoptional
404 Trunk not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message
# DELETE /sip/trunks/{id}

Remove a SIP trunk

Returns 202 Accepted; teardown and final removal run asynchronously. A sip_register trunk unregisters first (REGISTER with Expires: 0); an ip_ip trunk only stops its OPTIONS health check, and nothing is sent to the peer.

Parameters

NameInTypeDescription
idpathstringrequiredLeg ID

Responses

202 Trunk accepted for teardown
404 Trunk not found
FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message

Schemas

Objects used by the SIP Trunks endpoints above.

CreateTrunkRequest

FieldTypeDescription
typeenumrequiredTrunk type discriminator. `sip_register` REGISTERs to an upstream registrar; `ip_ip` peers with a fixed upstream without registering.
Values: sip_register, ip_ip
app_idstringoptionalApplication identifier carried through to every event emitted by this trunk.
sip_registerobjectoptionalRequired when type == "sip_register". Configures the outbound REGISTER (registrar URI, AOR, digest credentials, expiry).
registrar_uristringrequiredUpstream registrar SIP URI (e.g. "sip:pbx.example.com:5060" or "sips:pbx.example.com:5061"). Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Note that "transport" is a URI parameter (";"), not a URI header ("?") — RFC 3261 section 19.1.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's REGISTER and for outbound INVITEs placed from its AOR, attached as a loose `Route` header (the Request-URI is left unchanged, and digest auth still targets `registrar_uri`). E.g. "sip:edge.example.com:5060;transport=tcp". Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `registrar_uri`.
aorstringrequiredAddress-of-record this trunk REGISTERs (e.g. "sip:alice@pbx.example.com"). Becomes the From URI on outbound REGISTER, and the From / P-Asserted-Identity host on outbound INVITEs placed `from` this AOR.
usernamestringoptionalDigest auth username. Defaults to the AOR user-part when empty.
passwordstringrequiredDigest auth password. Required. Never returned in any response.
contact_userstringoptionalOverride the user-part of the Contact header sent in REGISTER. Defaults to the AOR user-part.
expires_secondsintegeroptionalRequested registration lifetime in seconds. Clamped to [SIP_OUTBOUND_REGISTRATION_MIN_EXPIRES_SECONDS, SIP_OUTBOUND_REGISTRATION_MAX_EXPIRES_SECONDS]. Default: SIP_OUTBOUND_REGISTRATION_DEFAULT_EXPIRES_SECONDS (3600).
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` registrar or outbound proxy whose certificate is self-signed, privately signed, or carries no SAN (`x509: certificate relies on legacy Common Name field`). Scoped to that peer's hostname — every other TLS peer is still verified in full, unlike the server-wide `SIP_TLS_INSECURE_SKIP_VERIFY`. Ignored (with a logged warning) when the next hop is not TLS, or when it is named by IP literal: such a dial sends no SNI and cannot be told apart from any other, so use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there. Prefer `SIP_TLS_CA_FILE` when the peer's CA can simply be trusted.
ip_ipobjectoptionalRequired when type == "ip_ip". Configures static peering with a fixed upstream (peer URI, optional digest credentials, inbound source addresses, OPTIONS health check).
peer_uristringrequiredSIP URI of the peer (e.g. "sip:203.0.113.10:5060" or "sips:sbc.carrier.example:5061"). Outbound calls placed through this trunk are routed here: with a loose `Route` header when the call's Request-URI names another host, and with none when it already targets the peer. Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Any user part is ignored. When the host is an IP literal it is also matched against the source of inbound INVITEs.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's outbound INVITEs and OPTIONS pings. When set, the INVITE carries a single loose `Route` naming the proxy, so the peer is only reached if the call's Request-URI names it. Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `peer_uri`. A proxy is never treated as an inbound source — list its address in `inbound_sources` if the peer's calls arrive through it.
aorstringoptionalOptional identity this trunk presents (e.g. "sip:acme@carrier.example"). An outbound call whose `from` matches it, as a full URI or by user-part, is placed through this trunk without naming `trunk_id`; its host becomes the From / P-Asserted-Identity realm when `from` names none. Also used to tell apart several trunks that share an inbound source, by the To header.
usernamestringoptionalDigest auth username for outbound INVITEs the peer challenges. Requires `password`. Defaults to the `aor` user-part when a password is set.
passwordstringoptionalDigest auth password for outbound INVITEs the peer challenges. Optional — omit for a peer that authenticates by source address. Never returned in any response.
inbound_sourcesarray[string]optionalIP addresses and CIDR ranges (IPv4 or IPv6) that inbound INVITEs from this peer arrive from, e.g. ["198.51.100.0/24", "203.0.113.7"]. An inbound call whose source address falls in one is tagged with this trunk's `trunk_id` and inherits its `app_id`; when several trunks match, the longest prefix wins. This is a matching rule, not an access list: calls from other addresses are still accepted. The `peer_uri` host is included automatically when it is an IP literal; hostnames are never resolved. At most 64 entries; a /0 range is rejected.
options_ping_interval_secondsintegeroptionalSeconds between OPTIONS health checks sent to the peer; 0 (the default) disables them. With checks on, the trunk's status follows the peer — `active` when it answers, `failed` when it does not — and `sip.trunk_up` / `sip.trunk_down` are published on each change. Any reply counts as up, including 404 or 405, except 408 and 5xx other than 501; no reply within 5 seconds counts as down. With checks off the trunk stays `active`. Status is informational: calls are attempted on a `failed` trunk too. 0
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` peer or outbound proxy whose certificate is self-signed or privately signed. Scoped to that peer's hostname — every other TLS peer is still verified in full. Ignored (with a logged warning) when the next hop is not TLS or is named by IP literal; use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there.

CreateTrunkResponse

FieldTypeDescription
idstringrequired
typestringrequired
statusstringrequired

Error

FieldTypeDescription
instance_idstringoptionalInstance identifier
errorstringrequiredError message

IPIPTrunkSpec

FieldTypeDescription
peer_uristringrequiredSIP URI of the peer (e.g. "sip:203.0.113.10:5060" or "sips:sbc.carrier.example:5061"). Outbound calls placed through this trunk are routed here: with a loose `Route` header when the call's Request-URI names another host, and with none when it already targets the peer. Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Any user part is ignored. When the host is an IP literal it is also matched against the source of inbound INVITEs.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's outbound INVITEs and OPTIONS pings. When set, the INVITE carries a single loose `Route` naming the proxy, so the peer is only reached if the call's Request-URI names it. Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `peer_uri`. A proxy is never treated as an inbound source — list its address in `inbound_sources` if the peer's calls arrive through it.
aorstringoptionalOptional identity this trunk presents (e.g. "sip:acme@carrier.example"). An outbound call whose `from` matches it, as a full URI or by user-part, is placed through this trunk without naming `trunk_id`; its host becomes the From / P-Asserted-Identity realm when `from` names none. Also used to tell apart several trunks that share an inbound source, by the To header.
usernamestringoptionalDigest auth username for outbound INVITEs the peer challenges. Requires `password`. Defaults to the `aor` user-part when a password is set.
passwordstringoptionalDigest auth password for outbound INVITEs the peer challenges. Optional — omit for a peer that authenticates by source address. Never returned in any response.
inbound_sourcesarray[string]optionalIP addresses and CIDR ranges (IPv4 or IPv6) that inbound INVITEs from this peer arrive from, e.g. ["198.51.100.0/24", "203.0.113.7"]. An inbound call whose source address falls in one is tagged with this trunk's `trunk_id` and inherits its `app_id`; when several trunks match, the longest prefix wins. This is a matching rule, not an access list: calls from other addresses are still accepted. The `peer_uri` host is included automatically when it is an IP literal; hostnames are never resolved. At most 64 entries; a /0 range is rejected.
options_ping_interval_secondsintegeroptionalSeconds between OPTIONS health checks sent to the peer; 0 (the default) disables them. With checks on, the trunk's status follows the peer — `active` when it answers, `failed` when it does not — and `sip.trunk_up` / `sip.trunk_down` are published on each change. Any reply counts as up, including 404 or 405, except 408 and 5xx other than 501; no reply within 5 seconds counts as down. With checks off the trunk stays `active`. Status is informational: calls are attempted on a `failed` trunk too. 0
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` peer or outbound proxy whose certificate is self-signed or privately signed. Scoped to that peer's hostname — every other TLS peer is still verified in full. Ignored (with a logged warning) when the next hop is not TLS or is named by IP literal; use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there.

IPIPTrunkView

FieldTypeDescription
peer_uristringrequired
outbound_proxystringoptional
aorstringoptional
usernamestringoptional
inbound_sourcesarray[string]required
options_ping_interval_secondsintegeroptional
last_ping_atstringoptional
last_ping_status_codeintegeroptional
tls_insecure_skip_verifybooleanoptional

SIPRegisterTrunkSpec

FieldTypeDescription
registrar_uristringrequiredUpstream registrar SIP URI (e.g. "sip:pbx.example.com:5060" or "sips:pbx.example.com:5061"). Transport is taken from the URI: a "sips:" scheme or a ";transport=tls" parameter selects TLS, ";transport=tcp" selects TCP, otherwise UDP. Note that "transport" is a URI parameter (";"), not a URI header ("?") — RFC 3261 section 19.1.
outbound_proxystringoptionalNext-hop SIP proxy for this trunk's REGISTER and for outbound INVITEs placed from its AOR, attached as a loose `Route` header (the Request-URI is left unchanged, and digest auth still targets `registrar_uri`). E.g. "sip:edge.example.com:5060;transport=tcp". Defaults to `SIP_OUTBOUND_PROXY`; when neither is set, requests go straight to `registrar_uri`.
aorstringrequiredAddress-of-record this trunk REGISTERs (e.g. "sip:alice@pbx.example.com"). Becomes the From URI on outbound REGISTER, and the From / P-Asserted-Identity host on outbound INVITEs placed `from` this AOR.
usernamestringoptionalDigest auth username. Defaults to the AOR user-part when empty.
passwordstringrequiredDigest auth password. Required. Never returned in any response.
contact_userstringoptionalOverride the user-part of the Contact header sent in REGISTER. Defaults to the AOR user-part.
expires_secondsintegeroptionalRequested registration lifetime in seconds. Clamped to [SIP_OUTBOUND_REGISTRATION_MIN_EXPIRES_SECONDS, SIP_OUTBOUND_REGISTRATION_MAX_EXPIRES_SECONDS]. Default: SIP_OUTBOUND_REGISTRATION_DEFAULT_EXPIRES_SECONDS (3600).
tls_insecure_skip_verifybooleanoptionalAccept this trunk's next-hop certificate without verifying it, for a `sips:` / `;transport=tls` registrar or outbound proxy whose certificate is self-signed, privately signed, or carries no SAN (`x509: certificate relies on legacy Common Name field`). Scoped to that peer's hostname — every other TLS peer is still verified in full, unlike the server-wide `SIP_TLS_INSECURE_SKIP_VERIFY`. Ignored (with a logged warning) when the next hop is not TLS, or when it is named by IP literal: such a dial sends no SNI and cannot be told apart from any other, so use `SIP_TLS_CA_FILE` or `SIP_TLS_INSECURE_SKIP_VERIFY` there. Prefer `SIP_TLS_CA_FILE` when the peer's CA can simply be trusted.

SIPRegisterTrunkView

FieldTypeDescription
registrar_uristringrequired
outbound_proxystringoptional
aorstringrequired
usernamestringoptional
contact_uristringoptional
requested_expires_secondsintegerrequired
granted_expires_secondsintegeroptional
last_registered_atstringoptional
next_refresh_atstringoptional
call_idstringoptional
cseqintegeroptional
source_addressstringoptional
tls_insecure_skip_verifybooleanoptional

TrunkView

FieldTypeDescription
idstringrequired
typestringrequired
app_idstringoptional
statusstringrequired
last_errorstringoptional
created_atstringrequired
sip_registerobjectoptional
registrar_uristringrequired
outbound_proxystringoptional
aorstringrequired
usernamestringoptional
contact_uristringoptional
requested_expires_secondsintegerrequired
granted_expires_secondsintegeroptional
last_registered_atstringoptional
next_refresh_atstringoptional
call_idstringoptional
cseqintegeroptional
source_addressstringoptional
tls_insecure_skip_verifybooleanoptional
ip_ipobjectoptional
peer_uristringrequired
outbound_proxystringoptional
aorstringoptional
usernamestringoptional
inbound_sourcesarray[string]required
options_ping_interval_secondsintegeroptional
last_ping_atstringoptional
last_ping_status_codeintegeroptional
tls_insecure_skip_verifybooleanoptional

TrunksListResponse

FieldTypeDescription
trunksarray[object]required