trunk row and are carried in the Redis
payload, so they can be changed on an existing trunk without recreating
it.
How a trunk save reaches the gateway
Every write on this screen is double-published:- The non-secret row is written to the Postgres/Supabase
trunktable. This is what the SPA lists and filters on. - The same trunk is mirrored into Redis (
trunks_data) throughadminApi.addTrunk/adminApi.updateTrunk, so the TeleQuick C++ gateway picks the config up immediately.
- Order matters. Postgres first, then the Redis mirror. A trunk that exists only in Redis still routes calls but is invisible on this screen.
- Secrets are never hydrated back into the form.
sip_passwordandapi_bearer_tokenload as empty strings. Blank means keep what is stored; typing a value rotates it. Their only home is the sealed Redis payload — thetrunktable is RLS-readable by every org member. - Deactivating a trunk (
active = false) is a soft delete: the row stays in Postgres but is pulled from Redis, so the gateway stops routing through it.
Packetization and the rtp_ptime_ms field
rtp_ptime_ms is the packetization interval in milliseconds — how much
audio each RTP packet carries on this trunk.
The field defaults to unset (null). Unset means the trunk does not
force a ptime and the value is left to normal codec/offer negotiation.
The payload builder coerces a falsy value to null, so clearing the
field (or entering 0) is the same as “not set”.
When you do set it, you are trading packet rate against delay:
Set a larger ptime when you are packet-rate bound (high channel counts on
a constrained edge, or a carrier that asks for it). Keep it small — or
unset — on legs where responsiveness is the point, such as an AI agent
leg where auto barge-in has to interrupt quickly: packetization delay
sits in front of every barge-in decision the gateway makes.
A ptime you set here is still an offer. If the carrier does not accept
it, the negotiated value wins.
Carrier source CIDRs and the digest challenge
acl_allow_cidrs is a list of source CIDRs for this trunk. It is
validated in the form with the shared CIDR validator, so a malformed
entry blocks the save rather than reaching the gateway.
- Empty list. The payload sends
null— no source allowlist. Inbound requests on the trunk are authenticated the ordinary way, by digest challenge againstsip_username/sip_password. - Populated list. The listed carrier source ranges are recognised by address, so carrier traffic is admitted on IP identity instead of being challenged. Many PSTN carriers will not answer a digest challenge at all, which is exactly the case this field exists for.
IP-authenticated carrier trunks commonly run with
require_registration = false; credentialed SIP accounts set it true.
Pinning a trunk to a regional SIP edge
sip_edge_id pins the trunk to a row in the platform sip_edge
registry. The picker is populated from the enabled edges, which are
readable by every tenant. null is the direct option — no regional
edge in the path.
When you pin an edge, two things happen that you do not configure by
hand:
- On save, the BFF derives
proxyandinternal_sip_ipfrom the edge. You should not expect to hand-maintain those two fields on a pinned trunk; the edge selection owns them. - The edge’s Kamailio pulls this trunk’s carrier IPs into its allowlist, so the edge will pass traffic for this trunk.
acl_allow_cidrs before, or at the same time as, pinning the edge.
Pin an edge when the carrier requires signalling from a particular region
or a stable set of egress addresses. Leave the trunk direct when the
carrier peers with your gateway addresses already.
RTP port range and concurrency
Two fields define the media port window the gateway uses for this trunk:
Both are carried in the Redis payload, so the gateway sees a change as
soon as the save completes. Whatever window you choose has to be open
end-to-end: through your firewall and through any NAT, toward the trunk’s
external_rtp_ip.
channel_limit (default 50) is a separate number. It caps the
concurrent channels on the trunk; the port window does not enforce it and
the two are not validated against each other. If you raise
channel_limit, check that the port window is still wide enough for the
media sessions that limit now permits, and that the firewall rule matches
the window rather than the old one.
Both values are clamped by the form before they are sent, so a mistyped
port lands at the boundary instead of propagating a nonsense value into
Redis.
Auto barge-in mode and aggressiveness
Barge-in is configured per trunk, not only globally, so a carrier trunk and an AI-vendor trunk on the same org can behave differently.
Energy-based detection keys off incoming audio level, which makes it
sensitive to the acoustic conditions of the leg. A noisy PSTN leg with an
aggressive setting will cut prompts off on background noise; a quiet,
well-conditioned agent leg tolerates more aggression and feels more
responsive. Tune the value on the trunk the complaints are coming from,
rather than changing it for every trunk at once.
Both fields ride the same payload as everything else here, so the gateway
applies the new behaviour to calls placed after the save.
Reading the registration status chip
The chip in the trunk list has two possible sources, and knowing which one you are looking at matters. Live registration state. On load the screen callsadminApi.trunkRegState(orgId), which returns a per-trunk record:
This call is best effort. It runs in parallel with the table load and
its rejection is swallowed — the list still renders if the lookup fails.
The stored
status column. When live state is unavailable, the chip
falls back to the status column on the trunk row, which is one of:
status is a save-time constant, not a health signal. It is written
with the row; it does not update as the trunk’s registration comes and
goes.
Practical reading of the chip:
- A chip backed by live state, with a recent
ts_ms, is a real registration signal. Usecodeto tell an auth failure from a reachability failure. - A chip backed only by
statustells you what was stored at save time and nothing about right now. A green chip here is not proof that the trunk is registered. - A trunk with
require_registration = falsenever produces outbound REGISTER state at all, so it will always read from the storedstatus.
Field reference
Every field below is persisted on thetrunk row and mirrored into the
Redis payload the gateway reads.
The endpoint banner above the table shows your org’s SIP and WebRTC
domains and the signalling ports TeleQuick listens on:
5060 UDP/TCP and 5061 TLS.
Related
- Telemetry — the RTP, jitter, and MOS metrics to watch after changing ptime or the port window
- Telephony Metrics — healthy ranges for the audio quality numbers these settings move