> For a complete page index, fetch https://docs.synthflow.ai/llms.txt. For full documentation content, fetch https://docs.synthflow.ai/llms-full.txt. # How to Direct SIP Dialing > Route calls directly to the Synthflow SIP endpoint when your telephony setup does not use elastic SIP trunking. In scenarios where your telephony provider does not offer elastic SIP trunking or if you have a more complex telephony setup unsuitable for elastic SIP trunking, you can use direct SIP dialing to our endpoint. In this scenario, Synthflow does not directly place or receive calls. Rather, your telephony system manages the dialing process to connect with the specified SIP endpoint. You will need to develop the integration logic tailored to your telephony provider's requirements. From Synthflow's standpoint, all call interactions will be treated as incoming, so your integration must explicitly define call direction handling. The process involves three primary steps: 1. **Importing a custom phone number** 2. **Creating the agent and linking it to the phone number** 3. **Dialing to the SIP Endpoint** ## Step 1: Import a Custom Phone Number Register the number Synthflow should answer for in your workspace. This creates a custom number record your telephony system can dial into, without elastic SIP trunking on the Synthflow side. If your carrier or PBX requires outbound SIP registration before it routes calls, set `uac_enabled` to `true` and provide trunk credentials. Expand the endpoint below to send a test request, then use the table for the fields most relevant to direct SIP dialing. ### Request POST [https://api.synthflow.ai/v2/custom-numbers](https://api.synthflow.ai/v2/custom-numbers) **`Import Custom Number`** ```curl Import Custom Number curl -X POST https://api.synthflow.ai/v2/custom-numbers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "workspace_id": "1710107690998x536152705164378100", "phone_number": "+33782990580", "friendly_name": "My Custom Number", "provider_name": "custom", "termination_uri": "sip.example.com" }' ``` **`Import Custom Number`** ```python Import Custom Number import requests url = "https://api.synthflow.ai/v2/custom-numbers" payload = { "workspace_id": "1710107690998x536152705164378100", "phone_number": "+33782990580", "friendly_name": "My Custom Number", "provider_name": "custom", "termination_uri": "sip.example.com" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`Import Custom Number`** ```go Import Custom Number package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.synthflow.ai/v2/custom-numbers" payload := strings.NewReader("{\n \"workspace_id\": \"1710107690998x536152705164378100\",\n \"phone_number\": \"+33782990580\",\n \"friendly_name\": \"My Custom Number\",\n \"provider_name\": \"custom\",\n \"termination_uri\": \"sip.example.com\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`Import Custom Number`** ```ruby Import Custom Number require 'uri' require 'net/http' url = URI("https://api.synthflow.ai/v2/custom-numbers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"workspace_id\": \"1710107690998x536152705164378100\",\n \"phone_number\": \"+33782990580\",\n \"friendly_name\": \"My Custom Number\",\n \"provider_name\": \"custom\",\n \"termination_uri\": \"sip.example.com\"\n}" response = http.request(request) puts response.read_body ``` **`Import Custom Number`** ```java Import Custom Number import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.synthflow.ai/v2/custom-numbers") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"workspace_id\": \"1710107690998x536152705164378100\",\n \"phone_number\": \"+33782990580\",\n \"friendly_name\": \"My Custom Number\",\n \"provider_name\": \"custom\",\n \"termination_uri\": \"sip.example.com\"\n}") .asString(); ``` **`Import Custom Number`** ```csharp Import Custom Number using RestSharp; var client = new RestClient("https://api.synthflow.ai/v2/custom-numbers"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"workspace_id\": \"1710107690998x536152705164378100\",\n \"phone_number\": \"+33782990580\",\n \"friendly_name\": \"My Custom Number\",\n \"provider_name\": \"custom\",\n \"termination_uri\": \"sip.example.com\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`Import Custom Number`** ```swift Import Custom Number import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "workspace_id": "1710107690998x536152705164378100", "phone_number": "+33782990580", "friendly_name": "My Custom Number", "provider_name": "custom", "termination_uri": "sip.example.com" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.synthflow.ai/v2/custom-numbers")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` | Field | Required | Description | | ---------------------- | -------- | ---------------------------------------------------------------------------- | | `workspace_id` | Yes | Your workspace ID | | `phone_number` | Yes | The phone number to import | | `friendly_name` | No | A human-readable name for the phone number | | `termination_uri` | No | SIP domain used for outbound calls | | `trunk_username` | No | SIP trunk username for authentication. Required when `uac_enabled` is `true` | | `trunk_pwd` | No | SIP trunk password for authentication. Required when `uac_enabled` is `true` | | `sip_outbound_proxy` | No | Outbound proxy for calls and SIP REGISTER requests | | `sip_auth_username` | No | Auth username for REGISTER when it differs from `trunk_username` | | `uac_enabled` | No | Set to `true` to enable outbound SIP registration. Defaults to `false` | | `uac_register_expires` | No | Registration refresh interval in seconds (60 to 3600). Defaults to `300` | ## Step 2: Create an agent Create an inbound agent and attach the custom phone number from Step 1. Synthflow treats every call that reaches that number as incoming, so set `type` to `inbound`. Wait until Step 1 succeeds before you send this request. Expand the endpoint below to try the call, then use the table for the minimum fields needed in this flow. ### Request POST [https://api.synthflow.ai/v2/assistants](https://api.synthflow.ai/v2/assistants) ```curl curl -X POST https://api.synthflow.ai/v2/assistants \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "type": "outbound", "name": "Sales Assistant", "agent": { "prompt": "You are a helpful sales assistant for Acme Corp.", "greeting_message": "Hello, this is Sarah from Acme Corp. How can I help you today?", "llm": "gpt-4.1-Mini", "language": "en-US", "voice_id": "eleven_turbo_v2" } }' ``` ```python import requests url = "https://api.synthflow.ai/v2/assistants" payload = { "type": "outbound", "name": "Sales Assistant", "agent": { "prompt": "You are a helpful sales assistant for Acme Corp.", "greeting_message": "Hello, this is Sarah from Acme Corp. How can I help you today?", "llm": "gpt-4.1-Mini", "language": "en-US", "voice_id": "eleven_turbo_v2" } } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.synthflow.ai/v2/assistants" payload := strings.NewReader("{\n \"type\": \"outbound\",\n \"name\": \"Sales Assistant\",\n \"agent\": {\n \"prompt\": \"You are a helpful sales assistant for Acme Corp.\",\n \"greeting_message\": \"Hello, this is Sarah from Acme Corp. How can I help you today?\",\n \"llm\": \"gpt-4.1-Mini\",\n \"language\": \"en-US\",\n \"voice_id\": \"eleven_turbo_v2\"\n }\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.synthflow.ai/v2/assistants") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"type\": \"outbound\",\n \"name\": \"Sales Assistant\",\n \"agent\": {\n \"prompt\": \"You are a helpful sales assistant for Acme Corp.\",\n \"greeting_message\": \"Hello, this is Sarah from Acme Corp. How can I help you today?\",\n \"llm\": \"gpt-4.1-Mini\",\n \"language\": \"en-US\",\n \"voice_id\": \"eleven_turbo_v2\"\n }\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.synthflow.ai/v2/assistants") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"type\": \"outbound\",\n \"name\": \"Sales Assistant\",\n \"agent\": {\n \"prompt\": \"You are a helpful sales assistant for Acme Corp.\",\n \"greeting_message\": \"Hello, this is Sarah from Acme Corp. How can I help you today?\",\n \"llm\": \"gpt-4.1-Mini\",\n \"language\": \"en-US\",\n \"voice_id\": \"eleven_turbo_v2\"\n }\n}") .asString(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.synthflow.ai/v2/assistants"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"type\": \"outbound\",\n \"name\": \"Sales Assistant\",\n \"agent\": {\n \"prompt\": \"You are a helpful sales assistant for Acme Corp.\",\n \"greeting_message\": \"Hello, this is Sarah from Acme Corp. How can I help you today?\",\n \"llm\": \"gpt-4.1-Mini\",\n \"language\": \"en-US\",\n \"voice_id\": \"eleven_turbo_v2\"\n }\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "type": "outbound", "name": "Sales Assistant", "agent": [ "prompt": "You are a helpful sales assistant for Acme Corp.", "greeting_message": "Hello, this is Sarah from Acme Corp. How can I help you today?", "llm": "gpt-4.1-Mini", "language": "en-US", "voice_id": "eleven_turbo_v2" ] ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.synthflow.ai/v2/assistants")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` | Field | Required | Description | | -------------- | -------- | --------------------------------------------------------------------------------------------- | | `type` | Yes | Set to `inbound` for receiving calls | | `name` | Yes | A name for your agent | | `phone_number` | Yes | The custom phone number created in Step 1 | | `agent` | Yes | Agent configuration including `llm`, `language`, `prompt`, `greeting_message`, and `voice_id` | ## Step 3: Configure Twilio After the trunk is set up on SynthFlow, redirect Twilio calls to it using TwiML commands. Be sure to include the GHL unique call ID or Twilio Call SID in the SIP header using the `X-EI` key. **Javascript Example**: **`Dialing via TWIML`** ```javascript Dialing via TWIML const express = require('express'); const { twiml: { VoiceResponse } } = require('twilio'); const app = express(); const PORT = process.env.PORT || 3000; const TERMINATION = "sipin.synthflow.ai:32681"; /** * Redirects a call to SynthFlow SIP endpoint. */ app.get('/redirect_call', (req, res) => { const { Called, CallSid } = req.query; if (!Called) { return res.status(400).send('Missing "Called" query parameter'); } const voiceResponse = new VoiceResponse(); voiceResponse.dial().sip(`sip:${Called}@${TERMINATION}?X-EI=${CallSid}`); res.set('Content-Type', 'text/xml'); res.status(200).send(voiceResponse.toString()); }); app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); }); ``` **Python Example**: **`Dialing via TWIML`** ```python Dialing via TWIML from fastapi import FastAPI, Response from twilio.twiml.voice_response import VoiceResponse app = FastAPI() TERMINATION = "sipin.synthflow.ai:32681" @app.get("/redirect_call") async def redirect_call(Called: str, CallSid: str): # pylint: disable=invalid-name voice = VoiceResponse() voice.dial().sip(f"sip:{Called}@{TERMINATION}?X-EI={CallSid}") return Response(str(voice), media_type="text/xml", status_code=200) ``` ## Pre-actions with pre-call variables You can use Pre-Actions to fetch pre-call variables via API and incorporate them into the agent prompt for more personalized responses by using the `` verb in API request. > Note: The transfer call will work the same as before. > Route calls directly to the Synthflow SIP endpoint when your telephony setup does not use elastic SIP trunking.