rapid-honey-43838
02/28/2026, 2:13 PMtall-airline-16756
02/28/2026, 2:13 PMtall-airline-16756
02/28/2026, 2:13 PMtransfer_sip_participant method with a TransferSIPParticipantRequest including:
◦ `room_name`: the room where the call is happening
◦ `participant_identity`: the SIP participant’s identity
◦ `transfer_to`: the destination SIP URI (e.g., <sip:payment-ivr@your-pci-provider.com>) or a tel: number
Example (Python-like):
await job_ctx.api.sip.transfer_sip_participant(
api.TransferSIPParticipantRequest(
room_name=job_ctx.room.name,
participant_identity=sip_participant.identity,
transfer_to="<sip:payment-ivr@your-pci-provider.com>",
)
)
1. Expected behavior after initiating the transfer
• The agent session ends and the call is handed off to the destination (this is a cold transfer — the agent does not stay on the line).
1. Verify trunk configuration and caller ID behavior
• Ensure your SIP trunk is configured to allow REFER and preserve or set caller ID as needed. If the trunk rewrites caller ID or doesn’t allow transfers, the transfer can fail or present the wrong caller ID.
If you’d like, tell me:
• which SIP provider you’re using (e.g., Twilio), and
• the destination format you plan to use (sip: URI vs tel:),
and I’ll provide provider-specific notes and any extra configuration tips.
Sources: Handling payments with PCI compliance | LiveKit | Agents telephony integration | LiveKit Documentation | Preserve caller ID during SIP transfers with Twilio | LiveKitrapid-honey-43838
02/28/2026, 2:25 PMtall-airline-16756
02/28/2026, 2:26 PM143.223.88.0/21 and 161.115.160.0/19. If this is what you need, tell me which region (US, EU, India, etc.) and I’ll point to the exact CIDRs for that region.
• If you’re using a self‑hosted LiveKit server and want its public IP: check the public IP assigned by your cloud provider or DNS record for the VM/load balancer. For example, on AWS you can view the Elastic IP in the EC2 console or run curl <http://ifconfig.me|ifconfig.me> from the server to show its public IP.
• If you need the IP for a specific room/participant or ephemeral media connection: LiveKit normally uses domain names and WebRTC (ICE) for media; clients connect via hostnames (your LiveKit domain) and peer ICE candidates. There’s generally no fixed per‑call IP you need to hardcode.
Tell me which of the three (Cloud egress blocks, self‑hosted server public IP, or per‑call/media IP) you mean and which region or provider you’re using, and I’ll give precise steps or the exact CIDRs to use.
Sources: Support data sovereignty in India | LiveKit | Running LiveKit on AWSrapid-honey-43838
02/28/2026, 2:49 PMtall-airline-16756
02/28/2026, 2:49 PMrapid-honey-43838
02/28/2026, 2:50 PMtall-airline-16756
02/28/2026, 2:50 PM<sip:user@your-trunk.sip>.twilio.com). Test an inbound call via Twilio to ensure Zoiper rings and answers.
3) Prepare the transfer destination format
• Use a SIP URI as the transfer target. Example:
◦ sip:your-zoiper-username@your-twilio-sip-domain
• Alternatively, you can use a tel: number if you route through PSTN, but since Zoiper registers to a Twilio SIP URI, prefer the sip: URI.
4) Use LiveKit’s TransferSIPParticipant API to initiate a cold transfer
• Identify the SIP participant in the LiveKit room (the participant representing the call).
• Call transfer_sip_participant with room_name, participant_identity, and transfer_to set to the SIP URI.
Example (Python-like):
await job_ctx.api.sip.transfer_sip_participant(
api.TransferSIPParticipantRequest(
room_name=job_ctx.room.name,
participant_identity=sip_participant.identity,
transfer_to="sip:your-zoiper-user@your-twilio-sip-domain",
)
)
• This initiates a cold transfer: the agent drops and the call is handed off to the destination.
5) Post-transfer behavior and verification
• After the transfer, confirm Zoiper receives the incoming call and the session completes.
• If the transfer fails, check:
◦ Twilio trunk logs for rejected REFERs or authentication issues.
◦ Whether Twilio rewrote or blocked the REFER or caller ID.
◦ LiveKit logs for errors from the transfer_sip_participant request.
6) Common troubleshooting checks
• Caller ID/From header: Some trunks rewrite or require specific From headers. Ensure Twilio accepts the From header LiveKit sends or configure Twilio to accept/rewrite appropriately.
• Authentication: Ensure Twilio trunk will accept calls for the destination SIP URI without additional auth or that Zoiper’s registration matches Twilio routing rules.
• Network/firewall: If any intermediate firewall is present, ensure Twilio and LiveKit egress/ingress are allowed. (LiveKit Cloud uses regional egress IP blocks; if you need those CIDRs, tell me your LiveKit region and I’ll provide them.)
If you’d like, I can:
• Provide an example transfer_to URI formatted specifically for your Twilio domain,
• Walk through reading Twilio’s transfer logs if you paste an error snippet,
• Or show a short example in another language (Node/Go) if you need it. Which would help most right now?rapid-honey-43838
02/28/2026, 2:51 PMtall-airline-16756
02/28/2026, 2:51 PMtransfer_to is a valid SIP URI Twilio will route to (e.g., <sip:user@your-trunk.sip>.twilio.com) — malformed URIs can cause rejections.
• LiveKit credentials/permissions: Confirm the LiveKit transfer API call is authorized and that the SIP participant identity is correct (so LiveKit is actually issuing the transfer to Twilio).
• Firewall/network: If you have IP restrictions, ensure LiveKit or your server can reach Twilio; some networks may respond with 403-like behavior when a service is blocked.
What I need from you to diagnose
1. The exact error details or logs:
◦ LiveKit logs around the transfer_sip_participant call (error message, stack, HTTP response if present).
◦ Twilio SIP Trunk logs showing the incoming REFER or call attempt and the 403 reason (Twilio’s debugger/log timestamp helps).
1. The transfer_to value you are using (obscure any sensitive parts if needed). Example: <sip:zoiper-user@your-trunk.sip>.twilio.com.
2. Confirmation that Twilio trunk has Call Transfer (SIP REFER) and PSTN Transfer enabled.
3. Whether Zoiper registers directly to Twilio (yes/no) and any custom authentication or IP ACLs on Twilio.
4. If possible, the time (UTC) when you attempted the transfer so I can match logs you paste.
Immediate troubleshooting steps you can try now
1. Reproduce and capture logs:
◦ Invoke the transfer and capture LiveKit logs and Twilio request logs for the same timestamp.
1. Test a manual INVITE via Twilio to the same SIP URI to confirm Twilio will route a normal call to Zoiper.
2. Try transferring to a tel: number (if allowed) to verify whether REFERs in general are accepted by Twilio from LiveKit.
3. Check Twilio trunk Auth/ACLs: ensure the destination URI is permitted and that Twilio won’t require extra authentication for that target.
If you paste:
• the Twilio SIP log entry showing the 403 (or the LiveKit error output), and
• the transfer_to value you used,
I’ll analyze the headers and give a precise fix (e.g., adjust From header, enable a Twilio setting, or change the transfer URI format).rapid-honey-43838
02/28/2026, 2:51 PMtall-airline-16756
02/28/2026, 2:52 PM<sip:user@your-sip-domain.com>) as the transfer_to. Malformed URIs or unsupported schemes can be rejected.
• From/Caller-ID and headers: Some SIP servers enforce policies on the From, Contact, or Referred-By headers. If these look unexpected, the server may return 403.
LiveKit-side steps to verify
1. Use the Transfer API correctly:
◦ Call transfer_sip_participant with room_name, participant_identity, and:
▪︎ transfer_to="<sip:zoiper-user@your-sip-domain.com>"
◦ This initiates a cold transfer (agent drops, call handed off).
1. Ensure your LiveKit access token has SIP call permissions:
◦ Include the SIP grant (SIPCall = true) in the token so SIP operations are permitted.
1. Confirm how LiveKit authenticates to your SIP domain:
◦ If your SIP server requires IP-based allowlisting, ensure LiveKit’s outbound IPs are whitelisted.
◦ If credential-based auth is required, ensure LiveKit is configured with the correct SIP credentials.
Concrete checks to run now
1. Reproduce the transfer and capture logs:
◦ Copy the LiveKit error output for the failed transfer_sip_participant call.
◦ Collect the SIP server logs for the same timestamp to see the incoming REFER and the exact 403 reason.
1. Inspect the REFER request on your SIP server:
◦ Look at Refer-To, From, Referred-By, and Contact headers in the incoming request. Note any headers your server rejects or flags.
1. Test a manual REFER (or INVITE) from an external client:
◦ Use a SIP testing tool (sipp, sofia, or another SIP endpoint) to send a REFER to your domain in the same format LiveKit would. If that also yields 403, the issue is on the SIP server side (policies/auth).
1. Temporarily relax restrictions (if possible):
◦ Allow the domain/user in your SIP server policy to accept REFERs from LiveKit IPs or credentials, then retry to confirm policy is the blocker.
Likely fixes depending on root cause
• If SIP server blocks REFERs: Enable or allow REFER handling for the domain/target user.
• If authentication fails: Either whitelist LiveKit egress IPs or configure credential-based auth in LiveKit to match your SIP trunk credentials.
• If headers are rejected: Adjust your SIP server policy to accept the `From`/`Refer-To` values LiveKit sends or configure header rewriting on your SIP server.
• If URI format is wrong: Use <sip:user@your-sip-domain.com> exactly (no extra params) as transfer_to.
If you share two things I can give a precise fix
1. The transfer_to value you used (obscure credentials/user if needed).
2. The SIP server log entry for the incoming REFER showing the 403 (or the LiveKit error log around the same time).
With those I’ll:
• Inspect the headers and point out which header or value likely triggered the 403.
• Give the exact change (allowlist, header rewrite, or token/credential change) to make the transfer succeed. Sources: Firewall Tips for LiveKit Connectivity | LiveKit | Pass UUI data to Genesys Cloud during SIP transfers | LiveKit | Handling payments with PCI compliance | LiveKit | server-sdk-kotlin | livekit/livekit_composite | DeepWiki | How VICIdial handles bridging, transfers, and SIP calls | LiveKitrapid-honey-43838
02/28/2026, 2:52 PMtall-airline-16756
02/28/2026, 2:52 PMtransfer_to SIP URI format.
• Capture the SIP REFER on your server to confirm the rejection reason if it still fails.
Step-by-step checklist
1) Configure SIP credentials in LiveKit
• Add the SIP trunk/account credentials (username/password) in LiveKit’s SIP agent or trunk configuration so LiveKit can authenticate outbound requests to your SIP domain. If LiveKit is not authenticating, your SIP server will reject the REFER with 403.
• Ensure the credential used by LiveKit maps to the destination (Zoiper) or a routing rule that delivers calls to Zoiper’s registered user.
2) Ensure the access token allows SIP operations
• When issuing access tokens for the agent performing the transfer, include the SIP grant (SIPCall = true). Without this SIP grant, LiveKit may not be permitted to run SIP operations.
3) Use the correct transfer target format
• Use a SIP URI as transfer_to, for example:
◦ transfer_to = "sip:zoiper-user@your-sip-domain.com"
• Do not use malformed URIs or add unexpected params that your SIP server may reject.
4) Confirm SIP REFER is allowed for that credential
• Your SIP server must accept REFERs when the request is authenticated by the credential LiveKit presents.
• Some servers allow INVITEs from an authenticated account but block REFERs. Enable or permit REFER for the account/trunk used.
5) Whitelist IPs if you rely on IP authentication
• If your SIP server requires IP allowlisting instead of credentials, ensure LiveKit’s outbound IPs are whitelisted. If you use credential auth, this is less likely needed — but check both.
6) Inspect headers that commonly trigger 403
• If authentication succeeds but your server still returns 403, inspect the incoming REFER headers on your SIP server:
◦ Refer-To, From, Referred-By, Contact
• Some servers enforce policies on From or Referred-By values. If these headers don’t align with what your server expects, configure the server to accept or rewrite them.
7) Reproduce and collect logs
• Reproduce the failing transfer and capture:
◦ LiveKit transfer error logs (timestamped)
◦ SIP server logs for the incoming REFER (full request and reason for 403)
• The SIP server log will usually say whether the 403 is due to auth failure, denied method (REFER), or policy.
If you want, I can give a focused fix — please share:
• The exact transfer_to value you used (mask any sensitive parts).
• The SIP server log entry for the incoming REFER that shows 403 (or the LiveKit error output at the same timestamp).
What I’ll do with those:
• Check if LiveKit is sending auth credentials or not, and whether the REFER headers look acceptable to your SIP domain.
• Recommend the exact config change: add credentials to LiveKit, adjust server policies to accept REFER for that user, or adjust headers/caller ID rewriting.
If you’d prefer, I can also walk you through a quick test using a SIP tool (sipp) to simulate an authenticated REFER to your SIP domain so we can confirm whether the server or LiveKit is the blocker. Which would you like to try next?tall-airline-16756
02/28/2026, 2:58 PMrpc error: code = PermissionDenied desc = sip status: 403: Forbidden. I’ll help you pinpoint why LiveKit is being rejected and what to change.
Why this 403 commonly happens (short)
• LiveKit’s transfer request is being rejected by your SIP domain because of authentication/authorization or SIP policy (REFER not allowed).
• The most frequent causes here are: LiveKit not presenting valid SIP credentials for the outbound request, the token used lacks the SIP grant (so LiveKit isn’t allowed to perform SIP operations), or your SIP server refuses REFERs from the authenticated account.
Concrete next steps to resolve
1) Confirm the access token used by the CLI has the SIP grant
• Ensure the agent token includes the SIP grant (SIPCall = true). Without that, LiveKit will not be permitted to initiate SIP transfers and you can get PermissionDenied/403.
• If you generate tokens programmatically, add the SIP grant to the token before running the CLI command.
2) Configure SIP credentials for LiveKit outbound calls
• Your SIP domain requires username/password auth for Zoiper. Make sure LiveKit is configured to use those credentials (or a trunk credential that routes to Zoiper) when sending outbound SIP requests.
• If your LiveKit project has a SIP trunk/agent configuration area, add the credential there so LiveKit will authenticate when sending the REFER/INVITE.
3) Verify your --to format
• Use a clean SIP URI without mailto/encoding. Example:
◦ --to "sip:+12762219741@lk-test-saurabh.sip.twilio.com"
• Ensure no extra brackets or mailto formatting are used in the CLI value.
4) Ensure your SIP server accepts REFER from that credential
• Confirm that the account LiveKit authenticates as is permitted to send REFER requests and that the SIP server routes REFER to Zoiper’s registered user.
• Some servers permit INVITE but block REFER for security—enable REFER for the account if needed.
5) Capture logs for the failing attempt
• Re-run the transfer and capture:
◦ LiveKit server logs around the CLI call (timestamp).
◦ Your SIP server logs for the incoming REFER/INVITE showing the 403 reason.
• The SIP server log will usually say whether rejection was due to auth, method blocked, or header policy.
Quick checklist to try now
• Regenerate the agent token with SIP grants and retry the same CLI command.
• Confirm LiveKit is configured with the SIP username/password used by Zoiper (or a routing credential).
• Use the plain SIP URI in --to, e.g. <sip:+12762219741@lk-test-saurabh.sip>.twilio.com.
• If it still 403s, paste the LiveKit server log entry and the SIP server log for the same timestamp (you can redact secrets); I’ll inspect headers and tell you exactly which value to change.
If you’d like, I can show an example of creating a token with the SIP grant or a sample CLI invocation after token creation—tell me which you prefer.rapid-honey-43838
02/28/2026, 3:02 PMtall-airline-16756
02/28/2026, 3:02 PMSIPCall = true).
Step 1 — Create an outbound SIP trunk with credentials
• Use the LiveKit API/CLI to create a SIP outbound trunk and include the authentication username and password that your SIP server (the domain Zoiper registers to) expects.
Example (Python-like SDK):
from livekit import api
await lk_api.sip.create_sip_outbound_trunk(
api.CreateSIPOutboundTrunkRequest(
trunk=api.SIPOutboundTrunkInfo(
name="Zoiper-Trunk",
sip_uri="sip:<http://your-sip-domain.com|your-sip-domain.com>",
auth_username="zoiper_username",
auth_password="zoiper_password",
# optional: allowed_addresses = ["<optional ip>"]
)
)
)
Example (CLI):
lk sip outbound create \
--name "Zoiper-Trunk" \
--sip-uri "sip:<http://your-sip-domain.com|your-sip-domain.com>" \
--auth-username "zoiper_username" \
--auth-password "zoiper_password"
Step 2 — Use the trunk when initiating the outbound call/transfer
• When you create a SIP participant or initiate the transfer, reference the sip_trunk_id of the trunk you created so LiveKit sends the outbound request authenticated with those credentials.
Example creating an outbound participant (used for transfer or direct outbound call):
await ctx.api.sip.create_sip_participant(
api.CreateSIPParticipantRequest(
room_name="current_room",
sip_trunk_id="ST_outbound_trunk_id", # ID returned when creating trunk
sip_call_to="<sip:zoiper-user@your-sip-domain.com>",
participant_identity="outbound_to_zoiper",
wait_until_answered=True,
)
)
For cold transfer specifically:
• Use the same transfer_sip_participant call, but ensure LiveKit is configured with the outbound trunk so the REFER/INVITE flows out using the trunk credentials.
Step 3 — Ensure token grants and permissions
• The agent or service invoking the transfer must have an access token that includes the SIP grant:
◦ SIPCall = true
• Without the SIP grant, LiveKit will deny SIP operations and you can see PermissionDenied/403.
Step 4 — Verify your SIP server accepts authenticated REFERs/INVITEs
• Confirm that the credential you used allows sending REFER (some SIP servers permit INVITE but block REFER for certain accounts).
• If your SIP server enforces header policies, ensure it accepts the From, Refer-To, and Referred-By headers LiveKit sends, or add a rule to accept/rewite them for the authenticated account.
Step 5 — Test and collect logs if still failing
• Reproduce the transfer and check:
◦ LiveKit logs for the transfer call (timestamp).
◦ Your SIP server logs for the incoming authenticated request and the reason for 403 (authentication failure, method not allowed, header policy).
• If it still fails, paste:
◦ The `sip_trunk_id`/`transfer_to` value (you can redact passwords),
◦ The SIP server log entry showing the 403 (redact secrets).
I’ll inspect the headers and tell you exactly whether LiveKit is failing to send credentials or if the SIP server is rejecting a header/method.
Quick checklist to try now
• Create outbound trunk with `auth_username`/`auth_password`.
• Use that trunk’s ID in your outbound call/transfer request.
• Regenerate and use an access token that has SIPCall grant.
• Retry and check the SIP server logs for the incoming request details.
If you want, tell me:
• Which method you prefer (CLI or SDK) and your LiveKit region,
• The exact transfer_to SIP URI (masking sensitive parts),
and I’ll provide the precise CLI/SDK command and a sample token snippet ready to run.
Sources: Python SDKs | livekit/livekit_composite | DeepWiki | Agents telephony integration | LiveKit Documentation | server-sdk-kotlin | livekit/livekit_composite | DeepWikirapid-honey-43838
02/28/2026, 3:04 PMtall-airline-16756
02/28/2026, 3:04 PMSIPCall = true) so LiveKit is allowed to perform SIP operations.
Quick checklist and minimal steps
1. Create outbound trunk with credentials (CLI or API)
◦ sip_uri = "sip:your-sip-domain.com"
◦ auth_username = "zoiper_username"
◦ auth_password = "zoiper_password"
1. Use the trunk for the transfer
◦ When calling transfer_sip_participant or creating an outbound SIP participant, set sip_trunk_id to the trunk you created and transfer_to to the SIP URI (<sip:zoiper-user@your-sip-domain.com>).
1. Ensure token grants
◦ Access token used for the transfer includes SIPCall = true.
1. Verify server accepts REFERs for that credential
◦ Confirm your SIP server allows REFER from that authenticated account or adjust policy.
If you want, I can:
• Provide the exact CLI or SDK commands for your environment (Python/Node/CLI).
• Show an example of creating a token with the SIP grant.
• Inspect logs if you paste the LiveKit error and the SIP server log for the failed REFER.
Which of these would help you next?rapid-honey-43838
02/28/2026, 3:07 PMtransfer_sip_participant call, but ensure LiveKit is configured with the outbound trunk so the REFER/INVITE flows out using the trunk credentials., how ?tall-airline-16756
02/28/2026, 3:08 PMtransfer_sip_participant) uses the outbound trunk credentials (username/password) so your SIP domain (Zoiper) accepts the REFER/INVITE. Below are the concrete steps: create an outbound trunk with credentials, confirm LiveKit will use that trunk for outbound SIP signaling, and call the transfer API referencing the trunk. I include CLI and SDK examples and quick verification steps.
Step 1 — Create an outbound SIP trunk with username/password
• Create a SIP outbound trunk in LiveKit containing:
◦ sip_uri: your SIP domain (e.g., sip:<http://your-sip-domain.com|your-sip-domain.com>)
◦ auth_username / auth_password: the credential LiveKit should present
◦ optional: allowed_addresses or other routing options if needed
Example (CLI)
lk sip outbound create \
--name "Zoiper-Trunk" \
--sip-uri "sip:<http://your-sip-domain.com|your-sip-domain.com>" \
--auth-username "zoiper_username" \
--auth-password "zoiper_password"
Example (Python SDK — illustrative)
from livekit import api
resp = await lk_api.sip.create_sip_outbound_trunk(
api.CreateSIPOutboundTrunkRequest(
trunk=api.SIPOutboundTrunkInfo(
name="Zoiper-Trunk",
sip_uri="sip:<http://your-sip-domain.com|your-sip-domain.com>",
auth_username="zoiper_username",
auth_password="zoiper_password",
)
)
)
# note resp will include the trunk id (e.g., resp.trunk.id)
Step 2 — Note the trunk ID
• Save the returned trunk id (e.g., ST_abcdef123). You’ll reference this when creating outbound calls or performing transfers.
Step 3 — Ensure your token has SIP permissions
• The agent/service initiating the transfer must have an access token that includes the SIP grant (SIPCall = true). Without it, LiveKit will deny SIP operations.
Step 4 — Initiate the cold transfer so LiveKit uses that trunk
• When doing a transfer, instruct LiveKit to use the outbound trunk by creating an outbound SIP participant through the trunk or by ensuring the trunk selection is applied to the transfer flow. Two common patterns:
A) Preferred pattern — create an authenticated outbound call via the trunk, then transfer:
1. Create an outbound SIP participant using sip_trunk_id and sip_call_to (this makes LiveKit send an authenticated INVITE via that trunk).
2. Transfer the LiveKit participant to that created SIP participant (or use the trunk in the transfer API if your environment supports specifying trunk on transfer).
Example creating outbound participant (Python-like):
out_part = await ctx.api.sip.create_sip_participant(
api.CreateSIPParticipantRequest(
room_name="room1",
sip_trunk_id="ST_abcdef123", # trunk created in step 1
sip_call_to="<sip:zoiper-user@your-sip-domain.com>",
participant_identity="out_to_zoiper",
wait_until_answered=False,
)
)
# then transfer the original participant to out_part.identity if required
await ctx.api.sip.transfer_sip_participant(
api.TransferSIPParticipantRequest(
room_name="room1",
participant_identity="current_agent_identity",
transfer_to=out_part.identity, # or the sip URI depending on your flow
)
)
B) Direct transfer with trunk configured (if your LiveKit deployment allows specifying trunk on transfer)
• Some LiveKit setups route outbound REFER/INVITE through the default or matching trunk for the SIP domain automatically if a matching outbound trunk exists. In that case, call:
await ctx.api.sip.transfer_sip_participant(
api.TransferSIPParticipantRequest(
room_name="room1",
participant_identity="agent_identity",
transfer_to="<sip:zoiper-user@your-sip-domain.com>",
)
)
• LiveKit will choose the outbound trunk matching <http://your-sip-domain.com|your-sip-domain.com> and send the REFER/INVITE authenticated with the trunk credentials. If your deployment requires explicitly passing sip_trunk_id on transfer, use pattern A.
Step 5 — Verify the SIP server sees authentication
• Reproduce the transfer and inspect your SIP server logs. Look for Authorization: Digest headers or authenticated session markers on the incoming INVITE/REFER — the request should show the auth username you configured.
• If your server still returns 403:
◦ Confirm the `auth_username`/`auth_password` are correct.
◦ Verify the SIP server accepts REFER for that account.
◦ Check header policy (From/Refer-To) — server may reject based on headers even when auth is valid.
Quick troubleshooting checklist
• Did trunk creation return a trunk id? Use it when creating outbound participant or ensure domain matches so LiveKit selects it automatically.
• Does the agent token include SIPCall = true?
• Does your SIP domain accept Digest auth for outbound calls and allow REFER from that authenticated user?
• Review SIP logs to confirm LiveKit included the Authorization header and check the exact 403 reason.
If you want, I can:
• Show exact CLI/SDK commands tailored to your environment (Node/Python/CLI).
• Inspect a sample SIP server log entry for the incoming request (redact secrets) and point out which header/credential is failing.
Which would you like next?rapid-honey-43838
02/28/2026, 3:18 PMtall-airline-16756
02/28/2026, 3:18 PMlk agent list
◦ Stream logs: lk agent logs --id <agent-id>
◦ Reproduce the transfer while streaming; note the exact timestamp.
• If you run a self‑hosted LiveKit server:
◦ Tail the server logs (systemd, Docker logs, or your logging sink). Example:
▪︎ systemd: journalctl -u livekit -f
▪︎ Docker: docker logs -f <livekit_container>
• Enable verbose debug if needed (helps show SIP details):
◦ Start agent/server with debug or set log level to DEBUG. Then reproduce the transfer.
• What to copy from LiveKit logs:
◦ The transfer API call entry (transfer_sip_participant) and any returned error lines.
◦ Any stack trace or RPC error showing PermissionDenied / 403.
◦ Timestamps for each logged event.
2) SIP domain (your SIP server / trunk) logs — capture the incoming REFER/INVITE
• Access your SIP server or provider dashboard logs (where Zoiper registers):
◦ Look for inbound requests at the same timestamp as the LiveKit log.
◦ Find the incoming REFER (or INVITE if LiveKit sends an INVITE during transfer) and the 403 response.
• What to capture from SIP logs:
◦ Full SIP request text for the REFER/INVITE (start line and headers).
◦ The Authorization header or WWW-Authenticate reply (redact secrets).
◦ The exact reason or reason phrase accompanying 403 Forbidden.
◦ Source IP of the request.
• If Zoiper is the endpoint, enable SIP debug in Zoiper:
◦ Settings → Advanced → Debug → Enable SIP logging (reproduce transfer and save logs).
3) What to inspect in the SIP request/response
• Presence of Authorization: Digest ... header — confirms LiveKit sent credentials.
• Refer-To, From, Referred-By, and Contact headers — servers often enforce policies on these.
• Source IP vs allowed IPs — confirm the request comes from an allowed IP if IP whitelisting is used.
• Authentication challenge flow: if server returns 401 then LiveKit should retry with credentials; if it returns 403 it’s an authorization/policy rejection.
4) Correlate timestamps
• Use the exact timestamp from the LiveKit log when the transfer was initiated.
• Match that with the SIP server log for the incoming request and the 403 response.
• This shows whether LiveKit’s request reached the SIP server and whether it included auth.
5) Quick reproduction steps to generate useful logs
1. Start LiveKit logs streaming (CLI or server tail).
2. Enable SIP logging on your SIP server and Zoiper.
3. Reproduce the cold transfer.
4. Collect:
◦ LiveKit log entries around the timestamp (copy 30s before/after).
◦ SIP server request/response text for that timestamp.
◦ Zoiper debug log (if available).
6) Share redacted snippets for help
• If you want me to inspect, paste (you can redact passwords/secrets):
◦ LiveKit error lines around the transfer (with timestamp).
◦ The SIP request/response text showing the 403 (include headers but redact secrets).
• I’ll point out whether LiveKit sent credentials, which header caused the rejection, or whether it’s a server policy issue.
If you tell me:
• How you host LiveKit (LiveKit Cloud vs self‑hosted) and
• Which SIP server/provider you use,
I’ll provide the exact commands or dashboard locations to retrieve logs for each system. Which environment should I tailor instructions for?
Sources: Where to find your Agent Logs | LiveKit | Handling payments with PCI compliance | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation | Pass UUI data to Genesys Cloud during SIP transfers | LiveKitrapid-honey-43838
02/28/2026, 3:25 PMtall-airline-16756
02/28/2026, 3:25 PM--log-level flag when starting)
D. SIP trunk / SIP server logs (your SIP domain)
1. Provider dashboard (if using a hosted SIP provider): open the trunk/session logs and filter by the transfer timestamp. Look for incoming REFER/INVITE and the 403 response.
2. Self‑hosted SIP server (e.g., Asterisk, FreeSWITCH, Kamailio):
◦ Enable SIP debug (example Asterisk):
▪︎ asterisk -rvvv
▪︎ sip set debug on
◦ For Kamailio/OpenSIPS, increase log level in conf and tail logs (kamailio -DD -E or check /var/log/syslog).
1. Capture raw SIP traffic for exact headers:
◦ tcpdump -i any -w sip.pcap port 5060 or port 5061
◦ Open sip.pcap in Wireshark to inspect Refer-To, From, Authorization headers, and the 403 reason.
E. Zoiper client — enable SIP debug
1. Open Zoiper settings → Advanced → Debug/SIP logging.
2. Enable SIP logging and reproduce the transfer.
3. Export the log from Zoiper (or copy the relevant timestamped entries showing the incoming REFER and any response).
F. What to collect (minimum useful data)
• LiveKit logs (30s before/after transfer) showing the transfer API call and any error (PermissionDenied / 403).
• SIP server incoming request and 403 response (raw SIP request + headers).
• Zoiper debug log for same timestamp (if available).
• Exact transfer_to SIP URI you used (you can redact sensitive parts).
G. Quick reproduction workflow
1. Start LiveKit logs streaming (A, B or C).
2. Enable SIP logging on your SIP server and Zoiper (D, E).
3. Perform the cold transfer.
4. Save the three logs and note the exact UTC timestamp.
If you want, tell me:
• Whether you’re using LiveKit Cloud or self‑hosted,
• Which agent runtime (Node or Python), and
• Which SIP server/provider you use.
I’ll then give the precise command(s) tailored to your environment and explain what exact log lines to look for (e.g., Authorization header presence, Refer‑To format, and the 403 reason).
Sources: Server startup modes | LiveKit Documentation | Where to find your Agent Logs | LiveKit | Streamline troubleshooting with Agent Observability | Streamline troubleshooting with Agent Observability | Preserve caller ID during SIP transfers with Twilio | LiveKit