How to send BYE signal to sip and how to set custo...
# ask-ai
g
How to send BYE signal to sip and how to set custom headers with BYE signal ?
t
Thanks for reaching out, YASH. 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 how to send a SIP BYE from LiveKit and how to include custom headers with that BYE. Short answer • LiveKit sends the SIP BYE when you delete the room containing the SIP participant (call). • To include custom headers on that BYE, map participant attributes to SIP headers in your inbound trunk using
attributes_to_headers
, set those participant attributes before ending the call, then delete the room. What to do (step-by-step) 1. Configure the inbound SIP trunk with an attributes→headers mapping. ◦ Add an
attributes_to_headers
section that maps LiveKit participant attribute keys to the SIP header names you want on BYE (for example, map
five9.route_reason
→
X-RouteReason
). 1. Set the participant attributes you want sent as headers. ◦ Use
update_participant
to set those attribute keys/values on the SIP participant while the call is active. ◦ Example attributes you might set:
five9.route_reason
,
five9.route_type
,
five9.route_value
,
five9.metadata
. 1. End the call (this sends BYE with the mapped headers). ◦ Call
delete_room
for the room that contains the SIP participant. LiveKit will send the SIP BYE to the SIP endpoint and include the headers mapped from the participant attributes. Important notes • If the caller hangs up first (SIP endpoint sends BYE), LiveKit will not be able to add headers to that BYE — headers are sent when LiveKit initiates the BYE by deleting the room. • This pattern is commonly used for integrations like Five9 where the IVR or contact center needs routing/metadata returned in the BYE headers. If you’d like, I can: • Show a concrete example JSON trunk configuration with
attributes_to_headers
. • Provide exact code snippets for
update_participant
and
delete_room
in the language you’re using (Python, Node, etc.). Which language or example would you prefer? Sources: Python Agents: Handling exceptions in your entrypoint | LiveKit | How to do call transfers with Five9 | LiveKit
g
provide code examples using python I need to set these headers X-route_type X-route_value X-ABDC-Queue X-ABC-SessionId X-ABDC-PersonId X-Studio-Contained X-ABDC-Language
t
Thanks — I’ll show Python examples that: • set the participant attributes that map to the SIP headers you listed, and • trigger the BYE by deleting the room. Assumptions made: • Your inbound SIP trunk is configured with
attributes_to_headers
mapping that maps the LiveKit attribute keys below to the SIP header names you want (for example,
abdc.route_type
→
X-route_type
). If you need the exact trunk JSON example, I can provide it next. 1) Example: set participant attributes (Python) • This updates the SIP participant’s attributes so they will be converted to SIP headers when LiveKit sends the BYE.
Copy code
# example_update_participant.py
from livekit import api  # adjust import to match your LiveKit client library layout
import asyncio

async def set_participant_attributes(client, room_name, participant_identity):
    # Attributes keys must match the keys used in your trunk's attributes_to_headers mapping.
    attributes = {
        "abdc.route_type": "TRANSFER",
        "abdc.route_value": "support_queue",
        "abdc.queue": "queue_123",              # maps to X-ABDC-Queue
        "abdc.iva_session_id": "iva-7890",      # maps to X-IVA-SessionId
        "abdc.person_id": "person-456",         # maps to X-ABDC-PersonId
        "abdc.studio_contained": "true",        # maps to X-Studio-Contained
        "abdc.language": "en-US"                # maps to X-ABDC-Language
    }

    req = api.UpdateParticipantRequest(
        room=room_name,
        identity=participant_identity,
        attributes=attributes
    )

    await client.room.update_participant(req)
    print(f"Updated attributes for participant {participant_identity} in room {room_name}")
Notes: • Use attribute keys that match your trunk mapping. In the example above I used keys prefixed with
abdc.
(e.g.,
abdc.route_type
). Your trunk file must map those keys to the exact SIP header names you asked for (see trunk example below). • Keep attribute values simple strings. If you need JSON, stringify it. 2) Example: delete the room to send BYE (Python) • Deleting the room causes LiveKit to initiate termination of the SIP call and include the mapped headers in the BYE.
Copy code
# example_delete_room.py
from livekit import api  # adjust to the actual client import
import asyncio

async def end_call_and_send_bye(client, room_name):
    req = api.DeleteRoomRequest(room=room_name)
    await client.room.delete_room(req)
    print(f"Deleted room {room_name} — LiveKit will send SIP BYE with mapped headers.")
3) Putting it together (example usage)
Copy code
# run_flow.py
import asyncio
from livekit import LiveKitClient  # replace with your actual client class
from example_update_participant import set_participant_attributes
from example_delete_room import end_call_and_send_bye

async def main():
    client = LiveKitClient.from_api_key("YOUR_API_KEY", "YOUR_API_SECRET")  # adjust auth
    room_name = "support-room-001"
    sip_identity = "sip-participant-1"

    # 1) Set attributes that will be mapped to SIP headers
    await set_participant_attributes(client, room_name, sip_identity)

    # 2) Optionally wait or perform other logic, then end the call
    await end_call_and_send_bye(client, room_name)

if __name__ == "__main__":
    asyncio.run(main())
4) Example inbound trunk JSON (attributes_to_headers) • This is the trunk snippet you should apply when creating the inbound SIP trunk so LiveKit knows which participant attributes map to which SIP header names:
Copy code
{
  "trunk": {
    "name": "my-inbound-trunk",
    "numbers": [
      "+15551234567"
    ],
    "attributes_to_headers": {
      "abdc.route_type": "X-route_type",
      "abdc.route_value": "X-route_value",
      "abdc.queue": "X-ABDC-Queue",
      "abdc.iva_session_id": "X-IVA-SessionId",
      "abdc.person_id": "X-ABDC-PersonId",
      "abdc.studio_contained": "X-Studio-Contained",
      "abdc.language": "X-ABDC-Language"
    }
  }
}
Important reminders • The BYE with custom headers is sent only when LiveKit initiates the BYE by deleting the room. If the SIP endpoint sends BYE first (caller hangs up), LiveKit cannot inject custom headers into that BYE. • Ensure your trunk mapping keys exactly match the participant attribute keys your code sets (case-sensitive). • If any header needs structured data (JSON), stringify it into the participant attribute value. Would you like: • the exact Python imports and client initialization tailored to the LiveKit Python SDK version you’re using, or • a complete runnable example including authentication and error handling?
g
Does Kamailio handles all these changes ?
t
Thanks — I’m responding to your question about whether Kamailio handles the SIP BYE and custom-header changes described for LiveKit. Short answer • The LiveKit service is responsible for mapping participant attributes to SIP headers and sending those headers in the BYE when LiveKit initiates the hangup. The sources do not state whether Kamailio specifically performs or modifies those mappings in your environment, so I cannot confirm Kamailio’s role without more details. Context you can rely on • LiveKit uses an inbound-trunk setting
attributes_to_headers
to map participant attributes into X-headers. When you call
delete_room()
, LiveKit sends the SIP BYE and includes the mapped headers (for example, used in Five9 integrations). If the caller (SIP endpoint) sends BYE first, LiveKit cannot add headers to that BYE. (See: How LiveKit maps attributes → headers and sends BYE.) How to do call transfers with Five9 How Kamailio typically fits into a SIP chain (general guidance) • SIP proxies/B2BUAs like Kamailio normally forward or route SIP messages, and they can be configured to add, remove, or rewrite headers. • If Kamailio sits between LiveKit and your downstream SIP endpoint (or contact center), it may: ◦ simply pass through the BYE and its X-headers untouched, or ◦ be configured to strip or modify headers, or ◦ add its own headers or routing logic. What I need to know to give a definitive answer Please tell me: • Where Kamailio sits in your call flow (e.g., LiveKit → Kamailio → Five9, or LiveKit → Five9 with Kamailio only for some routes). • Whether Kamailio is configured as a stateless proxy, a full B2BUA, or performing header rewriting/filtering. • Any observed behavior (e.g., LiveKit sends BYE but downstream system does not see the X-headers; or headers are being changed/removed). What I can help with next • If Kamailio is in the path, I can suggest Kamailio config checks and settings to ensure headers are preserved (examples of header-pass-through checks and where to look for header rewriting rules). • If you prefer, I can show example Kamailio config snippets to preserve X- headers once you confirm Kamailio’s placement and mode. Which of the three would you like to do next? • Provide your call-flow placement and any logs you’re seeing (I’ll point out exactly what to check), or • I can share example Kamailio config patterns to preserve/forward custom X-headers. Sources: Pass UUI data to Genesys Cloud during SIP transfers | LiveKit | How to do call transfers with Five9 | LiveKit
g
where I can get custom header sent by sip or five9 ?
t
I’m replying to your question about where you can get the custom SIP headers sent by a SIP endpoint or Five9. Short answer • Incoming custom headers from Five9 or another SIP provider are made available in LiveKit as participant attributes (after mapping via
headers_to_attributes
). • Outgoing custom headers that LiveKit sends in BYE come from participant attributes you set and are delivered to the SIP provider (verify them in SIP logs or Five9 call logs). Where to look and how to retrieve them 1) In your agent code (participant attributes) • When Five9 or another SIP endpoint sends X- headers in the INVITE, LiveKit converts mapped headers into participant attributes. • Retrieve them from the SIP participant’s
attributes
dictionary in your agent code. Example pattern: ◦ Find the SIP participant in the room (participant.kind == SIP). ◦ Read
participant.attributes.get("your.attribute_key")
. • Make sure your inbound trunk has
headers_to_attributes
mapping for the header keys you want to capture. 2) In LiveKit / application logs • Server-side or agent logs that print participant objects will show the attributes you can use to debug header values. Enable relevant logging or log the participant attributes in your agent flow. 3) SIP-level inspection (raw SIP messages) • Capture SIP traffic (e.g., tcpdump/Wireshark) between LiveKit and your SIP provider to see raw INVITE/BYE messages and all X- headers directly. Use this when you need proof the header was transmitted on the wire. 4) On the SIP provider side (Five9) • Five9 call logs and CAVs (Call Variables) will show headers received in BYE or INVITE. Use Five9’s logging/tracing tools to confirm the headers LiveKit sent were received and parsed by Five9. 5) Trunk configuration checks • Verify
headers_to_attributes
(for inbound headers) and
attributes_to_headers
(for outbound BYE headers) in your inbound trunk config. Keys must match exactly (case-sensitive) between trunk mappings and participant attribute keys. Important behaviors to note • LiveKit will only include mapped attributes as X- headers in BYE when LiveKit initiates the hangup (e.g., you call
delete_room
). If the caller hangs up first, LiveKit cannot add headers to that BYE. • If an intermediate SIP proxy (e.g., Kamailio) sits between LiveKit and Five9, it may rewrite/strip headers. If you do not see headers at the destination, check the proxy’s config or capture SIP traffic on both sides of the proxy. If you want, I can: • Show a short Python snippet that reads the SIP participant’s attributes in your agent flow. • Provide the exact trunk JSON example for
headers_to_attributes
and
attributes_to_headers
. • Suggest packet-capture commands and exact SIP fields to check for quick verification. Which would help most right now? Sources: How to do call transfers with Five9 | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation | Understanding TLS in SIP | LiveKit
g
i am using Kamailio
t
Thanks — since you’re using Kamailio, I’ll explain how LiveKit’s header handling interacts with Kamailio and what to check or change so your custom X- headers flow end-to-end. What LiveKit does • LiveKit maps incoming SIP headers (INVITE) into participant attributes using
headers_to_attributes
. • When LiveKit initiates a hangup (you call
delete_room
), LiveKit maps participant attributes back to SIP headers in the BYE using
attributes_to_headers
. • Those X- headers will be present on the BYE that LiveKit sends onto the next hop in your SIP path. How Kamailio may affect those headers • Kamailio is typically a SIP proxy/B2BUA and can: ◦ pass headers through unchanged, ◦ remove or rewrite headers, or ◦ add headers of its own. • Whether Kamailio modifies or preserves the headers depends entirely on its configuration (routing scripts, header handling modules, or rewrite rules). Checklist — what to verify in your setup 1. Call-flow placement ◦ Confirm the exact path: LiveKit → Kamailio → Five9 (or LiveKit → Five9 → Kamailio, etc.). The location of Kamailio matters for where to capture/inspect SIP traffic. 1. Confirm LiveKit is sending headers ◦ Capture SIP traffic on the LiveKit side (or check LiveKit SIP logs) to ensure the BYE contains the expected headers: ▪︎ X-route_type, X-route_value, X-ABDC-Queue, X-ABC-SessionId, X-ABDC-PersonId, X-Studio-Contained, X-ABDC-Language ◦ If LiveKit’s BYE already contains them, the issue is downstream (Kamailio or beyond). 1. Capture traffic between Kamailio and the next hop ◦ Use tcpdump/wireshark on the Kamailio host to inspect the incoming BYE from LiveKit and the outgoing BYE toward Five9. ◦ Compare headers on both sides to see if Kamailio is removing or changing them. 1. Inspect Kamailio config for header handling ◦ Look in your routing script(s) and modules for any header manipulation: ▪︎ presence of functions like
remove_hf()
,
hov_add_hf()
,
append_hf()
,
rewritehost()
,
fix_nated_contact()
, or other header rewrite utilities. ◦ Check for modules/logic that sanitize or strip X- headers for security or policy reasons. 1. Preserve headers in Kamailio if needed ◦ If Kamailio is stripping headers, add logic to preserve or forward them. Example patterns: ▪︎ Ensure you are not calling
remove_hf("X-...")
for those headers. ▪︎ Use
append_hf()
/
add_hf()
to re-add headers if you must transform them. ▪︎ If Kamailio terminates and re-creates dialogs (B2BUA behavior), explicitly copy desired headers from the incoming message into the outgoing message. Quick Kamailio examples (patterns) • To check for a header and log it: ◦ In your routing script: if (has_hf("X-ABDC-Queue")) { xlog("X-ABDC-Queue: $hdr(X-ABDC-Queue)\n"); } • To forward headers unchanged, avoid calls that remove or normalize unknown headers. • To preserve and re-add a header if your script needs to rebuild messages: ◦ Extract the header value: $var(q) = $hdr(X-ABDC-Queue); ◦ Add it to the outgoing request: append_hf("X-ABDC-Queue: $var(q)\r\n"); How to debug quickly 1. Capture the BYE on three points: ◦ On LiveKit side (to confirm it sent headers). ◦ On Kamailio inbound interface (to confirm it received headers). ◦ On Kamailio outbound interface toward Five9 (to confirm it forwarded headers). 1. If headers are present on LiveKit but missing after Kamailio receives them, search the Kamailio config for header removal or rewriting logic. 2. If headers are present in Kamailio incoming but absent in outgoing, add explicit copy/append logic or remove the code that strips them. If you want, I can: • Show a short Kamailio routing-script snippet demonstrating how to read and append a header (I’ll keep it minimal and aligned to your setup), or • Provide exact tcpdump/Wireshark capture commands and the SIP filter expressions to capture INVITE/BYE headers for quick verification. Which would you prefer — a Kamailio snippet to preserve/append headers, or capture commands to inspect the packets first?
g
how can I add dummy header from kamailio / Trunk to sent in Livekit
t
Thanks — I’ll show how to add a dummy SIP header in Kamailio (or via your trunk) so LiveKit receives it as a participant attribute. I’ll also show the LiveKit trunk mapping and a short Python snippet to read the attribute. Overview • Add the header in Kamailio on the request path toward LiveKit (for INVITE or other requests). • Ensure your LiveKit inbound trunk has a headers_to_attributes mapping for that header so LiveKit converts it to a participant attribute. • Read the attribute in your agent code from the SIP participant’s
attributes
dictionary. 1) Kamailio: add a dummy header • In your routing script (e.g., in request_route), add or append the header before forwarding the request to LiveKit. Example routing-snippet (kamailio.cfg pseudo-code): • Extract or set the header value and add it to the outgoing request:
Copy code
# set a variable you want to send
$var(dummy_val) = "dummy-value-123";

# add or overwrite header X-Dummy-Header in the outgoing request
# append_hf() adds a header line; remove_hf() can remove an existing header if needed
remove_hf("X-Dummy-Header");            # optional: remove any existing header
append_hf("X-Dummy-Header: $var(dummy_val)\r\n");
Placement notes: • Add this before you forward the request to LiveKit (e.g., before t_relay() or forward() call). • If Kamailio is acting as a B2BUA and you rebuild requests, explicitly copy or append the header when creating the outbound request. 2) Trunk / SIP provider: alternative • If you can configure your SIP trunk to add headers, add the header there (e.g., X-Dummy-Header: dummy-value-123). LiveKit will receive it the same way. 3) LiveKit: map header → participant attribute • Edit your inbound trunk config and add a
headers_to_attributes
mapping for the header name: Example trunk JSON snippet:
Copy code
{
  "trunk": {
    "name": "kamailio-to-livekit",
    "numbers": [
      "+15551234567"
    ],
    "headers_to_attributes": {
      "X-Dummy-Header": "kamailio.dummy_header"
    }
  }
}
Notes: • The right-hand value (
kamailio.dummy_header
) is the participant attribute key you will read in code. • Header names are case-insensitive in SIP but keep exact casing in your trunk mapping to avoid confusion. 4) Read the attribute in Python (agent) • Once LiveKit converts the header, the attribute is available on the SIP participant. Minimal example to find the SIP participant and print the attribute:
Copy code
# read_sip_attribute.py
def get_sip_participant_attribute(room, attr_key):
    sip_participant = None
    for p in room.remote_participants.values():
        # adjust kind check to your SDK names; look for SIP participant
        if getattr(p, "kind", None) == "sip":   # replace with actual enum/constant if present
            sip_participant = p
            break

    if not sip_participant:
        print("No SIP participant found in room")
        return None

    value = sip_participant.attributes.get(attr_key)
    print(f"{attr_key} = {value}")
    return value

# Usage:
# get_sip_participant_attribute(job_ctx.room, "kamailio.dummy_header")
5) Test & debug checklist • Capture SIP at three points to verify: ◦ On Kamailio: ensure the header is present on the outgoing INVITE toward LiveKit. ◦ On LiveKit side (or LiveKit logs): confirm the header was received. ◦ In your app: confirm the participant attribute exists. • If the header doesn’t appear in LiveKit: ◦ Verify Kamailio actually sends the header (tcpdump/wireshark). ◦ Confirm trunk
headers_to_attributes
contains the exact header name used by Kamailio. ◦ Ensure any intermediate SIP proxy does not strip X- headers. Important considerations • If headers are added only on BYE and the caller hangs up first, LiveKit will not be able to convert them (LiveKit converts inbound headers from INVITE into attributes). Prefer adding headers on INVITE or other LiveKit-received requests that create the participant. • If Kamailio is rewriting requests, ensure it does not remove headers before sending to LiveKit. • Keep header values short and stringified if they contain JSON. Would you like: • a concrete kamailio.cfg example tailored to your routing (show me the snippet where you forward to LiveKit), or • packet-capture commands (tcpdump) and Wireshark filters to verify headers quickly?
p
{ "sip_trunk_id": "ST_tG9gvNDj2TbU", "name": "trunk", "numbers": ["+1111111111"], "mediaEncryption": "SIP_MEDIA_ENCRYPT_ALLOW", "attributes_to_headers": { "five9.route_type": "X-route_type", "five9.route_value": "X-route_value", "five9.queue": "X-NEMT-Queue", "five9.iva_session_id": "X-IVA-SessionId", "five9.person_id": "X-NEMT-PersonId", "five9.studio_contained": "X-Studio-Contained", "five9.language": "X-NEMT-Language", "five9.transfer_reason": "X-transfer_reason" } } i do a update trunk using this json and alos in agent.py do a sip_participant = None for participant in job_ctx.room.remote_participants.values(): if participant.kind == ParticipantKind.PARTICIPANT_KIND_SIP: sip_participant = participant break if not sip_participant: print("No SIP participant found.") return "No SIP participant found." print("SIP participant:", sip_participant) attrs = { "five9.route_type": "Queue", "five9.route_value": "Queue", "five9.queue": "True", "five9.iva_session_id": str(self.state.session_id or ""), "five9.person_id": str(self.state.person_id or ""), "five9.studio_contained": "No", "five9.language": self.state.language or "en-US", "five9.transfer_reason": str(reason or ""), } res = await job_ctx.api.room.update_participant( api.UpdateParticipantRequest( room=job_ctx.room.name, identity=sip_participant.identity, attributes=attrs ) ) print("Update participant response:", res) # End the call - this sends BYE with X-Headers to Five9 await job_ctx.api.room.delete_room( api.DeleteRoomRequest(room=job_ctx.room.name) ) now how we can check inside a sip server that it work and pass the provided headers and all how i can check it or any issues in my setup
t
Thanks — I reviewed the trunk JSON and your agent code. Your setup looks correct: you map participant attributes to X-headers in the trunk, set those attributes with
update_participant()
, then call
delete_room()
to have LiveKit send BYE with the mapped headers. Below are practical, step‑by‑step checks and troubleshooting actions you can perform on the SIP server (Kamailio) and around the call flow to confirm the BYE includes your headers and to find any issues. 1) Capture the SIP BYE on the LiveKit → Kamailio hop • Purpose: Confirm LiveKit actually sends the BYE with the X- headers. • Command (run on the interface between LiveKit and Kamailio): ◦ tcpdump example (replace iface and IP/port as needed): ▪︎ sudo tcpdump -i <iface> -s 0 -w livekit_to_kamailio.pcap udp and port 5060 ◦ Or capture only BYE lines: ▪︎ sudo tcpdump -A -s 0 -i <iface> 'udp port 5060' | grep -i -A5 '^BYE\|^X-' • What to look for: In the captured BYE request, verify presence of: ◦ X-route_type, X-route_value, X-NEMT-Queue, X-IVA-SessionId, X-NEMT-PersonId, X-Studio-Contained, X-NEMT-Language, X-transfer_reason • If the headers are present here, LiveKit is sending them correctly. 2) Capture the SIP BYE on the Kamailio → Five9 hop • Purpose: See whether Kamailio forwards those headers unchanged, or strips/modifies them. • Command (on the Kamailio host, capture traffic to Five9): ◦ sudo tcpdump -i <kam_iface> -s 0 -w kamailio_to_five9.pcap udp and host <five9_ip> and port 5060 • Compare the BYE captured here to the BYE captured from LiveKit: ◦ If headers are missing or different, Kamailio is removing or rewriting them. ◦ If headers are identical, the issue is not Kamailio. 3) Inspect Kamailio config for header manipulation • Files to check: your kamailio.cfg and any included route script files. • Search for header operations/functions: ◦ remove_hf( "X-..." ), pop_hf(), rewrite_hf(), append_hf(), add_hf(), hdr.remove(), etc. • If you find removal/normalization logic, either: ◦ Remove/disable it for the X- headers you need to preserve, or ◦ Explicitly re-add them before forwarding: ▪︎ Example pseudo-logic: • $var(x) = $hdr(X-IVA-SessionId); • append_hf("X-IVA-SessionId: $var(x)\r\n"); • If your Kamailio acts as a B2BUA and rebuilds requests, ensure you copy the incoming header values into the outgoing request. 4) Quick Kamailio debugging snippets • Log header values in routing script: ◦ if (has_hf("X-IVA-SessionId")) { xlog("L_INFO", "X-IVA-SessionId: $hdr(X-IVA-SessionId)\n"); } • Copy a header into outgoing request (pseudo): ◦ $var(sessid) = $hdr(X-IVA-SessionId); ◦ append_hf("X-IVA-SessionId: $var(sessid)\r\n"); 5) Verify LiveKit participant attribute change before delete • Confirm update_participant returned success and attributes were applied: ◦ You already print
Update participant response:
, verify it shows success. • Optionally, log participant attributes server-side in your agent app after update to ensure they are set. 6) Verify at Five9 (destination) side • Use Five9 CAVs/logs to confirm they received those X- headers in the BYE. • If Five9 shows headers were not received, but you see them on Kamailio→Five9 capture, check Five9 parsing rules or contact your Five9 admin. 7) Common pitfalls to watch for • Case sensitivity and exact header names: SIP header matching in your trunk mapping is precise—ensure mapping keys match header names LiveKit expects to inject. • Timing: Ensure attributes are updated before calling
delete_room()
. If delete happens before update resolves, headers may be missing. • Caller-initiated BYE: If the caller (Five9) ends the call first, LiveKit does not send BYE — no headers from LiveKit will be sent in that case. • Intermediate proxies: Any intermediary between LiveKit and Five9 (including Kamailio) can alter headers. 8) Quick verification plan (recommended order) 1. Update participant attributes (your code). Confirm success. 2. Capture LiveKit→Kamailio BYE. Confirm headers present. 3. Capture Kamailio→Five9 BYE. Compare headers. 4. If missing at step 3, inspect Kamailio config and add logging/copy logic. 5. Confirm receipt at Five9 via Five9 logs. If you want, I can: • Provide exact tcpdump filter strings tailored to your IPs/ports, or • Provide a small concrete kamailio.cfg snippet showing how to copy/preserve the headers (paste your relevant request_route block if you want precise lines to insert). Which would you like me to provide next — tcpdump filters for your IPs/ports, or a kamailio.cfg snippet to preserve/add headers?