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.

IVR Menu with Queue Routing

A common contact center pattern: caller navigates an IVR menu, then enters a queue.

IVR to Queue Flow:

Caller                          VoIPBIN                         Agent
   |                               |                              |
   | Calls support number          |                              |
   +------------------------------>|                              |
   |                               |                              |
   |<------------------------------+                              |
   | "Press 1 for Sales,           |                              |
   |  Press 2 for Support"         |                              |
   |                               |                              |
   | Press 2                       |                              |
   +------------------------------>|                              |
   |                               |                              |
   |<------------------------------+                              |
   | "Please hold, connecting      |                              |
   |  to support..."               |                              |
   |                               |                              |
   |<------------------------------+                              |
   | (Hold music plays)            |                              |
   |                               |                              |
   |                               | Find available agent         |
   |                               +----------------------------->|
   |                               |                              |
   |                               |<-----------------------------+
   |                               | Agent accepts                |
   |                               |                              |
   |<==============================+==============================>|
   | Connected to agent            |       Connected to caller    |
   |                               |                              |

Flow Configuration:

{
    "name": "Support IVR with Queue",
    "actions": [
        {
            "id": "welcome",
            "type": "talk",
            "option": {
                "text": "Thank you for calling. Press 1 for Sales, Press 2 for Support, Press 3 for Billing.",
                "language": "en-US"
            }
        },
        {
            "type": "digits_receive",
            "option": {
                "duration": 10000,
                "length": 1
            }
        },
        {
            "type": "branch",
            "option": {
                "default_target_id": "invalid",
                "target_ids": {
                    "1": "sales_queue",
                    "2": "support_queue",
                    "3": "billing_queue"
                }
            }
        },
        {
            "id": "sales_queue",
            "type": "talk",
            "option": {
                "text": "Connecting you to Sales. Please hold."
            }
        },
        {
            "type": "queue_join",
            "option": {
                "queue_id": "sales-queue-uuid"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "support_queue",
            "type": "talk",
            "option": {
                "text": "Connecting you to Support. Please hold."
            }
        },
        {
            "type": "queue_join",
            "option": {
                "queue_id": "support-queue-uuid"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "billing_queue",
            "type": "talk",
            "option": {
                "text": "Connecting you to Billing. Please hold."
            }
        },
        {
            "type": "queue_join",
            "option": {
                "queue_id": "billing-queue-uuid"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "invalid",
            "type": "talk",
            "option": {
                "text": "Invalid selection."
            }
        },
        {
            "type": "goto",
            "option": {
                "target_id": "welcome",
                "loop_count": 2
            }
        },
        {
            "type": "talk",
            "option": {
                "text": "Goodbye."
            }
        },
        {
            "type": "hangup"
        }
    ]
}

Note

AI Implementation Hint

The queue_id values (e.g., "sales-queue-uuid") must be valid UUIDs obtained from GET /queues. The branch action’s target_ids map DTMF digits to action id values within the same flow. If a target_id does not match any action id, the flow will fail silently. Always include a default_target_id to handle unexpected input. The goto action’s loop_count prevents infinite loops – after the specified number of iterations, execution continues to the next action.

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 /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 few seconds)|                       |
   |                    |                       |
   +--- Human detected --+                      |
   |                    |                       |
   | Play message       |                       |
   +------------------->|                       |
   |                    |                       |
   | "Press 1 to speak  |                       |
   |  with an agent"    |                       |
   +------------------->|                       |
   |                    |                       |
   |                    |                       |
   +--- Machine detected ------------------------>|
   |                    |                       |
   | Hangup             |                       |
   +-------------------------------------->|    |
   |                    |                       |

Campaign Configuration:

POST /campaigns
{
    "name": "Customer Reminder Campaign",
    "detail": "Automated reminder calls before appointments",
    "type": "call",
    "service_level": 100,
    "end_handle": "stop",
    "outplan_id": "outplan-uuid",
    "outdial_id": "outdial-uuid",
    "queue_id": "queue-uuid",
    "actions": [
        {
            "type": "amd",
            "option": {
                "machine_handle": "hangup",
                "async": false
            }
        },
        {
            "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": "no_response",
            "type": "goto",
            "option": {"target_id": "human_path", "loop_count": 2}
        },
        {"type": "hangup"}
    ]
}

Note

AI Implementation Hint

outplan_id, outdial_id, and queue_id must be valid UUIDs obtained from GET /outplans, GET /outdials, and GET /queues respectively – all three are required to create a campaign. Each call placed by the campaign is individually chargeable. The amd (Answering Machine Detection) action analyzes the first few seconds of audio after answer and only supports two outcomes via machine_handle: "hangup" (immediately end the call if a machine answered, recorded with hangup_reason: "amd") or "continue" (proceed to the next action regardless of who answered). The amd action does not branch to different action id values for human vs. machine – with machine_handle: "hangup", only calls answered by a person survive past the amd action, so the flow can safely assume a live person from that point on. Set async: false to pause the flow until AMD analysis completes before executing the next action.

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 /calls
{
    "source": {
        "type": "tel",
        "target": "+15551234567",
        "name": "Acme Support"
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+15559876543"
        }
    ],
    "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": "recording_start",
            "option": {
                "format": "wav"
            }
        },
        {
            "type": "connect",
            "option": {
                "source": {"type": "tel", "target": "+15551234567"},
                "destinations": [
                    {"type": "tel", "target": "+15552222222"}
                ]
            }
        },
        {
            "type": "recording_stop"
        }
    ]
}

Note

AI Implementation Hint

The source.target in POST /calls must be a phone number you own, verified via GET /numbers. Flow actions execute only after the destination answers (this is always the case for calls created via POST /calls – there is no way to opt into early execution from the public API). The recording_start action must be placed before connect in the action list to capture the full conversation, and only format: "wav" is currently supported. 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_hangup
{
    "type": "call_hangup",
    "data": {
        "id": "call-uuid",
        "duration": 245,
        "recording_ids": ["recording-uuid"],
        "hangup_by": "remote",
        "hangup_reason": "normal"
    }
}

Your Server Response:
1. Fetch recording: GET /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 /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 /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 /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 /conferences response or from GET /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.

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 /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 /transfers must be the UUID of an active call in progressing status, obtained from GET /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 /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.