lk does not allow multiple trunks with empty numbe...
# ask-ai
r
lk does not allow multiple trunks with empty numbers. How can I create separate inbound trunks which which whitelists a disjoint set of ip addresses
t
Thanks for reaching out, Saurabh. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about creating separate inbound trunks that each whitelist a disjoint set of IP addresses when the system doesn’t allow multiple trunks with empty
numbers
. Good news: you can create multiple inbound trunks without numbers as long as each trunk is unique in another configurable property — specifically
allowed_addresses
. Create each
SIPInboundTrunkInfo
with a distinct
allowed_addresses
list (and a unique
name
if helpful). That satisfies the uniqueness check and gives you IP-based separation for inbound traffic. Recommended approach (high level): • For each logical trunk you want, set: ◦ `name`: a unique identifier (e.g., "trunk-region-a") ◦ `numbers`: omit or leave empty if you don’t need phone numbers ◦ `allowed_addresses`: list of IPs you want that trunk to accept • Create the trunks via the LiveKit API or CLI using
create_sip_inbound_trunk
(or equivalent). Example (Python-like pseudocode):
Copy code
trunk1 = create_sip_inbound_trunk({
    "name": "Trunk-Region-A",
    "numbers": [],  # empty
    "allowed_addresses": ["203.0.113.10", "203.0.113.11"]
})

trunk2 = create_sip_inbound_trunk({
    "name": "Trunk-Region-B",
    "numbers": [],  # empty
    "allowed_addresses": ["198.51.100.20", "198.51.100.21"]
})
A few quick notes and checks: • Ensure each trunk’s
allowed_addresses
lists are disjoint (no overlapping IPs) so each trunk only accepts its intended sources. • If you run into a uniqueness error when creating trunks, make sure
name
and any other trunk fields aren’t identical between trunks. • Once created, reference these trunks in your routing/dispatch rules as needed. If you want, I can: • Show the exact API request payload for the language/SDK you’re using (Python, Go, CLI, etc.) • Help verify why a trunk creation may be failing if you share the error message or the request payload you tried. Which SDK or method are you using to create the trunks? Sources: sip | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki | How to do call transfers with Five9 | LiveKit | examples/voice_agents | livekit/livekit_composite | DeepWiki
r
how can I get sip call events from livekit ?
t
You're asking how to receive SIP call events from LiveKit — good question. You can get SIP call events two main ways depending on whether you need durable notifications or real‑time in‑room signals: 1) Webhooks — durable, server-side notifications • What you get: SIP lifecycle events (e.g., participant_joined, participant_left, room_started, room_finished, track_published). SIP participants include attributes like
sip.callStatus
,
sip.phoneNumber
, and
sip.trunkID
. • How it works: LiveKit will POST signed event payloads to your webhook endpoint whenever SIP-related events occur. • When to use: You need reliable delivery, logging, or processing outside of an active room (e.g., billing, analytics, CRM updates). • Implementation notes: ◦ Configure your webhook URL in your LiveKit settings (or server config). ◦ Verify the signature on incoming webhooks using your API secret. ◦ Inspect participant attributes in the webhook payload to read SIP fields (e.g.,
sip.callStatus
). 2) In-room event listeners / agent listeners — real-time, in-process events • What you get: Immediate events in the room such as
participant_connected
,
participant_disconnected
, and
participant_attributes_changed
. You can read SIP-specific attributes on the participant (including call status transitions like
dialing
,
ringing
,
active
,
hangup
,
automation
). • How it works: An agent or backend connected to the room registers handlers for room/participant events and reacts immediately (logging, routing, updating UI, etc.). • When to use: You need low-latency handling while the call is active (e.g., live routing, IVR automation, agent desktop updates). • Implementation notes: ◦ Listen for participant connect/disconnect and attributes-changed events. ◦ Check
participant.kind == "SIP"
(or the SDK’s SIP participant kind) and read
participant.attributes["sip.callStatus"]
,
sip.phoneNumber
, etc. Which should you choose? • Choose webhooks if you need durable, out-of-room notifications and easy integration with web services. • Choose in-room listeners if you need immediate, live reactions while the call/room is running. • You can use both: webhooks for durable audit/logging and in-room listeners for real-time behavior. If you want, I can: • Show an exact webhook handler example in the language you use (Python/Node/Go) and how to verify signatures. • Show sample code for in-room event listeners for the SDK/agent you’re using (Python, JS, or the Agent framework). Which environment/SDK do you want the example for, and are you aiming for webhooks, in-room listeners, or both? Sources: sip | livekit/livekit_composite | DeepWiki | SIP Lifecycle Management Agent | LiveKit Documentation | Best practices for managing webhook event streams | LiveKit | Python SDKs | livekit/livekit_composite | DeepWiki
r
when is event
participant_attributes_changed
published and how can I consume it ?
t
You're asking when the
participant_attributes_changed
event is published and how to consume it — I’ll explain both clearly and show how to use it for SIP call state updates. When the event is published • The event is fired whenever a participant's attributes are updated. That includes: ◦ Server-side updates (e.g., calling the server API to update participant attributes). ◦ Client SDK calls to set attributes (for that participant or others, as permitted). ◦ SIP lifecycle updates (attributes such as
sip.callStatus
,
sip.phoneNumber
,
sip.trunkID
being changed as the call progresses). • The event is propagated asynchronously. In distributed deployments, attribute updates may arrive slightly later to participants connected to different SFU nodes, so rely on the event rather than immediate property reads to observe changes. What the event delivers • The handler receives a map/dictionary of only the attributes that changed (not the full attribute set). • Typical SIP attribute keys you might see:
sip.callStatus
(values like
dialing
,
ringing
,
active
,
hangup
,
automation
),
sip.phoneNumber
,
sip.trunkID
. • Always check
participant.kind
(or SDK-specific participant type) to ensure you’re processing SIP participants. How to consume it 1) In a backend agent or server process (Python example)
Copy code
@ctx.room.on("participant_attributes_changed")
def on_participant_attributes_changed(changed_attributes: dict, participant):
    # Only the changed attributes are provided
    if participant.kind == "SIP":
        if "sip.callStatus" in changed_attributes:
            new_status = changed_attributes["sip.callStatus"]
            print(f"SIP participant {participant.identity} status -> {new_status}")
        if "sip.phoneNumber" in changed_attributes:
            print(f"Phone number updated: {changed_attributes['sip.phoneNumber']}")
2) In a web client (TypeScript / JS example)
Copy code
room.on(RoomEvent.ParticipantAttributesChanged, (changedAttributes, participant) => {
  if (participant.kind === "SIP" && changedAttributes["sip.callStatus"]) {
    console.log(`SIP call status changed: ${changedAttributes["sip.callStatus"]}`);
  }
});
3) Best practices and notes • Use the event handler rather than polling
participant.attributes
, because the event provides the precise changes and avoids race conditions. • Expect asynchronous propagation; your handler should tolerate short delays. • If you need the current full attribute map after a change, read
participant.attributes
inside the handler (it will reflect latest state after the event). • For SIP workflows, react to
sip.callStatus
transitions (for example, perform routing or UI updates on
ringing
→
active
→
hangup
). If you want, I can: • Provide the exact code for the SDK you’re using (JS, Python, Go, or an Agent framework). • Show a small end-to-end example that listens for
sip.callStatus
changes and triggers a follow-up action (e.g., update a CRM, notify an agent UI). Which SDK/environment should I tailor the example to? Sources: Handling asynchronous metadata updates in LiveKit | LiveKit | Server-side | livekit/livekit_composite | DeepWiki | How to detect when an agent has finished speaking | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation | Job lifecycle | LiveKit Documentation
r
For call transfering, I need IP-based authentication. at transfer target. how can i get livekit origin ip address to share to target
t
You want the LiveKit origin IP address to share with your transfer target so the target can perform IP-based authentication for call transfers — got it. Here’s exactly how to get and use the IP information, and what to do depending on your region. Summary • LiveKit Cloud offers static egress IP blocks for outbound SIP traffic in certain regions (these are the IPs you should whitelist at the transfer target). • If your LiveKit deployment is in a region without static egress IPs, static IPs are not available — instead use hostname/DNS allow‑listing or deploy an SBC/on‑prem proxy with a fixed IP. What to do next (step-by-step) 1. Tell me your LiveKit region • I can confirm the exact static IPs or DNS names to share. Which region is your service deployed in (e.g., US, EU, India, Saudi Arabia, or another region)? 1. If your region is US, EU, or India • Use the region’s static egress IP blocks (these are the origin addresses LiveKit uses for outbound SIP, including REFER transfers). • Share those IP ranges with your transfer target’s firewall/whitelist so inbound calls from LiveKit transfers are accepted. 1. If your region does NOT have static IP blocks (no static egress IPs) • Static egress IPs are not available. • Options: ◦ Ask the transfer target to allow connections by hostname (DNS allow-listing for LiveKit hostnames used by your region). ◦ Deploy a proxy/SBC with a fixed IP in front of the transfer target (this proxy will receive the LiveKit SIP traffic and forward it from a fixed IP you control). 1. Region pinning for consistent egress • To ensure outbound SIP originates from the expected regional IP block, use the region-specific SIP hostname (e.g., the region-pinned SIP domain for your deployment). This helps keep egress traffic in the region that provides static IPs. Implementation/checklist • Confirm region and corresponding static IP blocks or DNS hostnames. • Whitelist IP ranges or DNS names at the transfer target. • Test an outbound transfer and confirm the source IP on the target side (or logs) matches the expected LiveKit egress addresses. • If your target only accepts exact IPs and your region has no static IPs, set up an SBC/proxy with a stable IP in the same region. If you tell me your region (or the SIP hostname you’re using), I’ll: • Provide the exact IP ranges or DNS endpoints you should share, and • Recommend the precise hostname to use for region pinning or the proxy/SBC approach if static IPs are not available. Sources: Support data sovereignty in India | LiveKit | Support data sovereignty in Saudi Arabia | LiveKit
r
US region
t
Thanks — since you’re on the US region, you can whitelist LiveKit’s static egress IP blocks so your transfer target accepts outbound SIP (including REFER transfers) from LiveKit. US region static egress IP blocks • 143.223.88.0/21 • 161.115.160.0/19 How to use them for IP-based authentication • Share those CIDR ranges with your transfer target’s firewall or SIP trunk provider and add them to the allowlist for incoming SIP traffic. • Ensure you pin your outbound SIP requests to the US region’s SIP hostname so LiveKit egress stays within the US IP blocks (use the region-specific SIP hostname your deployment uses). • After whitelisting, run a test transfer and confirm the source IP seen by the target matches one of the CIDR ranges. Best practices and checks • Verify the transfer target logs to confirm the observed source IP belongs to one of the ranges above. • If you need strict per-trunk IP separation or additional assurance, deploy an SBC/proxy that you control (with a fixed IP) in front of the transfer target. • If you want, I can provide the exact region-pinned SIP hostname to use for your deployment and a short test checklist. Would you like the region-pinned SIP hostname and a sample test checklist to validate transfers?
r
how to invoke transfer call function tool ?
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!
r
sip transfer