Trunk and number management is a control-plane surface. Drive it from the
admin console (
agent.clutchcall.dev) and the control-plane API on
portal.clutchcall.dev. There is no media-SDK method for it today. The
Voice SDK Calls client originates and
controls calls over a trunk that you already provisioned here (it takes a
trunkId). The Calls client does not create trunks or numbers.
For the task-oriented walkthroughs, see
SIP Trunking and
Number Provisioning.
This page is the operation-and-schema reference.orgId). Each operation is tenant-checked, so you
can touch only the trunks and numbers that your workspace owns. Writes take
effect live: the SIP gateway hot-reloads a changed trunk within a couple of
seconds, and the engine rebuilds the routing table, with no engine restart.
Trunks
A trunk is a named SIP/RTP profile. The profile defines where your carrier’s SBC lives, how to authenticate, which codecs to offer, and what an inbound call does. Four operations manage the set.admin.listTrunks reads from the same live routing store that the engine
consumes. The response is exactly what is in force on the data plane, not a
cache that can drift. The API unseals secret subfields for the edit form on the
way out. The API re-seals them on the next write.The trunk object
Onlytrunk_id is required. Every other field is optional and carries an
engine-side default. The most common fields:
string
required
The stable identifier for the trunk, typically the carrier-supplied circuit
name (for example
INT-KA-SBC09-9287). Numbers resolve against this key.
Keep the key stable after calls start to flow.string
The human-readable label that the console shows.
enum
default:"internal"
The trunk class. The class drives billing categorisation and which
destinations a tool call may transfer to. One of
internal (your own
PBX/extensions), external (a PSTN/SIP carrier — per-minute billing
applies), or ai_vendor (an external media vendor such as LiveKit, Vapi, or
Twilio that acts as the agent leg).boolean
When
true, the gateway REGISTERs outbound to the carrier with
sip_username / sip_password. When false, the gateway matches the trunk
by source IP (SBC) and sends no registration.string
The auth user for a registering trunk.
string
The auth secret for a registering trunk. Sealed at rest — see the note
below.
string
The signalling addresses. The split lets the gateway bind a private IP behind
cloud NAT while it advertises the public IP in
Contact / Via.string
The media addresses, with the same private-bind / public-advertise split as
the SIP IPs.
string
The address of the upstream carrier gateway / session border controller that
the trunk peers with.
string[]
The ordered codec offer, for example
["PCMU", "PCMA"]. G.711 µ-law/A-law
are the wire codecs. See the
Codec Guide.integer
The maximum number of concurrent calls on the trunk.
enum
default:"proxy"
proxy routes RTP through the engine’s media plane (the production default).
direct is signalling-only carrier→runtime media.enum
default:"full"
The identity-header policy on outbound INVITEs.
full sends
regulator-friendly caller-identity headers (P-Asserted-Identity,
Remote-Party-ID, P-Access-Network-Info). minimal suppresses them, for
carriers whose CLI screening silently drops calls that assert identity. For
finer control, use enable_pai, enable_pani, and custom_pani_header.Inbound routing target
An inbound INVITE matched to a trunk needs a destination. Set one of these fields. The engine regenerates the routing table on write, so the target takes effect immediately:string
Offer the call to the oldest-idle agent who holds this skill (ACD fallback).
string | null
Route to a VDN, so its IVR/vector program runs on inbound. This field is
mutually exclusive with an agent binding. The router emits a
vector: rule
when the field is set. See
PBX / ACD.string
Stream the answered call to an AI agent endpoint over QUIC.
inbound_ai_websocket_url is the WebSocket-fallback equivalent for bespoke
WS audio receivers.Secrets are sealed at rest. The API applies field-level encryption to
sip_password and api_bearer_token before storage. The API opens them only
under the trunk’s own workspace. The rest of the trunk (IPs, usernames,
routing) stays readable to the engine without any decrypt. Deployments that
require this — HIPAA / SOC 2 — get it by default. You send the plaintext
secret. You never receive the secret back in the clear, except in the edit
form.Create a trunk
updateTrunk takes the same trunk object plus a trunkId. It replaces the
stored config wholesale. removeTrunk takes just { orgId, trunkId }.
Numbers
A phone number (DID) is a row in the workspace’s number registry. The row maps an E.164 address to a trunk and/or an agent. Register a number to route an inbound call to it. The gateway rejects a call to an unregistered number.string
required
The number in E.164, for example
+14155550123.enum
default:"local"
local, toll-free, or mobile.string
default:"US"
The ISO-3166 alpha-2 country code.
string | null
The trunk that carries this number’s calls. This is the number → trunk
assignment.
string | null
The agent that answers calls to this number. This is the number → agent
assignment.
enum
default:"active"
active, pending, or inactive. Only an active number is published to
the inbound routing index. A flip to pending/inactive withdraws the
number, but does not delete the row.string | null
Where the number came from (for example
manual, or a carrier name). For
numbers that you import by hand, use your own value.When you register a number, the API publishes a lookup entry. The SIP gateway
resolves this entry on every inbound INVITE (by dialed number, then by trunk
source IP). The API also rebuilds the routing table, so the call reaches its
assigned agent. Only
active numbers are published. deletePhoneNumber (or a
status flip) withdraws the entry immediately.Assignment is the whole point
To provision an address and to assign it are two steps. A number with neither atrunk_id nor an agent_id still parks a call. The assignment model:
- Number → trunk (
trunk_id) — which carrier profile carries the call. - Number → agent (
agent_id) — which agent answers it. - Trunk → target (
inbound_skill_id/vdn_id/inbound_ai_quic_url) — the fallback destination for any inbound call on the trunk that a specific number does not override.
Managed number catalog (search-and-buy)
telephony.searchAvailableNumbers searches an upstream carrier catalog for a
new DID that you can allocate. The search pages and filters by country and
type. The search also annotates each offer to show whether your workspace
already owns the number.
string
A substring / area-code filter.
string
default:"all"
An ISO country filter.
enum
default:"all"
local, toll-free, mobile, or all.integer
Pagination;
perPage clamps to 50.Per-tenant SIP address (no purchase)
Separately from carrier trunks, every workspace gets a ready-to-use SIP address at creation —<workspace-id>.sip.clutchcall.dev (with matching
<workspace-id>.webrtc.clutchcall.dev and apex records). No Telephony API call
is necessary. The address exists from onboarding. The gateway derives the
tenant from the leftmost DNS label of an inbound INVITE. Use the address to
register softphones, or to point a test carrier at your workspace immediately.
Details are in
Number Provisioning.
Related
SIP Trunking
Task walkthrough: connect a carrier, bring your own trunk, or use a managed one.
Number Provisioning
The three routes to a reachable address, and how to assign it.
PBX / ACD
VDNs, vectors, and the skill-queue routing that trunks and numbers target.
Calls API
Originate and control live calls over a provisioned trunk from the SDK.

