Call Flows Integration
Call Flows define the automated routing logic for incoming and outgoing calls. They are built and managed visually using the graphical designer inside the Firetell Console.
Since Call Flow management and structure manipulation are internal resources, no public REST API endpoints are exposed. Instead, developers can integrate custom database lookups and dynamic routing logic directly into their own servers using two key integration nodes: Contact Lookup and JSON Call Action (JCA).
Contact Lookup Node (contact_lookup)​
The Contact Lookup node allows Firetell to query your CRM, database, or API endpoint to resolve the caller's identity before routing the call.
How it Works​
- Internal Fallback (Optional): If the Request URL parameter is left empty, Firetell will automatically search the internal Firetell Call Center database for a contact matching the caller's phone number.
- Webhook Query: If a Request URL is provided, Firetell issues an HTTP
POSTrequest to your configured webhook URL. The request body contains the call context:event(string):"call_flow.contact_lookup".call_id(string): Unique call ID.caller_number(string): The caller's E.164 phone number.destination_number(string): The dialed inbound DID/phone number.workspace_id(string): Workspace identifier.call_flow_id(string): Call flow identifier.
- Your server must respond with a
200 OKJSON payload containing the contact's name.
Expected JSON Response​
Firetell scans the response object for a display name using the following fields (in order of priority):
display_namenamefullNamedisplay_titletitle
Example response:
{
"id": "customer_99182",
"display_name": "John Doe",
"email": "john.doe@example.com",
"tier": "VIP"
}
Telephony Behavior​
- Caller ID Display Name: If a name is found, Firetell injects it into the SIP headers. Softphones, WebRTC clients, and physical IP phones will display the contact's name instead of a raw phone number.
- Session Variable: The raw JSON response is saved into the call's channel variable (
firetell_contact_data). This data can be referenced later during the call flow or accessed inside subsequent JCA webhooks.
JSON Call Action Node (json_call_action)​
The JSON Call Action (JCA) node allows your server to dynamically direct and control the call flow in real-time by returning a sequence of execution actions.
How it Works​
- When a call reaches this node, Firetell sends an HTTP
POSTrequest to your configured backend webhook URL. - Firetell sends the call context (caller number, dialed destination, workspace ID, call flow ID, call ID, and contact lookup data) in the body.
- Your server should process the business logic and respond with a
200 OKcontaining a list ofactionsto execute next.
HTTP POST Request Body​
{
"event": "call_flow.jca",
"call_id": "call_e9a0c7eb1a744b55a0ee65",
"workspace_id": "ws_abc123",
"call_flow_id": "cf_xyz987",
"caller_number": "14155550100",
"destination_number": "18005550199",
"contact_data": "{\"display_name\":\"John Doe\",\"tier\":\"VIP\"}" // Stringified response from preceding Contact Lookup node
}
Expected Response​
Your server must return a JSON response containing an array of compiled call actions.
Example response (Welcome user, and then bridge to an operator):
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_welcome_vip",
"answer_call": true,
"continue_on_play": false
}
},
{
"action": "to_operator",
"params": {
"phone_number": "+14155550123",
"timeout": 45
}
}
]
}
Supported Webhook Actions​
The following action objects can be returned in the actions array:
1. Play Audio (play)​
Plays a pre-recorded audio file stored in the workspace cache.
audio_id(string, required): ID of the audio metadata resource.answer_call(boolean, optional): Iffalse, streams the audio as early media (SIP 183 Progress) without answering/billing the call. Default:true.continue_on_play(boolean, optional): Iftrue, runs the audio in the background and immediately moves to the next action. Iffalse, blocks call flow until playback ends. Default:false.
2. Text to Speech (tts)​
Plays a text announcement using synthetic voice.
text(string, required): The text content to read (max 1000 characters).voice(string, optional): Selected TTS voice identifier.speed(number, optional): Playback speed rate.
3. Collect Digits (ivr)​
Waits for the caller to press DTMF keys.
timeout(number, optional): Time in seconds to wait for input. Default:5.max_digits(number, optional): Maximum digits to collect (between 1 and 10). Default:1.
4. To Operator (to_operator)​
Bridges the call to an external phone number or direct SIP URI.
to(object, required): Destination call party object:number(string, required): Destination E.164 phone number or SIP URI.name(string, optional): Destination display name.
from(object, optional): Custom outbound caller ID object:number(string, required): Outbound caller ID / DID number owned by your workspace. If omitted, the call flow's assigned DID is used.name(string, optional): Caller ID name displayed on the callee's device.
gateway_id(string, optional): Specific outbound gateway ID to route the call through.timeout(number, optional): Max ringing time in seconds before failover (max 300). Default:30.
5. Connect Agent (connect_agent)​
Routes the call to a registered Firetell agent.
agent_id(string, required): Unique agent ID.timeout(number, optional): Max ringing time in seconds. Default:30.
6. Connect Team (connect_team)​
Bridges the call to a team queue.
team_id(string, required): Unique team ID.strategy(string, optional): ACD strategy (ring-all,round-robin,sequential,random). Default:ring-all.timeout(number, optional): Ring timeout in seconds. Default:30.
7. Voicemail (voicemail)​
Records a voicemail message from the caller and uploads it to the S3 workspace cloud.
greeting_audio_id(string, optional): Audio ID to play before recording. If omitted, plays default greeting "Please leave your message after the tone."max_duration(number, optional): Max message recording length in seconds. Default:60.beep(boolean, optional): Play a tone beep sound before recording starts. Default:true.
8. Disconnect (disconnect)​
Ends the call session immediately.
cause(string, optional): SIP hangup cause (e.g.NORMAL_CLEARING).
Use Cases & Real-World Examples​
[Driver / Courier] (PSTN)
│
│ 1. Calls Virtual Proxy Number (DID)
â–¼
[Firetell Platform]
│
│ 2. Triggers JCA Webhook POST
â–¼
[Partner Server] ──► 3. Looks up active delivery order for caller_number
│
│ 4. Responds with to_operator action
â–¼
[Firetell Platform] ──► 5. Bridges to customer's real phone number
(Caller ID displayed is the Virtual Proxy Number)
Step 1: Firetell sends JCA Webhook​
{
"event": "call_flow.jca",
"call_id": "call_9c8df104a8b27e",
"workspace_id": "ws_ecommerce_app",
"call_flow_id": "cf_number_masking",
"caller_number": "14155550144",
"destination_number": "18005550199",
"contact_data": null
}
Step 2: Your Server returns Dynamic Bridge Actions​
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_connecting_mask_notice",
"answer_call": true,
"continue_on_play": true
}
},
{
"action": "to_operator",
"params": {
"to": {
"number": "+14155550188",
"name": "Customer John"
},
"from": {
"number": "+18005550199",
"name": "Firetell Proxy"
},
"timeout": 30
}
}
]
}
Two-Way Privacy:
Both the caller (driver) and the callee (customer) only see the Virtual Proxy Number on their phone screens, ensuring strict compliance with user privacy regulations and personal data protection standards.
Use Case 2: VIP Customer Dynamic Priority Routing​
Route callers dynamically based on their customer tier in your CRM or database.
Scenario:​
- When a call arrives, the Contact Lookup node queries your CRM with
caller_number. - The JSON Call Action receives the caller's tier (
VIPvsStandard). - If
VIP, the call is immediately routed to their dedicated Account Manager. IfStandard, it is routed to the general support queue.
Your Webhook Response (VIP Customer):​
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_vip_welcome_greeting",
"answer_call": true,
"continue_on_play": false
}
},
{
"action": "connect_agent",
"params": {
"agent_id": "agt_account_mgr_alex",
"timeout": 45
}
}
]
}
Your Webhook Response (Standard Customer):​
{
"actions": [
{
"action": "connect_team",
"params": {
"team_id": "team_general_support",
"timeout": 30
}
}
]
}
Use Case 3: Expired Order or Invalid Access Handling​
If a customer or driver calls after an order has already been completed or canceled, your server can reject the connection gracefully without consuming unnecessary call duration or operator time.
Your Webhook Response:​
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_order_completed_notice",
"answer_call": true,
"continue_on_play": false
}
},
{
"action": "disconnect",
"params": {
"cause": "NORMAL_CLEARING"
}
}
]
}
Use Case 4: After-Hours On-Call Duty Escalation​
Route after-hours emergency calls dynamically based on your company's live on-call schedule (e.g. Opsgenie, PagerDuty, or internal roster).
Your Webhook Response:​
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_after_hours_emergency",
"answer_call": true,
"continue_on_play": false
}
},
{
"action": "to_operator",
"params": {
"phone_number": "+14155550177",
"timeout": 40
}
}
]
}
Use Case 5: Two-Factor Authentication & Voice OTP (2FA)​
Voice OTP delivery provides higher deliverability and enhanced protection compared to standard SMS. You can implement Voice OTP in two ways:
Option A: Inbound Reverse Voice OTP (User Calls Verification Number)​
- The user requests 2FA verification on your website/app and is prompted to call your verification number from their registered phone.
- The incoming call hits the Call Flow and triggers the JSON Call Action with
caller_number. - Your server looks up the pending 2FA login session for that phone number and responds with a sequence of pre-recorded audio digit clips (e.g.
0–9) or dynamic TTS. - Firetell answers, plays the greeting, sequentially plays each OTP digit, and hangs up immediately.
{
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_greeting_2fa",
"answer_call": true,
"continue_on_play": false
}
},
{
"action": "play",
"params": {
"audio_id": "au_digit_9",
"continue_on_play": false
}
},
{
"action": "play",
"params": {
"audio_id": "au_digit_2",
"continue_on_play": false
}
},
{
"action": "play",
"params": {
"audio_id": "au_digit_8",
"continue_on_play": false
}
},
{
"action": "play",
"params": {
"audio_id": "au_digit_4",
"continue_on_play": false
}
},
{
"action": "disconnect",
"params": {
"cause": "NORMAL_CLEARING"
}
}
]
}
Option B: Outbound Voice OTP (Automated Call Broadcast)​
Your server proactively triggers an outbound call to the user's phone via the Make Call API passing the exact same OTP action chain with max_duration: 45.