Integration Issue: Connecting 3CX PBX with Retell Agent via Inbound Webhook

I am currently working on integrating a Retell AI Agent into a 3CX PBX system and I am facing issues establishing the connection correctly.

The Objective: We want the AI agent to act as an internal resource within the PBX. The call flow should be:

  1. An external customer calls our 3CX PBX.

  2. The customer dials a specific extension.

  3. That extension connects to a Retell Virtual Number (configured with an Inbound Webhook).

  4. A workflow is triggered to define dynamic variables.

  5. The call connects to the AI Agent, passing these parameters.

  6. Hand-off: If the customer asks to speak with a person, the agent must redirect the call back to a specific extension/queue in our 3CX PBX.

The Problem: I am unable to connect the agent to the PBX without the PBX attempting to treat it as a standard outbound call, which is failing (Error 486 / Registration issues). I want to ensure the metadata/dynamic variables are passed correctly during this “internal” hand-off.

Could you please provide guidance on:

  • The best practice for 3CX to Retell SIP connectivity for inbound webhooks.

  • How to ensure the dynamic variables are correctly captured when the call is forwarded from 3CX.

Looking forward to your guidance.

Hi @tecnico

For your 3CX setup, we recommend using the Dial to SIP URI method:

  • Call the Register Phone Call API from your server to get a call_id.

  • Dial sip:{call_id}@sip.retellai.com from 3CX. Make sure to whitelist Retell’s IP 18.98.16.120/30 and use TCP (recommended).

  • This avoids SIP registration errors since Retell accepts direct SIP INVITE calls.

Alternatively, if your 3CX supports Elastic SIP Trunking, you can import your number into Retell and use the Inbound Webhook to pass dynamic variables and metadata.

For Passing Dynamic Variables: Dial to SIP URI: Send them via the Register Phone Call API.SIP Trunk + Webhook: Your server responds with dynamic_variables in JSON.

For transferring calls back to 3CX, you can use the agent’s Transfer Call tool to your extension or SIP URI. Note that if using Dial to SIP URI, a custom function may be needed for transfer.

Thank You

Hi @tecnico,

Connecting 3CX can sometimes be annoying, as it’s configuration isn’t straight forward (also routing is problematic, depending on your 3CX license). To make life easier, you can use Cloudonix to perform this interconnect. Here are a couple of guides for this:

Connecting 3CX to Cloudonix:

Connecting Cloudonix and Retell:

Feel free to ping me with more questions if you have any.

Hi @shaw,

Thanks for the guidance. However, the Dial to SIP URI method using register_phone_call doesn’t fit our current architecture for two main reasons:

  1. No Middleware Server: We don’t have a dedicated server to trigger the API and obtain a call_id before each call.

  2. Dynamic Agent Override: Our setup relies entirely on Retell’s Inbound Webhook. The number configured in Retell doesn’t have a fixed agent; instead, the Webhook performs an agent_override and defines dynamic_variables based on the caller’s data.

Since the register_phone_call API forces us to define an agent_id upfront, it bypasses the logic we’ve built into our Webhook.

Could you please clarify the following?

  • Standard SIP Trunking: How can we configure 3CX as a standard SIP Trunk so that when a call hits Retell, it automatically triggers the Inbound Webhook associated with that number/trunk?

  • Metadata via SIP Headers: If we forward the call from 3CX via SIP, can Retell capture custom SIP headers (like X-Custom-Metadata) and pass them to our Webhook so we can still handle dynamic variables?

  • Authentication: Since we are seeing Error 486/Registration issues, what is the specific configuration for 3CX to hand off the call to Retell without a pre-registered call_id?

Looking forward to your technical advice on how to keep the Webhook as the “brain” of the operation.

Best regards,

Raúl

Hi @nirs,

Thanks for the suggestion! Cloudonix looks like a solid tool for handling complex 3CX routing. However, our goal is to keep the architecture as lean as possible by establishing a direct SIP connection between 3CX and Retell.

We are currently focused on making the Inbound Webhook workflow work directly, as we need Retell to trigger our webhook for agent_override and dynamic_variables without adding middle layers if possible.

If we hit a dead end with the direct SIP Trunk configuration, we’ll definitely look into Cloudonix as an alternative. For now, do you have any experience bypassing the 486/Registration issues in 3CX when pointing directly to Retell’s infrastructure?

Best regards,

Raúl

Hi @tecnico

I’ve shared this with our team so they can provide more detailed guidance. Once they review it, we’ll get back to you with the best recommendations.

Thank you for your patience!

Well, I had some significant time to play with the 3CX system - and sorry to say, I couldn’t find a “rational” way to do it, the way 3CX is designed simply requires that registration part - which is highly annoying. Sorry to say, the caveats of 3CX exist with many of the PBX vendor, who impose their own “opinion” as to how businesses should use SIP.

Thanks for your answer @nirs, how should I proceed then?

Well,

Eventually, you will be required to use some form of SBC element - either on-premise, or cloud. It can be Cloudonix, it can be Jambonz, it can be AcmePacket or Sonus - it doesn’t matter, eventually you’ll need it for doing more than just “connecting to Retell”.

The primary issue with tools like 3CX (or other vendor products) is that “vendors” are have a strict opinion as to how their product should work. If you don’t fall into the “accurate” use case, all bets are off.

Thanks @nirs, that helps clarify the direction.

In that case, for our specific use case, would you recommend Cloudonix as the most straightforward SBC path to start with, or do you see a better fit among the options you mentioned?

Our goal is still to keep the flow as simple as possible while preserving the Incoming Webhook logic on the Retell side. If possible, it would be very helpful if you could point us to the most practical reference architecture for:

3CX → SBC → Retell

Also, if there are any specific 3CX limitations or routing considerations we should account for from the beginning, that would help us avoid going down the wrong path.

Thanks again.

Hi @tecnico

Thanks for reaching out about your 3CX integration. Here’s guidance on each of your questions:

  1. SIP Trunk Configuration:
    Retell uses invite-based SIP trunking — it does not support SIP REGISTER. You’ll need to configure 3CX to send direct SIP INVITEs to Retell’s SIP endpoint without requiring registration. This is the most likely cause of your Error 486 / registration issues. In 3CX, set up the trunk as a “direct routing” or “IP-based” trunk (no registration required) pointing to Retell’s SIP server.

To set this up on the Retell side, use the [Import Phone Number API](https://docs.retellai.com/api-references/import-phone-number) to register your number. You’ll provide:

  • Your phone number
  • A termination_uri pointing to your 3CX system (for outbound/return calls from Retell)
  • (Optional) SIP trunk authentication credentials
  • (Optional) An inbound_webhook_url if you need dynamic variable handling
  • (Optional) An inbound_agent_id to assign which agent handles inbound calls
  1. Custom SIP Headers / Metadata:
    Yes! Retell captures custom SIP headers prefixed with X- (e.g., X-Custom-Metadata) from the incoming SIP INVITE and passes them to your inbound webhook as custom_sip_headers. Your webhook can then return dynamic_variables and metadata to customize the agent’s behavior per call.

  2. Authentication / No Pre-registered call_id:
    Since Retell uses invite-based trunking, no pre-registered call_id is needed. When 3CX sends a SIP INVITE to Retell, Retell automatically creates a new call and triggers the inbound webhook (if configured). The key is to ensure 3CX sends the INVITE directly without attempting to register first.

For the detailed API reference, see our Custom Telephony documentation(https://docs.retellai.com/make-receive-phone-calls/custom-telephony).

Pardon me for the late reply, been a crazy few days. Cloudonix has various integrations and direct easy setup with ReTell. Jambonz requires more management and more setup. The primary issue is the 3CX installed license, as each license has different capabilities.

Hi @shaw

Thanks for the detailed explanation regarding the SIP trunk configuration and the move to invite-based trunking.

However, I’m a bit confused about one point. If the phone number is already integrated and active within the Retell platform, I don’t quite understand the specific functionality or necessity of using the Import Phone Number API in this case.

Could you clarify why this step is required if the number is already recognized by the system?

Hi @tecnico

The Import Phone Number API is necessary because even though your number is active with your telephony provider, Retell doesn’t automatically know about it. Importing the number tells Retell how to route calls for that specific number — including the termination SIP URI, authentication credentials, and any custom SIP headers needed to connect to your provider’s trunk.

For more details you can see ( Custom Telephony Overview - Retell AI ) Guide

Thank You