Advanced Call Scenarios¶
This section covers real-world call scenarios that combine multiple VoIPBIN features. Each scenario includes the complete flow, API examples, and best practices.
Note
AI Implementation Hint
All scenarios in this section involve active outbound calls, which are chargeable. Each POST /calls request creates a billable call. Test your flow logic with a single destination before scaling to production. Use GET /calls/{call-id} to verify call status at each step.
AI-Assisted Customer Service¶
Combine AI voice assistant with human escalation:
AI First, Human Backup:
Caller AI Assistant Agent
| | |
| "I need to check | |
| my order status" | |
+----------------------->| |
| | |
| | Query CRM |
| | (tool call) |
| | |
|<-----------------------+ |
| "Your order #12345 | |
| shipped yesterday. | |
| Tracking: ABC123" | |
| | |
| "I want to talk to | |
| a real person" | |
+----------------------->| |
| | |
|<-----------------------+ |
| "Let me transfer you | |
| to an agent" | |
| | |
| | Transfer |
| | (tool call) |
| +--------------------->|
| | |
|<==============================================|
| Connected to agent | |
| | |
AI Assistant Configuration:
POST /v1/calls
{
"source": {"type": "tel", "target": "+15551234567"},
"destinations": [{"type": "tel", "target": "+15559876543"}],
"actions": [
{
"type": "ai_talk",
"option": {
"ai_id": "customer-service-ai-uuid",
"prompt": "You are a helpful customer service agent for Acme Corp. You can look up orders, check account balances, and answer questions about products. If the customer asks to speak to a human, transfer them to the support queue.",
"tools": [
{
"name": "lookup_order",
"description": "Look up order status by order ID or customer phone",
"webhook_url": "https://your-server.com/api/orders"
},
{
"name": "transfer_to_agent",
"description": "Transfer the call to a human agent",
"action": "transfer",
"destination": "queue:support-queue-uuid"
}
],
"end_call_phrases": ["goodbye", "bye", "that's all"]
}
}
]
}
Note
AI Implementation Hint
The ai_id in the ai_talk action must be a valid UUID obtained from GET /ais. Tool definitions with webhook_url will send HTTP POST requests to your server when the AI invokes the tool – ensure your endpoint is publicly accessible and returns responses within 5 seconds. The end_call_phrases trigger automatic call hangup when the caller says any of the listed phrases.
Outbound Campaign with Voicemail Detection¶
Automated calling campaign that detects answering machines:
Campaign Call Flow:
VoIPBIN Destination Voicemail
| | |
| Dial | |
+------------------->| |
| | |
| Answer? | |
|<-------------------+ |
| | |
| AMD Analysis | |
| (first 3 seconds) | |
| | |
+--- Human detected --+ |
| | |
| Play message | |
+------------------->| |
| | |
| "Press 1 to speak | |
| with an agent" | |
+------------------->| |
| | |
| | |
+--- Machine detected ------------------------>|
| | |
| Leave voicemail | |
| message | |
+-------------------------------------->| |
| | |
| Hangup | |
+-------------------------------------->| |
| | |
Campaign Configuration:
POST /v1/campaigns
{
"name": "Customer Reminder Campaign",
"outplan_id": "outplan-uuid",
"flow_id": "campaign-flow-uuid",
"dial_timeout": 30000,
"max_concurrent_calls": 10,
"schedule": {
"timezone": "America/New_York",
"start_time": "09:00",
"end_time": "17:00",
"days": ["mon", "tue", "wed", "thu", "fri"]
}
}
Campaign Flow:
{
"actions": [
{
"type": "amd",
"option": {
"machine_action": "voicemail",
"human_action": "continue",
"timeout": 3000
}
},
{
"id": "human_path",
"type": "talk",
"option": {
"text": "Hello! This is a reminder from Acme Corp about your upcoming appointment. Press 1 to confirm, Press 2 to reschedule."
}
},
{
"type": "digits_receive",
"option": {"duration": 10000, "length": 1}
},
{
"type": "branch",
"option": {
"target_ids": {
"1": "confirmed",
"2": "reschedule"
},
"default_target_id": "no_response"
}
},
{
"id": "confirmed",
"type": "talk",
"option": {"text": "Great! Your appointment is confirmed. Goodbye."}
},
{"type": "hangup"},
{
"id": "reschedule",
"type": "talk",
"option": {"text": "Please hold while we connect you to schedule a new time."}
},
{
"type": "connect",
"option": {
"destinations": [{"type": "tel", "target": "+15551234567"}]
}
},
{
"id": "voicemail",
"type": "talk",
"option": {
"text": "Hello, this is Acme Corp reminding you of your upcoming appointment. Please call us back at 555-123-4567 to confirm. Thank you."
}
},
{"type": "hangup"},
{
"id": "no_response",
"type": "goto",
"option": {"target_id": "human_path", "loop_count": 2}
},
{"type": "hangup"}
]
}
Note
AI Implementation Hint
The outplan_id and flow_id must be valid UUIDs obtained from GET /outplans and GET /flows respectively. Each call placed by the campaign is individually chargeable. The amd (Answering Machine Detection) action analyzes the first few seconds of audio after answer – if it detects a voicemail greeting, execution jumps to the action with id matching machine_action. The max_concurrent_calls limits how many calls the campaign places at the same time.
Click-to-Call with Recording¶
Website visitor clicks to call, conversation is recorded:
Click-to-Call Flow:
Website Your Server VoIPBIN Visitor Phone Agent
| | | | |
| Click "Call Me" | | | |
+---------------->| | | |
| | | | |
| | POST /calls | | |
| +---------------->| | |
| | | | |
| | | Call visitor | |
| | +------------------->| |
| | | | |
|<----------------+<----------------+<-------------------+ |
| "Calling you..."| Call created | Ringing | |
| | | | |
| | |<-------------------+ |
| | | Answered | |
| | | | |
| | | Start recording | |
| | | | |
| | | Play greeting | |
| | +------------------->| |
| | | | |
| | | Bridge to agent | |
| | +---------------------------------->|
| | | | |
| | | |<============>|
| | | Recording both directions |
| | | | |
API Request:
POST /v1/calls
{
"source": {
"type": "tel",
"target": "+15551234567",
"name": "Acme Support"
},
"destinations": [
{
"type": "tel",
"target": "+15559876543"
}
],
"early_execution": false,
"actions": [
{
"type": "talk",
"option": {
"text": "Hello! Thank you for requesting a callback from Acme Corp. Please hold while we connect you to an agent.",
"language": "en-US"
}
},
{
"type": "record_start",
"option": {
"direction": "both",
"format": "mp3"
}
},
{
"type": "connect",
"option": {
"source": {"type": "tel", "target": "+15551234567"},
"destinations": [
{"type": "tel", "target": "+15552222222"}
],
"ring_timeout": 30000
}
},
{
"type": "record_stop"
}
]
}
Note
AI Implementation Hint
The source.target in POST /v1/calls must be a phone number you own, verified via GET /numbers. The early_execution: false setting (default) ensures actions execute only after the destination answers. The record_start action must be placed before connect in the action list to capture the full conversation. After the call ends, retrieve the recording via GET /recordings/{recording-id} using the ID from the call’s recording_ids array.
Webhook Integration:
Webhook: call_hungup
{
"type": "call_hungup",
"data": {
"id": "call-uuid",
"duration": 245,
"recording_ids": ["recording-uuid"],
"hangup_by": "remote",
"hangup_reason": "normal"
}
}
Your Server Response:
1. Fetch recording: GET /v1/recordings/{recording-uuid}
2. Download audio: GET {recording.url}
3. Store in your CRM
4. Update call log with recording link
Multi-leg Conference Call¶
Create a conference with multiple participants joining at different times:
Multi-leg Conference:
Organizer VoIPBIN Participant A Participant B Participant C
| | | | |
| Create | | | |
| Conference | | | |
+-------------->| | | |
| | | | |
|<--------------+ | | |
| Conf ID | | | |
| | | | |
| Add self | | | |
+-------------->| | | |
| | | | |
|<==============> | | |
| In conference | | | |
| | | | |
| Dial out to A | | | |
+-------------->| | | |
| | Call A | | |
| +-------------->| | |
| | | | |
| |<--------------+ | |
| | Answered | | |
| | | | |
|<==============><==============> | |
| A joins conf | | | |
| | | | |
| Dial out to B | | | |
+-------------->| | | |
| | Call B | | |
| +------------------------------>| |
| | | | |
| |<------------------------------+ |
| | Answered | | |
| | | | |
|<==============><==============><==============>| |
| B joins conf | | | |
| | | | |
| | | | C dials in |
| | | | |
| |<---------------------------------------+-------+
| | Inbound call | | |
| | | | |
|<==============><==============><==============>|<==============>|
| All in conf | | | |
Conference Creation:
Step 1: Create Conference
POST /v1/conferences
{
"name": "Weekly Team Sync",
"customer_id": "customer-uuid"
}
Response:
{
"id": "conf-uuid",
"name": "Weekly Team Sync",
"status": "active",
"participant_count": 0
}
Step 2: Add Organizer via Dial-in
POST /v1/calls
{
"source": {"type": "tel", "target": "+15551111111"},
"destinations": [{"type": "tel", "target": "+15550000000"}],
"actions": [
{
"type": "conference_join",
"option": {
"conference_id": "conf-uuid",
"role": "moderator",
"mute_on_join": false
}
}
]
}
Step 3: Dial Out to Participants
POST /v1/calls
{
"source": {"type": "tel", "target": "+15551111111", "name": "Team Sync"},
"destinations": [{"type": "tel", "target": "+15552222222"}],
"actions": [
{
"type": "talk",
"option": {
"text": "You are being connected to the Weekly Team Sync."
}
},
{
"type": "conference_join",
"option": {
"conference_id": "conf-uuid",
"role": "participant",
"mute_on_join": false
}
}
]
}
Note
AI Implementation Hint
The conference_id in conference_join must be obtained from the id field in the POST /v1/conferences response or from GET /v1/conferences. The customer_id in the conference creation request must match your authenticated customer ID. Each dial-out to a participant creates a separate billable call. The role field controls permissions: moderator can mute/unmute others, while participant can only control their own audio.
Call Screening with Whisper¶
Screen calls before connecting to agent:
Call Screening Flow:
Caller VoIPBIN Agent
| | |
| Incoming call | |
+----------------->| |
| | |
|<-----------------+ |
| "Please state | |
| your name" | |
| | |
| "John Smith" | |
+----------------->| |
| | |
| (Record name) | |
| | |
|<-----------------+ |
| "Please hold" | |
| | |
| (Hold music) | Dial agent |
| +----------------->|
| | |
| |<-----------------+
| | Agent answers |
| | |
| | Whisper to agent |
| | (caller can't hear)
| +----------------->|
| | "You have a call |
| | from John Smith"|
| +----------------->|
| | "Press 1 accept, |
| | 2 to reject" |
| +----------------->|
| | |
| |<-----------------+
| | Press 1 |
| | |
|<=================>==================>|
| Connected | |
| | |
Flow Configuration:
{
"actions": [
{
"type": "talk",
"option": {
"text": "Please state your name after the beep."
}
},
{
"type": "record_voice",
"option": {
"duration": 5000,
"silence_timeout": 2000,
"variable_name": "caller_name_recording"
}
},
{
"type": "talk",
"option": {
"text": "Thank you. Please hold while we connect you."
}
},
{
"type": "moh_start",
"option": {
"music_class": "default"
}
},
{
"type": "connect",
"option": {
"destinations": [{"type": "tel", "target": "+15552222222"}],
"whisper": {
"enabled": true,
"message": "You have a call from:",
"play_recording": "{{caller_name_recording}}",
"accept_key": "1",
"reject_key": "2"
}
}
}
]
}
Note
AI Implementation Hint
The whisper feature in the connect action plays a message only to the agent (the caller cannot hear it). The record_voice action stores the recording in a flow variable (caller_name_recording) that can be referenced later using {{variable_name}} syntax. If the agent presses the reject_key, the connect action fails and flow execution continues to the next action – add a fallback (e.g., try another agent or go to voicemail).
Warm Transfer with Context¶
Transfer call with context passed to the receiving agent:
Warm Transfer Flow:
Caller Agent A VoIPBIN Agent B
| | | |
|<===============> | |
| Talking | | |
| | | |
| | Initiate | |
| | transfer | |
| +--------------->| |
| | | |
|<---------------+ | |
| (On hold) | | |
| | | Call Agent B |
| | +--------------->|
| | | |
| | |<---------------+
| | | Answered |
| | | |
| |<===============>================|
| | Talk to B | |
| | (Caller on hold) |
| | | |
| | "Customer has | |
| | billing issue"| |
| | | |
| | Complete | |
| | transfer | |
| +--------------->| |
| | | |
|<===============================>=================|
| Connected to B | (Disconnected) | |
| | | |
API for Attended Transfer:
Step 1: Agent A initiates transfer
POST /v1/transfers
{
"transfer_type": "attended",
"transferer_call_id": "call-uuid-of-agent-a",
"transferee_addresses": [
{
"type": "tel",
"target": "+15553333333"
}
]
}
Response:
{
"id": "transfer-uuid",
"type": "attended",
"transferer_call_id": "call-uuid-of-agent-a",
"transferee_call_id": "consult-call-uuid",
"transferee_addresses": [
{"type": "tel", "target": "+15553333333"}
]
}
Step 2: Agent A talks to Agent B, then completes
the transfer by hanging up their call.
Step 3: The caller and Agent B are now connected.
Note
AI Implementation Hint
The transferer_call_id in POST /v1/transfers must be the UUID of an active call in progressing status, obtained from GET /v1/calls. The transfer_type is an enum: attended or blind. The transferee_addresses array must contain at least one address (E.164 phone number or extension). The response includes a transferee_call_id (UUID) for the new outbound call to the transfer destination. The consult call to Agent B is a separate billable call.
Call with Real-time Transcription¶
Transcribe call in real-time for live captioning or analysis:
Real-time Transcription:
Caller VoIPBIN STT Service Your Server
| | | |
| Speaking | | |
+-------------->| | |
| | | |
| | Audio stream | |
| +--------------->| |
| | | |
| |<---------------+ |
| | Transcript: | |
| | "I need help" | |
| | | |
| | WebSocket push | |
| +---------------------------------->|
| | | |
| | | | Display
| | | | caption
| | | |
| (continues) | | |
+-------------->| | |
| | | |
| | More audio | |
| +--------------->| |
| | | |
| |<---------------+ |
| | "with my order"| |
| | | |
| +---------------------------------->|
| | | |
Enable Transcription:
POST /v1/calls
{
"source": {"type": "tel", "target": "+15551234567"},
"destinations": [{"type": "tel", "target": "+15559876543"}],
"actions": [
{
"type": "transcribe_start",
"option": {
"language": "en-US",
"direction": "both"
}
},
{
"type": "connect",
"option": {
"destinations": [{"type": "tel", "target": "+15552222222"}]
}
},
{
"type": "transcribe_stop"
}
]
}
WebSocket subscription for real-time transcripts:
{
"type": "subscribe",
"topics": ["customer_id:<your-id>:transcript:*"]
}
Received events:
{
"type": "transcript_created",
"data": {
"transcribe_id": "transcribe-uuid",
"direction": "in",
"message": "I need help with my order",
"tm_transcript": "0001-01-01 00:00:05.123"
}
}
Note
AI Implementation Hint
Real-time transcription events are delivered via WebSocket, not webhooks. You must establish a WebSocket connection to wss://api.voipbin.net/v1.0/ws?token=<token> and subscribe to the customer_id:<your-id>:transcript:* topic before the call starts to receive all events. The direction field in transcript events indicates which party is speaking: in for the caller, out for the agent/system. Place transcribe_start before connect in the action list to capture transcription from the beginning of the conversation.