Skip to main content
๐Ÿค– LLM Friendly: This page is available in raw Markdown format for LLM consumption:call.md|Get full documentation:llms.txt/llms-full.txt

Call

The Call API allows you to initiate outbound server-to-server calls, control active calls with actions, and retrieve call history.

Endpointsโ€‹

MethodEndpointDescription
GET/callsList call history
GET/calls/:id/eventsGet call events timeline
POST/calls/makeInitiate an outbound call
PUT/calls/:id/actionsUpdate actions on an active call

List Call Historyโ€‹

Returns paginated call history for your workspace. Requires ApiKey with any scope.

GET /calls?page=1&limit=20

Query Parametersโ€‹

ParameterTypeDefaultDescription
pagenumber1Page number (min: 1)
limitnumber20Items per page (max: 100)
searchstringโ€”Search by phone number or party name
directionstringallFilter by call direction: inbound, outbound, internal, all
statusstringallFilter by call status: answered, completed, active, failed, no_answer, busy, etc.
fromstringโ€”Filter by caller phone number or username
tostringโ€”Filter by destination phone number or username
sentimentstringallFilter by AI sentiment analysis: positive, neutral, negative, all

Responseโ€‹

{
"data": [
{
"id": "call_01h900000000000000000001",
"workspace_id": "ws_123456789",
"number": "18005550199",
"from": {
"name": "Support Agent 1",
"number": "agent1001"
},
"to": {
"name": "Customer",
"number": "14155552671"
},
"status": "completed",
"direction": "outbound",
"duration": 45,
"billsec": 42,
"recording": "ready",
"transcription": "completed",
"sentiment": "positive",
"summary": "Customer reached out to inquire about smart call center solutions.",
"action_items": ["Send Enterprise plan quotation", "Schedule system demo"],
"created_at": "2026-07-09T10:00:00Z"
}
],
"meta": {
"total": 100,
"page": 1,
"limit": 20,
"total_pages": 5
}
}

Make a Callโ€‹

Initiate an outbound server-to-server call. Requires ApiKey with full scope.

POST /calls/make

Request Bodyโ€‹

FieldTypeRequiredDescription
toobjectโœ…Destination party { number, name? }. Number can be an E.164 phone number, extension, or agent username.
to.numberstringโœ…Destination phone number (E.164), extension, or username (3-30 chars).
to.namestringโ€”Display name for the callee (up to 64 chars). Fallbacks to to.number if omitted.
fromobjectโ€”Caller party { number, name? }. Phone number (E.164) or agent username.
from.numberstringโœ…Caller ID phone number (E.164) or agent username (3-30 chars).
from.namestringโ€”Display name for the caller / CNAM (up to 64 chars). Fallbacks to from.number if omitted.
call_flow_idstringโ€”Call flow to execute on answer (mutually exclusive with actions).
max_durationnumberโ€”Maximum call duration limit in seconds (1 to 7200). The call automatically hangs up after this duration. Default: based on credit & platform safety cap (7200s).
actionsarrayโ€”Array of actions to perform sequentially when the call connects (mutually exclusive with call_flow_id).
tip

Auto-Hangup on Flow Completion

When executing sequential actions (e.g. playing an audio announcement or TTS notification), Firetell automatically hangs up the call (NORMAL_CLEARING) as soon as the last action in the list finishes executing. You do not need to explicitly append a hangup or disconnect action unless you want to terminate earlier.

Call Actionsโ€‹

Each action object has the following shape:

FieldTypeRequiredDescription
actionstringโœ…Action type (see below)
paramsobjectโ€”Action-specific parameters
continuebooleanโ€”Whether to continue to the next action
auto_answerbooleanโ€”Auto-answer the call before executing action

Action Referenceโ€‹

All server-to-server actions are unified with Call Flow builder actions for structural consistency.

play โ€” Audio Playbackโ€‹

Play a pre-uploaded workspace audio file.

ParamTypeRequiredDescription
audio_idstringโœ…ID of the workspace audio asset to play
answer_callbooleanโ€”Whether to answer the call before playing. Default: true
continue_on_playbooleanโ€”If true, playback runs in background while the next action executes. Default: false.

tts โ€” Text-to-Speechโ€‹

Play a synthesized speech message.

ParamTypeRequiredDescription
textstringโœ…The text to read aloud
voicestringโ€”Synthetic voice identifier
speednumberโ€”Voice speaking speed rate

ivr โ€” Wait for Digitsโ€‹

Wait for the callee to press DTMF keys.

ParamTypeRequiredDescription
timeoutnumberโ€”Time in seconds to wait for input. Default: 5
max_digitsnumberโ€”Maximum digits to collect (between 1-10). Default: 1
webhook_urlstringโœ…The POST destination URL where collected digits will be sent.
Collected Callback Payloadโ€‹

When DTMF collection completes (due to timeout, reaching max digits, or pressing #), Firetell dispatches a queued POST request to your webhook_url with the following JSON payload:

{
"event": "call.ivr_collected",
"data": {
"workspace_id": "ws_xyz789",
"call_id": "call_abc123",
"digits": "123",
"status": "completed" // "completed" or "timeout"
}
}

to_operator โ€” Connect External Phoneโ€‹

Bridge the call to an external phone number or direct SIP URI via carrier gateway.

ParamTypeRequiredDescription
phone_numberstringโœ…Destination E.164 phone number or direct SIP URI
fromstringโ€”Custom DID phone number (E.164) used as caller ID. Automatically resolves the matching carrier gateway to prevent cross-carrier blockage. Default: Call DID
timeoutnumberโ€”Timeout in seconds for the ringing phase. Default: 30
ringback_audio_idstringโ€”Audio file ID to play as hold music while ringing

connect_agent โ€” Connect Agentโ€‹

Bridge the call to a registered Firetell agent.

ParamTypeRequiredDescription
agent_idstringโœ…Unique registered agent ID
timeoutnumberโ€”Timeout in seconds. Default: 30
ringback_audio_idstringโ€”Audio file ID to play as hold music while ringing

connect_team โ€” Connect Team Queueโ€‹

Bridge the call to a queue team.

ParamTypeRequiredDescription
team_idstringโœ…Unique registered team ID
timeoutnumberโ€”Timeout in seconds. Default: 30
ringback_audio_idstringโ€”Audio file ID to play as hold music while ringing

connect_voice_agent โ€” Connect Voice AI Agentโ€‹

Bridge the call to a Realtime Conversational Voice AI Agent.

ParamTypeRequiredDescription
voice_agent_idstringโœ…Unique Voice Agent ID (va_...)
versionnumberโ€”Specific agent version number (e.g. 1). Defaults to the current active published version if omitted.
timeoutnumberโ€”Ringing timeout in seconds before fallback. Default: 30
max_duration_secondsnumberโ€”Maximum duration limit in seconds for the Voice AI session. Default: 300
ringback_audio_idstringโ€”Audio file ID to play as hold music while establishing connection

voicemail โ€” Voicemail Recordingโ€‹

Record a voicemail message from the caller and automatically upload it to Firetell Cloud Storage.

ParamTypeRequiredDescription
greeting_audio_idstringโ€”Pre-recorded greeting file ID. Fallbacks to default greeting if omitted.
max_durationnumberโ€”Max recording length in seconds. Default: 60
beepbooleanโ€”Whether to play a tone beep before starting recording. Default: true

disconnect / hangup โ€” Hang Upโ€‹

Terminate the active call channel. Either name can be used interchangeably.

ParamTypeRequiredDescription
causestringโ€”SIP hangup reason (default: NORMAL_CLEARING)

recording โ€” Call Session Recordingโ€‹

Record the entire call session and automatically upload the file to S3 cloud storage.

caution

This action will be automatically ignored and skipped if the workspace plan quota does not authorize call recording (specifically, call_recording for app-to-phone external calls, or call_internal_recording for app-to-app internal calls). In this case, the call flow will seamlessly proceed to the next action.

ParamTypeRequiredDescription
formatstringโ€”Audio format: wav (default) or mp3.
stereobooleanโ€”Whether to record caller and callee on separate stereo channels (left/right). Default: false.
answer_callbooleanโ€”Whether to answer the call immediately (true, default). Set to false to defer recording until bridged.

stream โ€” Audio Stream Forkโ€‹

Fork the call audio in real-time to your own WebSocket server. Useful for building custom voice bots, real-time translation, call analytics, or any scenario where your server needs raw audio access during the call.

ParamTypeRequiredDescription
ws_urlstringโœ…Destination WebSocket URL (wss:// or ws://). Must be a publicly accessible server.
trackstringโ€”Audio legs to fork: both (default, stereo โ€” caller on left, callee on right), inbound (caller only), outbound (callee only).
sample_ratenumberโ€”PCM audio sample rate in Hz: 8000 (default, G.711 compatible) or 16000 (wideband).
bidirectionalbooleanโ€”If true, audio sent from your WS server back to Firetell is played into the call channel in real-time (default: false).
answer_callbooleanโ€”Answer the call before starting the stream. Default: true. Set to false only if the call was already answered by a prior answer action โ€” audio will not flow until the channel is answered, regardless of whether the WebSocket connection to your server is established.
headersobjectโ€”Custom HTTP headers to include in the WebSocket handshake (e.g. { "Authorization": "Bearer token" }). Max 10 headers.
info

Bidirectional Audio

When bidirectional: true your server receives the caller's raw PCM audio and can send audio frames back in real-time. Firetell injects those frames directly into the caller's audio channel. This lets you build a fully custom voice bot, live interpreter, or real-time TTS system using the transport of your choice.

When bidirectional: false the stream action only sends audio to your server. The call flow continues normally, and your server can consume the audio stream for transcription, recording, or analytics without affecting the call.

caution

bidirectional: true requires the call to be answered.

Firetell only generates audio write frames (needed to play audio back to the caller) on channels that are in the ACTIVE (answered) state. If the call is not answered, your server will receive the connection but audio sent from your server will not be played to the caller.

Always use answer_call: true (the default) when bidirectional: true, or ensure the call was answered by a prior answer action in the flow.

Security notice: Only wss:// and ws:// URLs pointing to publicly routable IP addresses are accepted. Internal addresses (RFC 1918, loopback, link-local, cloud metadata) are blocked.

Use Cases & Examplesโ€‹

1. Simple Outbound Call โ€” Connect to Agentโ€‹

Call an external number and connect directly to an agent when answered.

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Customer Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "connect_agent",
"params": {
"agent_id": "agt_abc123",
"timeout": 30
}
}
]
}'

2. Outbound Call with Hold Musicโ€‹

Call an external number and play hold music while the agent is ringing. The music stops automatically when the agent answers.

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Customer Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "connect_agent",
"params": {
"agent_id": "agt_abc123",
"timeout": 30,
"ringback_audio_id": "aud_holdmusic"
}
}
]
}'
tip

The ringback_audio_id param works on connect_agent, connect_team, connect_voice_agent, and to_operator. Upload your hold music via the Audio API first to get the audio_id.

3. Agent Cascade โ€” Sequential Fallbackโ€‹

Try agent 1 first. If they don't answer within 10 seconds, automatically try agent 2. If agent 2 also doesn't answer, route to the support team.

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Customer Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "connect_agent",
"params": {
"agent_id": "agt_primary",
"timeout": 10,
"ringback_audio_id": "aud_holdmusic"
}
},
{
"action": "connect_agent",
"params": {
"agent_id": "agt_backup",
"timeout": 10,
"ringback_audio_id": "aud_holdmusic"
}
},
{
"action": "connect_team",
"params": {
"team_id": "team_support",
"timeout": 30,
"ringback_audio_id": "aud_holdmusic"
}
},
{
"action": "voicemail",
"params": {
"greeting_audio_id": "aud_vm_greeting",
"max_duration": 60
}
}
]
}'
info

Actions execute sequentially. If a connect_* action fails (no answer, timeout, agent offline), the system automatically falls through to the next action in the array.

4. Recorded Outbound Campaignโ€‹

Make an outbound call with recording enabled, play a TTS message, then hang up. Useful for automated notification campaigns.

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Customer Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "recording",
"params": {
"format": "wav",
"stereo": false
}
},
{
"action": "tts",
"params": {
"text": "Hello, this is a unified notification from your system."
}
},
{
"action": "disconnect"
}
]
}'
caution

The recording action is automatically skipped if your workspace plan does not include the call_recording quota. The remaining actions will still execute normally.

5. Automated Voice Broadcast / Order Notificationโ€‹

Make an automated announcement call. The call plays the order status audio file and automatically hangs up as soon as the playback finishes. Setting max_duration: 60 enforces an absolute safety cap of 60 seconds.

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Firetell Delivery"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"max_duration": 60,
"actions": [
{
"action": "play",
"params": {
"audio_id": "au_41817c09bc4d27a405ec5a",
"answer_call": true,
"continue_on_play": false
}
}
]
}'

6. Outbound AI Voice Agent Callโ€‹

Initiate an automated outbound call directly connected to a Realtime Voice AI Agent (e.g. appointment confirmation, customer survey, or booking assistant).

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Virtual Clinic Assistant"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"max_duration": 300,
"actions": [
{
"action": "connect_voice_agent",
"params": {
"voice_agent_id": "va_01h900000000000000000001",
"version": 1,
"timeout": 30
}
}
]
}'

7. Mid-Call Action Updateโ€‹

After a call is in started or active status, you can dynamically push new actions using the Update Call Actions endpoint. This is useful for interactive scenarios where your backend decides the next step based on external logic or customer input.

# Step 1: Initiate the call
curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "Customer Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "play",
"params": { "audio_id": "aud_welcome" }
}
]
}'
# Returns: { "data": { "call_id": "call_abc123", ... } }

# Step 2: After your backend logic, dynamically hand over the active call to a Voice AI Agent
curl -X PUT "https://{workspace_id}.firetell.app/api/v1/calls/call_abc123/actions" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"actions": [
{
"action": "connect_voice_agent",
"params": {
"voice_agent_id": "va_01h900000000000000000001"
}
}
]
}'

8. Custom Voice Bot via Audio Streamโ€‹

Fork the call audio in real-time to your own WebSocket server. Your server receives raw PCM audio and can send synthesized speech back into the call channel. This pattern is ideal when you want full control over the AI model, TTS provider, or business logic without using Firetell's built-in Voice Agent.

๐Ÿ“ฆ Sample code: Node.js ยท Python

curl -X POST "https://{workspace_id}.firetell.app/api/v1/calls/make" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"number": "+84901234567",
"name": "VoiceBot Support"
},
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"actions": [
{
"action": "stream",
"params": {
"ws_url": "wss://your-bot-server.example.com/call-stream",
"track": "both",
"sample_rate": 8000,
"bidirectional": true,
"headers": {
"Authorization": "Bearer your-api-token",
"X-Bot-Version": "v2"
}
}
}
]
}'

WebSocket protocol on your server side:

DirectionFrame typeContent
Firetell โ†’ Your serverBinaryPCM audio at sample_rate Hz (stereo if track=both: caller on left, callee on right)
Your server โ†’ FiretellBinaryMono PCM audio at sample_rate Hz โ€” played back to the caller in real-time (requires bidirectional: true)
Your server โ†’ FiretellText (JSON){"type":"killAudio"} โ€” instructs Firetell to immediately stop any queued audio playback (barge-in)
tip

call_id, workspace_id, caller_number, caller_name, destination_number, and stream_type=firetell_stream are automatically appended to your ws_url as query parameters so your server can identify the call and caller without needing custom headers.

Responseโ€‹

All POST /calls/make requests return:

{
"data": {
"call_id": "call_abc123",
"status": "created",
"direction": "outbound",
"from": {
"name": "Customer Support",
"number": "+84901234567"
},
"to": {
"name": "John Doe",
"number": "+84909876543"
},
"job_id": "job_xyz789",
"job_status": "queued"
}
}

Update Call Actionsโ€‹

Update the actions on an active call. Requires ApiKey with full scope.

The call must be in started or active status, and the media channel must be ready.

PUT /calls/:id/actions

Request Bodyโ€‹

FieldTypeRequiredDescription
actionsarrayโœ…Array of call action objects (minimum 1). See Action Reference above for available actions and params.

Example Requestโ€‹

curl -X PUT "https://{workspace_id}.firetell.app/api/v1/calls/call_abc123/actions" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"actions": [
{
"action": "tts",
"params": { "text": "Your order has been confirmed. Goodbye!" },
"continue": true
},
{
"action": "disconnect"
}
]
}'

Responseโ€‹

{
"data": {
"call_id": "call_abc123",
"queued": true,
"action_count": 2
}
}

Get Call Eventsโ€‹

Retrieve the event timeline for a specific call, sorted chronologically. Requires ApiKey with any scope.

GET /calls/:id/events?page=1&limit=50

Responseโ€‹

{
"data": [
{
"id": "evt_abc123",
"call_id": "call_abc123",
"event": "call.created",
"direction": "outbound",
"sip_code": null,
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"created_at": "2026-07-09T10:00:00Z"
},
{
"id": "evt_abc124",
"call_id": "call_abc123",
"event": "call.ringing",
"direction": "outbound",
"sip_code": null,
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"created_at": "2026-07-09T10:00:02Z"
},
{
"id": "evt_abc125",
"call_id": "call_abc123",
"event": "call.answered",
"direction": "outbound",
"sip_code": 200,
"to": {
"number": "+84909876543",
"name": "John Doe"
},
"created_at": "2026-07-09T10:00:05Z"
},
{
"id": "evt_abc126",
"call_id": "call_abc123",
"event": "call.ended",
"direction": "outbound",
"sip_code": 200,
"hangup_cause": "NORMAL_CLEARING",
"created_at": "2026-07-09T10:00:50Z"
}
],
"meta": {
"total": 4,
"page": 1,
"limit": 50,
"total_pages": 1
}
}

Event Typesโ€‹

EventDescription
call.createdCall channel created
call.answeredCall was answered
call.bridgedTwo call legs bridged together
call.endedCall hangup completed
call.destroyedCall channel destroyed
call.dtmfDTMF digit received
call.playback_startedAudio playback started
call.playback_stoppedAudio playback stopped
call.recording.startedCall recording stream started (In-Call SSE)
call.recording.completedCall recording stream completed (In-Call SSE)
call.recording.readyCall recording uploaded and ready (Webhook & SSE)
call.transcription.dialogueLive speech transcription utterance (In-Call SSE)
call.transcription.completedCall transcription with NER entities (Webhook)