Call

Create, control, and manage the full lifecycle of voice calls including outbound dialing, call transfers, group calls, and media operations. Calls transition through defined states from dialing to hangup.

API Reference: Call endpoints

Overview

Note

AI Context

  • Complexity: Medium

  • Cost: Chargeable (credit deduction per call minute)

  • Async: Yes. POST /calls returns immediately with status dialing. Poll GET /calls/{id} or subscribe via WebSocket to track call status changes.

The VoIPBIN call API provides a straightforward and convenient way to develop high-quality call applications in the Cloud. With the VoIPBIN API, developers can leverage familiar web technologies to build scalable and feature-rich call applications, giving them the power to control inbound and outbound call flows using JSON-based VoIPBIN actions. Additionally, the API offers capabilities to record and store inbound or outbound calls, create conference calls, and send text-to-speech messages in multiple languages with different gender and accents.

With the VoIPBIN API you can:

  • Build apps that scale with the web technologies you are already using.

  • Control the flow of inbound and outbound calls in JSON with VoIPBIN’s actions.

  • Record and store inbound or outbound calls.

  • Create conference calls.

  • Send text-to-speech messages in 50 languages with different gender and accents.

Protocol

VoIPBIN offers support for various call/video protocols, enabling users to join the same conference room and communicate with one another seamlessly. The flexibility in protocol options ensures efficient and reliable communication between different devices and platforms.

_images/call_overview_protocol.png

PSTN/Phone Number Format

In the VoIPBIN APIs, all PSTN/Phone numbers must adhere to the +E164 format. This format standardizes the representation of phone numbers to facilitate smooth communication and interoperability across different systems.

Key requirements for phone numbers within the VoIPBIN APIs:

  • The phone number must have the ‘+’ symbol at the beginning.

  • The number should not contain any special characters, such as spaces, parentheses, or hyphens.

For example, a US phone number should be represented as +16062067563, and a UK phone number should be represented as +442071234567.

Extension Number Format

The extension numbers used in the VoIPBIN system can be customized according to specific requirements. However, they must adhere to the following limitation:

  • Extension numbers should not contain any special characters, such as spaces, parentheses, or hyphens.

The absence of special characters ensures consistent and reliable processing of extension numbers within the VoIPBIN system, promoting smooth communication and interaction.

Call Lifecycle

Every call in VoIPBIN follows a predictable lifecycle from creation to termination. Understanding this lifecycle helps you build reliable applications that respond correctly to call state changes.

State Diagram

                               +--------------+
                               |   dialing    |
                               | (call starts)|
                               +------+-------+
                                      |
                +---------------------+---------------------+
                |                     |                     |
                v                     v                     v
         +------------+        +------------+        +------------+
         |  ringing   |        | canceling  |        |  hangup    |
         | (dest rang)|        | (caller    |        | (failed)   |
         +-----+------+        |  cancels)  |        +------------+
               |               +-----+------+
               |                     |
               v                     |
        +-------------+              |
        | progressing |              |
        | (answered)  |              |
        +------+------+              |
               |                     |
      +--------+--------+            |
      v                 v            |
+------------+   +------------+      |
|terminating |   |  hangup    |      |
|  (ending   |   |  (remote   |      |
|   locally) |   |  hangup)   |      |
+-----+------+   +------------+      |
      |                              |
      +--------------+---------------+
                     v
              +------------+
              |   hangup   |
              |  (final)   |
              +------------+

State Descriptions

Status

What is happening

dialing

Call has been created. The system is attempting to reach the destination through the phone network.

ringing

The destination device is ringing. The person being called can now answer.

progressing

The call has been answered. Both parties can now hear each other. Media (audio/video) is flowing.

terminating

The system is ending the call. This happens when your application hangs up or a flow action ends the call.

canceling

The caller is canceling before the destination answered. Only happens for outgoing calls.

hangup

The call has ended. This is the final state - no further changes are possible.

Key Behaviors

  • States only move forward, never backward. A call that reached “progressing” cannot go back to “ringing”.

  • Once a call reaches “hangup”, it cannot change anymore.

  • The “canceling” state only applies to outgoing calls (when the originator hangs up before answer).

What Happens At Each Stage

During Dialing

When you create an outbound call or receive an inbound call, the call enters the dialing state.

Your App                    VoIPBIN                    Destination
   |                           |                            |
   |  POST /v1/calls           |                            |
   +-------------------------->|                            |
   |                           |  SIP INVITE                |
   |                           +--------------------------->|
   |                           |                            |
   |  Call object              |                            |
   |  status: "dialing"        |                            |
   |<--------------------------+                            |

At this point:

  • VoIPBIN is trying to reach the destination

  • No audio is flowing yet

  • The call may fail if the network is unreachable

During Ringing

The destination device is ringing. The person can pick up the phone.

|                           |                            |
|                           |  180 Ringing               |
|                           |<---------------------------+
|  Webhook: call_updated    |                            |
|  status: "ringing"        |       Ring Ring            |
|<--------------------------+                            |

At this point:

  • The destination phone is ringing

  • Early media (ringback tone) may be playing

  • The caller is waiting for an answer

During Progressing (Answered)

The call has been answered. This is when real communication begins.

|                           |                            |
|                           |  200 OK                    |
|                           |<---------------------------+
|  Webhook: call_updated    |                            |
|  status: "progressing"    |   <=====================>  |
|<--------------------------+        (Audio flows)       |

At this point:

  • Both parties can hear each other

  • Flow actions start executing (if defined)

  • Recording can begin

  • Media controls (hold, mute) become available

During Hangup

The call has ended. Check the hangup_by and hangup_reason fields to understand why.

|                           |                            |
|                           |  BYE                       |
|                           |<---------------------------+
|  Webhook: call_updated    |                            |
|  status: "hangup"         |                            |
|  hangup_by: "remote"      |                            |
|  hangup_reason: "normal"  |                            |
|<--------------------------+                            |

Understanding Hangup Reasons

When a call ends, VoIPBIN tells you why it ended. This helps you build appropriate responses for different scenarios.

Hangup Reason Values

Hangup By Values

Common Scenarios

Scenario: Normal conversation
----------------------------
hangup_by: "remote"
hangup_reason: "normal"
-> The other person hung up after talking

Scenario: Missed call
----------------------------
hangup_by: "remote"
hangup_reason: "noanswer"
-> Phone rang but nobody answered

Scenario: Your app ended the call
----------------------------
hangup_by: "local"
hangup_reason: "normal"
-> Your flow action or API call ended it

Scenario: Network problem
----------------------------
hangup_by: "remote"
hangup_reason: "failed"
-> Call never connected due to network issues

Media Control Operations

Once a call is in the “progressing” state (answered), you can control the audio in several ways. Each operation is independent - you can combine them as needed.

Hold

Pauses the call. The other party hears silence (or music if MOH is enabled).

Before Hold                          After Hold
+---------+     audio      +---------+     +---------+     silence   +---------+
| Caller  | <============> | VoIPBIN |     | Caller  | ------------> | VoIPBIN |
+---------+                +---------+     +---------+  (or music)   +---------+
  • Use hold when the caller needs to wait (e.g., while transferring)

  • The caller stays connected but cannot hear ongoing activity

  • Unhold resumes normal audio

Mute

Silences audio in one or both directions without putting the call on hold.

Mute "in"                    Mute "out"                   Mute "both"
+----+  ---X-->  +----+     +----+  <--X---  +----+      +----+  --X--  +----+
| A  |  <------  | B  |     | A  |  -------> | B  |      | A  |  --X--  | B  |
+----+           +----+     +----+           +----+      +----+         +----+
A cannot hear B            A cannot be heard           Complete silence
  • “in”: The call cannot hear incoming audio

  • “out”: The call’s audio is not sent to others

  • “both”: Complete silence in both directions

Recording

Captures the call audio for later playback.

+---------+         +---------+         +---------+
| Caller  | <=====> | VoIPBIN | <=====> |  Dest   |
+---------+         +----+----+         +---------+
                         |
                         v (recording)
                    +---------+
                    |  File   |
                    +---------+
  • recording_id shows the current recording (if active)

  • recording_ids lists all recordings made during this call’s lifetime

  • You can start and stop recording multiple times in one call

Call Chaining

VoIPBIN’s call concept differs from traditional 1:1 calls. A single logical conversation may involve multiple call objects linked together.

The Two-Call Model

When you make a call from A to B through VoIPBIN, there are actually two separate calls:

Traditional View:     A -----------------------> B

VoIPBIN Reality:      A <--- Call 1 ---> VoIPBIN <--- Call 2 ---> B
                               |                        |
                               +------------------------+
                                      (bridged audio)

Why Two Calls?

This design enables powerful features:

  • Recording: VoIPBIN can record both sides independently

  • Conferencing: Add more parties without changing the original calls

  • Transfer: Move calls between agents without dropping the caller

  • Flow Control: Run different actions on each call leg

Master and Chained Calls

When calls are related, they form a chain:

+-------------------------------------------------------+
|                    Master Call                        |
|  master_call_id: 00000000-0000-0000-0000-000000000000 |
|  chained_call_ids: [call-2-id, call-3-id]             |
+-------------------------+-----------------------------+
                          |
          +---------------+---------------+
          v               v               v
    +----------+    +----------+    +----------+
    | Call 2   |    | Call 3   |    | Call 4   |
    | master:  |    | master:  |    | master:  |
    | call-1-id|    | call-1-id|    | call-1-id|
    +----------+    +----------+    +----------+

Chaining Behaviors

  • When the master call hangs up, all chained calls automatically hang up

  • Chained calls can only be added while the master is in dialing, ringing, or progressing state

  • Each chained call tracks its master via the master_call_id field

Common Use Case: Transfer

Step 1: Caller and Agent talking
+--------+       +---------+       +--------+
| Caller |<----->| VoIPBIN |<----->| Agent  |
+--------+       +----+----+       +--------+
                      |
                 Master Call

Step 2: Agent initiates transfer to Supervisor
+--------+       +---------+       +--------+
| Caller |<----->| VoIPBIN |       | Agent  | (on hold)
+--------+       +----+----+       +--------+
                      |
                      +-----------> +------------+
                      |            | Supervisor | (ringing)
                 Chained Call      +------------+

Step 3: Supervisor answers, Agent drops
+--------+       +---------+       +------------+
| Caller |<----->| VoIPBIN |<----->| Supervisor |
+--------+       +---------+       +------------+

Multi-Party Chaining (3+ Parties)

Call chaining supports more than two parties. Each chained call connects to the master:

+--------+       +---------+       +---------+
| Caller |<----->| VoIPBIN |<----->| Agent 1 |
+--------+       +----+----+       +---------+
                      |
                      +------------>+---------+
                      |             | Agent 2 |
                      |             +---------+
                      |
                      +------------>+------------+
                                    | Supervisor |
                                    +------------+

Master: Caller's call
Chained: Agent 1, Agent 2, Supervisor (all linked to master)

Chaining vs Conference Decision Guide

                Need multiple parties?
                       |
          +------------+------------+
          |                         |
     Sequential?               Simultaneous?
     (one at a time)          (all at once)
          |                         |
    +-----+-----+             +-----+-----+
    |           |             |           |
   Yes         No            Yes         No
    |           |             |           |
    v           |             v           |
[Chaining]      |       [Conference]      |
                |                         |
           Need transfers?                |
                |                         |
          +-----+-----+                   |
          |           |                   |
         Yes         No                   |
          |           +-------------------+
          v                   |
      [Chaining]              v
                        [Conference]

Aspect

Call Chaining

Conference

Parties

Sequential (transfer model)

Simultaneous (meeting model)

Audio

Bridged between pairs

Mixed for all participants

Master Control

Master hangup ends all

Host controls conference

Best For

Transfers, escalation, queues

Meetings, group calls

Timestamps Explained

Each call tracks important moments in its lifecycle:

Timeline of a successful call:

| tm_create                    tm_ringing          tm_progressing              tm_hangup
|     |                            |                    |                          |
v     v                            v                    v                          v
------o----------------------------o--------------------o--------------------------o------>
      |                            |                    |                          |
      |<--- dialing -------------->|<--- ringing ------>|<---- progressing ------->|
      |                            |                    |                          |
   Call created              Phone started           Call answered            Call ended
                               ringing

Timestamp

When it’s set

tm_create

When the call object was created in VoIPBIN

tm_ringing

When the destination phone started ringing

tm_progressing

When the call was answered

tm_hangup

When the call ended

tm_update

Last time any call property changed

Calculating Durations

Ring duration = tm_progressing - tm_ringing
Talk duration = tm_hangup - tm_progressing
Total duration = tm_hangup - tm_create

Route Failover

When an outgoing call fails during dialing or ringing, VoIPBIN can automatically try alternate routes.

+-----------------------------------------------------------------+
|                       Call Attempt Flow                         |
+-----------------------------------------------------------------+

                          Create Call
                               |
                               v
                       +--------------+
                       |   Route 1    |
                       |  (Primary)   |
                       +------+-------+
                              |
                      +-------+-------+
                      v               v
                 Connected?       Failed?
                      |               |
                      v               v
                  Success      +--------------+
                               |   Route 2    |
                               |  (Backup)    |
                               +------+-------+
                                      |
                              +-------+-------+
                              v               v
                         Connected?       Failed?
                              |               |
                              v               v
                          Success      +--------------+
                                       |   Route 3    |
                                       |  (Last try)  |
                                       +------+-------+
                                              |
                                              v
                                        Final Result

Failover Rules

Not all failures trigger failover. VoIPBIN only tries the next route when recovery is possible:

Hangup Reason

Failover

Why

failed

Yes

Network issue - another route might work

busy

No

The person is busy - trying again won’t help

noanswer

No

They didn’t answer - their choice

cancel

No

Caller cancelled - no need to retry

normal

No

Call succeeded - nothing to retry

No Failover Cases

Failover is disabled in these situations:

  • Incoming calls (the route is fixed by the caller)

  • Conference calls

  • Calls where flow execution already started (early_execution flag)

Incoming call

The VoIPBIN system provides the functionality to receive incoming calls from external parties. This feature allows users to accept and handle incoming calls through their VoIP services. Incoming calls are crucial for various communication applications and call center setups as they enable users to receive inquiries, provide support, and engage with customers, clients, or other users. When an incoming call is received, the VoIPBIN system processes the call request and prepares for call handling based on the specified parameters and configurations.

Execution of Call Flow for incoming call

The execution of the call flow for incoming calls involves a simple yet effective sequence of actions:

External Caller                VoIPBIN                    Your Flow
      |                           |                           |
      |  INVITE (call request)    |                           |
      +-------------------------->|                           |
      |                           |  Lookup destination       |
      |                           |  Find matching flow       |
      |                           |                           |
      |  100 Trying               |                           |
      |<--------------------------+                           |
      |                           |  Execute flow actions     |
      |                           +-------------------------->|
      |  180 Ringing / 200 OK     |                           |
      |<--------------------------+<--------------------------+
      |                           |                           |
  • Call Verification: When an incoming call is received, the VoIPBIN system verifies the call’s authenticity and checks for any potential security risks, such as spoofed or fraudulent calls. This verification process ensures that legitimate calls are allowed to proceed.

  • Determine Call Flow: After successful verification, the system determines the appropriate call flow based on the destination of the incoming call. The call flow includes a set of predefined actions and configurations tailored to handle calls directed to a specific user, department, or interactive voice response (IVR) system.

  • Execute Call Flow: Once the call flow is determined, the system proceeds to execute it without delay. The call flow actions are triggered in accordance with the predefined configuration for the call destination.

  • End the Call: After executing the call flow actions, the system initiates the process of ending the call. The call is terminated, and the connection with the external party is disconnected.

By following this streamlined call flow process, the VoIPBIN system efficiently handles incoming calls, ensures their secure and verified handling, and executes the appropriate flow actions based on the call destination. After executing the call flow, the system promptly ends the call, completing the call handling process for the incoming call. Customizable flow actions allow users to tailor the call handling process according to their application’s needs, optimizing user experience and call management efficiency.

_images/call_incoming.png

Outgoing call

The VoIPBIN system offers the outgoing call feature, enabling users to initiate calls to external parties through their VoIP services. This feature is commonly used in various communication applications and call center setups to establish connections with customers, clients, or other users outside the organization. To utilize the outgoing call feature, users need to provide the necessary call parameters, such as the destination phone number, caller ID information, and any additional call settings. These parameters are submitted to the VoIPBIN system, which then processes the request and attempts to establish a connection with the specified destination.

Execution of Call Flow for outgoing call

Once the outgoing call request is initiated, the VoIPBIN system starts the process of connecting to the destination phone number. During this phase, the system waits for the called party to answer the call. The call flow refers to the sequence of actions and events that occur from the moment the call is initiated until it is successfully answered or terminated.

Your Application               VoIPBIN                    Destination
      |                           |                           |
      |  POST /v1/calls           |                           |
      |  (with flow actions)      |                           |
      +-------------------------->|                           |
      |                           |  INVITE                   |
      |                           +-------------------------->|
      |  Call created             |                           |
      |  status: "dialing"        |  180 Ringing              |
      |<--------------------------+<--------------------------+
      |                           |                           |
      |  Webhook: "ringing"       |  200 OK (answered)        |
      |<--------------------------+<--------------------------+
      |                           |                           |
      |  Webhook: "progressing"   |  <=====================>  |
      |<--------------------------+  Execute flow actions     |
      |                           |                           |

The call flow execution occurs as follows:

  • Initiation: The user triggers the outgoing call request, providing the necessary call parameters.

  • Call Setup: The VoIPBIN system processes the request and establishes a connection with the destination phone number.

  • Wait for Call Answer: After the call setup, the system waits for the called party to answer the call. This waiting period involves ringing the called party’s phone and monitoring the call status.

  • Call Answered: Once the called party answers the outgoing call, the system proceeds to execute the predefined call flow actions.

  • Flow Actions Execution: The call flow actions are a set of customizable operations that are executed upon call answer. These actions can include call recording, call routing, call analytics, notifications, and post-call actions, among others.

The call flow execution is critical for ensuring a smooth and efficient communication experience. By customizing the flow actions, users can tailor the call handling process to meet the specific requirements of their application or service, enhancing user engagement and overall call management.

_images/call_outgoing.png

Error handling and Termination

During the incoming/outgoing call process, various errors may occur, such as call failures or network issues. The VoIPBIN system have robust error handling mechanisms to gracefully manage such situations. In case of a failed call attempt or call rejection, the system log relevant information for further analysis or reporting purposes.

Common Error Scenarios

Call concept

The concept of a call in VoIPBIN departs from the traditional 1:1 call model. Here’s an overview:

In VoIPBIN, a call includes source, destination, and additional metadata. Moreover, the call can be associated with multiple other calls, creating a dynamic journey that goes beyond the standard 1:1 connection. Envision a call’s trajectory as it connects to an agent and then diverges to another destination.

In VoIPBIN, the conventional call scenario A -> B is delineated by two distinct calls:

A            VoIPBIN            B
|<-- Call 1 --->|               |
|               |<--- Call 2 -->|
|<-----RTP----->|<-----RTP----->|

Comparison: Traditional Call Concept vs VoIPBIN Call Concept

Traditional Call Concept

  • Follows a 1:1 model where a call is a direct connection between a source and a destination.

  • Typically involves a straightforward flow from the caller to the recipient.

  • Limited in handling complex call journeys or interactions with multiple parties.

VoIPBIN Call Concept

  • Deviates from the traditional 1:1 model, allowing for more intricate call structures.

  • Encompasses source, destination, and additional metadata in a call.

  • Permits connections to multiple other calls, creating dynamic call journeys.

  • Visualizes a call’s path, which may involve connecting to an agent and branching to additional destinations.

In summary, while the traditional call concept adheres to a simple point-to-point model, the VoIPBIN call concept introduces a more flexible and multifaceted approach, accommodating diverse call scenarios and interactions.

Transfer

CPaaS, or Communications Platform as a Service, is a cloud-based technology that allows developers to add real-time communication features to their applications, such as voice and messaging capabilities. Call transfer is a common feature in CPaaS that allows an ongoing phone call to be transferred from one person to another, or from one device to another, without disrupting the conversation.

There are two main types of call transfer in CPaaS: blind transfer and attended transfer.

In both types of call transfer, the transfer can be done manually by the person initiating the transfer, or it can be automated using CPaaS software. Automated transfer is typically done using rules-based routing, which determines the appropriate person or device to transfer the call to based on predefined rules or criteria.

Call transfer is just one of many features available in CPaaS technology, which can help improve call handling, reduce call times, and improve overall customer service.

Note

AI Implementation Hint

Call transfers involve active calls, which are chargeable. A transfer creates a new outbound call to the transfer destination. The call-id used in POST /calls/{call-id}/transfer must be an active call (status progressing). Obtain the call-id from GET /calls or from a webhook event such as call_answered.

Blind Transfer

Blind transfer is the simplest type of call transfer. In this type of transfer, the person initiating the transfer simply transfers the call to another person or phone number without first speaking to them. This is useful when the person receiving the call is known to be available and ready to take the call. Blind transfer is commonly used in call center environments where a caller needs to be routed to the appropriate agent or department.

Caller           VoIPBIN        Transferer        Transferee
|                  |                |                |
|    Call in       | Call in        |                |
|    progress      | progress       |                |
|<---------------->|<-------------->|                |
|                  |                |                |
|                  | Send transfer  |                |
|                  | Request        |                |
|                  |<---------------|                |
|                  |                |                |
|                  | Dial           |                |
|                  |-------------------------------->|
|                  |                |                |
|   Ring           |                |                |
|<-----------------|                |                |
|                  |                |                |
|                  | Hangup         |                |
|                  |--------------->|                |
|                  |                |                |
|                  |                |     Answer     |
|                  |<--------------------------------|
|                  |                |                |
|  Stop ring       |                |                |
|<-----------------|                |                |
  • The Caller initiates a call to the VoIPBIN and the call is in progress.

  • The Transferer, who is already on a call, decides to transfer the Caller to the Transferee.

  • The Transferer sends a transfer request to the VoIPBIN, indicating the Transferee’s number.

  • The VoIPBIN dials to the Transferee.

  • The VoIPBIN hangs up the transferer right after dials to the transferee.

  • The Transferee answers the call and is connected to the Caller.

This is the basic process of an blind transfer using a CPaaS like VoIPBIN.

Note

AI Implementation Hint

In a blind transfer, the transferer is disconnected immediately after the transfer is initiated. If the transferee does not answer, the caller may be left with no connection. For critical calls, use attended transfer instead. The caller will hear ringing while waiting for the transferee to answer.

Attended Transfer

Attended transfer, also known as consultative transfer, involves the person initiating the transfer first speaking to the person who will be taking the call. This allows the person initiating the transfer to provide context or information about the caller or the reason for the transfer. Once the person who will be taking the call is ready, the transfer is initiated and the original caller is connected to the new person or device. Attended transfer is commonly used in situations where the person receiving the call may need more information before taking the call, such as when transferring a call to a supervisor or manager.

Caller           VoIPBIN        Transferer        Transferee
|                  |                |                |
|    Call in       | Call in        |                |
|    progress      | progress       |                |
|<---------------->|<-------------->|                |
|                  |                |                |
|                  | Send transfer  |                |
|                  | Request        |                |
|                  |<---------------|                |
|                  |                |                |
|                  | Dial           |                |
|                  |-------------------------------->|
|                  |                |                |
|   MOH/Mute       |                |                |
|<-----------------|                |                |
|                  |                |                |
|                  |                |    Answer      |
|                  |<--------------------------------|
|                  |                |                |
|                  | Call in        |                |
|                  | progress       |                |
|                  |<-------------->|                |
|                  |                |                |
|                  |                | Call in        |
|                  |                | progress       |
|                  |<------------------------------->|
|                  |                |                |
|                  | Hangup         |                |
|                  |<---------------|                |
|                  |                |                |
|  MOH off/Unmute  |                |                |
|<-----------------|                |                |
|                  |                |                |
|    Call in       |                |                |
|    progress      |                |                |
|<---------------->|                |                |
  • The Caller initiates a call to the VoIPBIN, and the call is in progress with transferer.

  • The Transferer, who is already on a call, decides to transfer the Caller to the Transferee.

  • The Transferer sends a transfer request to the VoIPBIN, indicating the Transferee’s number.

  • The VoIPBIN dials to the Transferee.

  • The VoIPBIN puts the Caller on music on hold and mute.

  • The Transferee answers the call and is connected to the Transferer and talk to each other.

  • The Transferer drops out of the call.

  • The VoIPBIN turn off the Caller’s Music on hold and the Caller and Transferee can now hear each other.

This is the basic process of an attended transfer using a CPaaS like VoIPBIN. It allows for seamless communication between parties and can help businesses manage their incoming calls more efficiently.

Note

AI Implementation Hint

During an attended transfer, the caller is placed on hold with music. The transferer and transferee can speak privately before completing the transfer. The transfer is only completed when the transferer hangs up. If the transferee does not answer or the consultation fails, the transferer can cancel the transfer via POST /transfers/{transfer-id}/cancel and resume the original call with the caller.

Groupcall

The Groupcall feature in VoIPBIN is a blast calling functionality that enables team members to communicate in real-time. When a Group Call is initiated, an alert is sent to all team members, allowing them to join the call with a single click. The feature uses VoIP technology to enable high-quality audio communication and offers benefits such as increased productivity, improved collaboration, and enhanced connectivity.

Note

AI Implementation Hint

Groupcalls create multiple simultaneous outbound calls, each of which is individually chargeable. The number of calls created equals the number of destinations in the groupcall request. Use call_ids in the groupcall response to track the status of each individual call via GET /calls/{call-id}.

Ringall

Ringall sends the dial request to all destinations simultaneously.

The ringall ring method is a way to make calls to multiple destinations simultaneously. When you initiate a groupcall using the ringall method, VoIPBIN will place calls to all of the destinations on your list at once. This means that each destination’s phone will start ringing simultaneously, and the person who answers first will begin executing the call flow specified for that groupcall, while all other destinations that have not yet been answered will be hung up immediately. This ensures that only one call is active at a time and the call flow is executed by the person who answered first.

Client           VoIPBIN        Destination-1    Destination-2
|                  |                |                |
|    Groupcall     |                |                |
|    request       |                |                |
|----------------->|                |                |
|                  |                |                |
|                  | Dial           |                |
|                  |--------------->|                |
|                  |                |                |
|                  | Dial           |                |
|                  |-------------------------------->|
|                  |                |                |
|                  |                |         Answer |
|                  |<--------------------------------|
|                  |                |                |
|                  | Cancel         |                |
|                  |--------------->|                |

The diagram shows the sequence of events for a Group Call request in VoIPBIN with two destination endpoints, Destination-1 and Destination-2. * The Client initiates the Group Call request by sending a request message to the VoIPBIN server. * The server then sends a Dial message to Destination-1 and Destination-2 to establish the call. * After Destination-2 answers the call, it sends an Answer message back to the server. * The VoIPBIN cancels the call to Destination-1 by sending a Cancel message to Destination-1.

Note

AI Implementation Hint

With ring_all, if no destination answers within the dial timeout, all calls will be hung up with hangup_reason: "dialout". Set an appropriate dial_timeout (default: 30000 ms) to allow enough ring time. For PSTN destinations, 45000-60000 ms is recommended.

Linear

The linear ring method is a way to call a list of destinations one by one, in a specific order.

When you initiate a groupcall using the linear method, VoIPBIN will call the first destination on your list. If that destination does not answer, VoIPBIN will move on to the next destination on the list and call it instead. This process will continue until one of the destinations answers the call, at which point the call flow specified for the groupcall will be executed. If all of the destinations on the list have been called and none of them have answered, the call will end without any further action.

The linear method is useful when you want to call a list of destinations in a specific order and don’t want to simultaneously ring all destinations at once.

For example, you might use the linear method for a sales team to call potential clients one by one, in a specific order based on priority.

groupcall1            destinationA       destinationB        destinationC
    |----- ring ---------->|                   |                   |
    |<---- no answer ------|                   |                   |
    |                      |                   |                   |
    |----- ring ------------------------------>|                   |
    |<---- no answer --------------------------|                   |
    |                      |                   |                   |
    |----- ring -------------------------------------------------->|
    |<---- answer -------------------------------------------------|

Note

AI Implementation Hint

With linear ring method, the total time to reach the last destination is the sum of all individual dial timeouts. For example, with 5 destinations and a 30-second timeout each, the last destination will not be tried until up to 150 seconds have elapsed. Plan your destination order and timeouts accordingly.

Nested groupcall

A nested groupcall is a groupcall that is included as one of the destinations in another groupcall. When a groupcall with a nested groupcall is initiated, the nested groupcall is also initiated, creating a “nested” groupcall within the main groupcall.

For example, let’s say you have a groupcall with the following list of destinations: Destination A, Destination B, and Destination C. Destination C is a nested groupcall that includes its own list of destinations: Destination X and Destination Y.

When you initiate the main groupcall, VoIPBIN will begin calling Destination A and Destination B simultaneously according to the ring method you’ve specified (either ringall or linear). When it reaches Destination C, the nested groupcall is initiated and VoIPBIN will begin calling Destination X and Destination Y according to the ring method specified in the nested groupcall.

Once a destination in the nested groupcall has answered the call, the flow specified for that groupcall is executed. The child groupcall informs the master groupcall that it has answered call. The master groupcall then hangs up any remaining calls that have not yet been answered in the child groupcall, and stops calling the remaining destinations in the main groupcall list.

In VoIPBIN, the main groupcall is considered the “master” groupcall and the nested groupcall is considered a “chained” groupcall. Each chained groupcall is assigned a unique ID, and the IDs of all chained groupcalls are stored in a list within the master groupcall. This allows VoIPBIN to keep track of all nested groupcalls and their current status within the main call.

It is also possible to have chained groupcalls within chained groupcalls, creating multiple levels of nesting. This means that a nested groupcall can itself include another groupcall as one of its destinations, forming a chain of groupcalls. The nested groupcalls can continue to be chained in a cascading manner, allowing for complex call flows and routing scenarios.

For example, the main groupcall may include a chained groupcall as one of its destinations, and that chained groupcall may, in turn, include another chained groupcall within it. This nesting can extend to multiple levels, providing a highly flexible and customizable approach to call routing and management.

By allowing nested and chained groupcalls, VoIPBIN empowers users to design and implement intricate call flows that cater to their specific needs. This functionality opens up possibilities for applications such as multi-level call routing, call forwarding to different departments or teams, and advanced call handling scenarios.

The ability to include nested groupcalls within a main groupcall is a powerful feature that allows for more complex call flows and routing strategies. It can be used, for example, to create more sophisticated call routing trees that can handle a wide range of call scenarios and use cases.

groupcall1            destinationA        destinationB        destinationC
    |----- ring ---------->|                   |       (groupcall destination linear)
    |----- ring ------------------------------>|                   |                         groupcall2        destinationX        destinationY
    |----- ring -------------------------------------------------->|-- start a nested groupcall-->|                 |                   |
    |                      |                   |                                                  |----- ring ----->|                   |
    |                      |                   |                                                  |<-- no answer ---|                   |
    |                      |                   |                                                  |----- ring ------------------------->|
    |                      |                   |                                                  |<-- answer --------------------------|
    |<---------------------------------------- inform that groupcall2 got answered call ----------|
    |----- cancel -------->|                   |
    |----- cancel ---------------------------->|

Note

AI Implementation Hint

Nested groupcalls multiply the number of outbound calls created. A master groupcall with 3 destinations, where one destination is a nested groupcall with 3 more destinations, can create up to 5 simultaneous calls (with ring_all). Each call is individually chargeable. When the nested groupcall answers, the master cancels all remaining unanswered calls across all levels.

Struct Call

Call

{
    "id": "<string>",
    "flow_id": "<string>",
    "type": "<string>",
    "master_call_id": "<string>",
    "chained_call_ids": [
        "<string>",
        ...
    ],
    "recording_id": "<string>",
    "recording_ids": [
        "<string>",
        ...
    ],
    "source": {
        ...
    },
    "destination": {
        ...
    },
    "status": "<string>",
    "action": {
        ...
    },
    "direction": "<string>",
    "hangup_by": "<string>",
    "hangup_reason": "<string>",
    "tm_create": "<string>",
    "tm_update": "<string>",
    "tm_progressing": "<string>",
    "tm_ringing": "<string>",
    "tm_hangup": "<string>"
}
  • id (UUID): The call’s unique identifier. Returned when creating a call via POST /calls or when listing calls via GET /calls.

  • flow_id (UUID): The flow associated with this call. Obtained from the id field of GET /flows. Set to 00000000-0000-0000-0000-000000000000 if no flow is assigned.

  • type (enum string): The call’s type. See Type.

  • master_call_id (UUID): The master call’s ID in a call chain. Obtained from another call’s id field. If set, this call follows the master call’s hangup. Set to 00000000-0000-0000-0000-000000000000 if this call has no master.

  • chained_call_ids (Array of UUID): List of chained call IDs linked to this call. Each ID is a call id from GET /calls. When this call hangs up, all chained calls also hang up.

  • recording_id (UUID): The currently active recording’s ID. Obtained from GET /recordings. Set to 00000000-0000-0000-0000-000000000000 if no recording is active.

  • recording_ids (Array of UUID): List of all recording IDs created during this call’s lifetime. Each ID can be used with GET /recordings/{id} to retrieve the recording.

  • source (Object): Source address info. See Address.

  • destination (Object): Destination address info. See Address.

  • status (enum string): The call’s current status. See Status.

  • action (Object): The call’s currently executing flow action. See Action.

  • direction (enum string): The call’s direction. See Direction.

  • hangup_by (enum string): Which endpoint initiated the hangup. See Hangup by.

  • hangup_reason (enum string): The reason the call ended. See Hangup reason.

  • tm_create (string, ISO 8601): Timestamp when the call was created.

  • tm_update (string, ISO 8601): Timestamp of the last update to any call property.

  • tm_progressing (string, ISO 8601): Timestamp when the call was answered.

  • tm_ringing (string, ISO 8601): Timestamp when the destination started ringing.

  • tm_hangup (string, ISO 8601): Timestamp when the call ended.

Note

AI Implementation Hint

Timestamps set to 9999-01-01 00:00:00.000000 indicate the event has not yet occurred. For example, tm_hangup with this value means the call is still in progress.

Example

{
    "id": "d9d32881-12fd-4b19-a6b2-6d5b6b6acf76",
    "flow_id": "4553c074-c88d-49e5-9d47-5c01598ac099",
    "type": "flow",
    "master_call_id": "00000000-0000-0000-0000-000000000000",
    "chained_call_ids": [],
    "recording_id": "00000000-0000-0000-0000-000000000000",
    "recording_ids": [],
    "source": {
        "type": "tel",
        "target": "+15551234567",
        "target_name": "",
        "name": "",
        "detail": ""
    },
    "destination": {
        "type": "tel",
        "target": "+15559876543",
        "target_name": "",
        "name": "",
        "detail": ""
    },
    "status": "hangup",
    "action": {
        "id": "0db08d32-b7d7-470d-8bda-9feff0877077",
        "next_id": "00000000-0000-0000-0000-000000000000",
        "type": "talk",
        "option": {
            "text": "Hello. Thank you for calling. How can I help you today?",
            "language": "en-US"
        },
        "tm_execute": "2022-05-01 15:10:38.785510878"
    },
    "direction": "outgoing",
    "hangup_by": "local",
    "hangup_reason": "normal",
    "tm_create": "2022-05-01 15:10:23.414798",
    "tm_update": "2022-05-01 15:10:44.781000",
    "tm_progressing": "2022-05-01 15:10:38.721000",
    "tm_ringing": "2022-05-01 15:10:26.978000",
    "tm_hangup": "2022-05-01 15:10:44.781000"
}

Type

Call’s type (enum string).

Type

Description

flow

Executing a call flow. The call runs the actions defined in the associated flow.

conference

Conference call. The call is part of a multi-party conference.

sip-service

SIP service call. Executes the pre-defined SIP service corresponding to the destination.

Status

Call’s current status (enum string). States only move forward, never backward.

Status

Description

dialing

The call is created. The system is dialing the destination through the phone network.

ringing

The destination has confirmed the call is ringing. The callee can now answer.

progressing

The call has been answered. Both endpoints can hear each other and media is flowing.

terminating

The system is ending the call. This occurs when the application hangs up or a flow action ends the call.

canceling

The call originator is canceling the call before the destination answered. Only applies to outgoing calls.

hangup

The call has ended. This is the final state — no further changes are possible.

state diagram

_images/call_struct_status.png

Direction

Call’s direction (enum string).

Direction

Description

incoming

The call originated from outside VoIPBIN (e.g., a PSTN caller dialing a VoIPBIN number).

outgoing

The call was initiated by VoIPBIN (e.g., via POST /calls).

Hangup by

Which endpoint sent the hangup request first (enum string).

hangup by

Description

remote

The remote end (the other party) hung up the call first.

local

The local end (your application or flow action) hung up the call first.

Hangup reason

The reason the call ended (enum string).

Reason

Description

normal

The call ended normally after being answered. Someone hung up.

failed

The call attempt did not reach the phone network. Network or routing failure.

busy

The destination is on another call.

cancel

The call was cancelled by the originator before the destination answered.

timeout

The call exceeded the maximum allowed duration after being answered.

noanswer

The destination did not answer before the destination’s ring timeout expired.

dialout

The call exceeded VoIPBIN’s dialing timeout before being answered. This is VoIPBIN’s own timeout for outgoing calls.

amd

The Answering Machine Detection (AMD) action detected a voicemail and hung up the call according to your AMD settings.

Struct Groupcall

Groupcall

{
    "id": "<string>",
    "customer_id": "<string>",
    "source": {
        ...
    },
    "destinations": [
        {
            ...
        },
        ...
    ],
    "ring_method": "<string>",
    "answer_method": "<string>",
    "answer_call_id": "<string>",
    "call_ids": [
       "<string>",
       ...
    ],
    "tm_create": "<string>",
    "tm_update": "<string>",
    "tm_delete": "<string>"
}
  • id (UUID): The groupcall’s unique identifier. Returned when creating a groupcall or when listing groupcalls via GET /groupcalls.

  • customer_id (UUID): The customer who owns this groupcall. Obtained from the id field of GET /customers.

  • source (Object): Source address info. See Address.

  • destinations (Array of Object): List of destination addresses to ring. Each entry follows the Address structure. A destination can also be another groupcall for nested groupcalls.

  • ring_method (enum string): How destinations are rung. See Ring method.

  • answer_method (enum string): What happens when a destination answers. See Answer method.

  • answer_call_id (UUID): The call ID of the destination that answered. Set to 00000000-0000-0000-0000-000000000000 until a destination answers. Obtained from GET /calls.

  • call_ids (Array of UUID): List of call IDs created for each destination. Each ID can be used with GET /calls/{id} to check individual call status.

  • tm_create (string, ISO 8601): Timestamp when the groupcall was created.

  • tm_update (string, ISO 8601): Timestamp of the last update to any groupcall property.

  • tm_delete (string, ISO 8601): Timestamp when the groupcall was deleted.

Note

AI Implementation Hint

Timestamps set to 9999-01-01 00:00:00.000000 indicate the event has not yet occurred. For example, tm_delete with this value means the groupcall has not been deleted.

Note

AI Implementation Hint

Groupcalls involve active calls to real destinations, which are chargeable. Each destination in the destinations array results in an individual call being created. With ring_all, all calls are placed simultaneously. Monitor call_ids to track the status of each individual call.

Example

{
    "id": "d8596b14-4d8e-4a86-afde-642b46d59ac7",
    "customer_id": "5e4a0680-804e-11ec-8477-2fea5968d85b",
    "source": {
        "type": "tel",
        "target": "+15551234567",
        "target_name": "",
        "name": "",
        "detail": ""
    },
    "destinations": [
        {
            "type": "endpoint",
            "target": "test11@test",
            "target_name": "",
            "name": "",
            "detail": ""
        },
        {
            "type": "endpoint",
            "target": "test12@test",
            "target_name": "",
            "name": "",
            "detail": ""
        }
    ],
    "ring_method": "",
    "answer_method": "",
    "answer_call_id": "00000000-0000-0000-0000-000000000000",
    "call_ids": [
        "3c77eb43-2098-4890-bb6c-5af0707ba4a6"
    ],
    "tm_create": "2023-04-21 15:33:28.569053",
    "tm_update": "9999-01-01 00:00:00.000000",
    "tm_delete": "9999-01-01 00:00:00.000000"
}

Ring method

Groupcall’s ringing method (enum string).

Type

Description

ring_all

Make a call to all destinations at once. The first destination to answer wins; all other calls are cancelled.

linear

Make a call to each destination one-by-one in order. If a destination does not answer, the next one is tried.

Answer method

What happens when a destination answers (enum string).

Type

Description

hangup_others

Hang up all other unanswered calls when one destination answers.

Tutorial

Before creating a call, you need:

  • An authentication token. Obtain one via POST /auth/login or use an access key from GET /accesskeys.

  • A source phone number in E.164 format (e.g., +15551234567). This must be a number you own. Obtain your numbers via GET /numbers.

  • A destination phone number in E.164 format (e.g., +15559876543) or a SIP endpoint address.

  • (Optional) A flow ID (UUID). Create one via POST /flows or obtain from GET /flows.

Note

AI Implementation Hint

All phone numbers must be in E.164 format: start with +, followed by country code and number, no dashes or spaces. For example, +15551234567 (US) or +821012345678 (Korea). If the user provides a local format like 010-1234-5678, normalize it to +821012345678 before calling the API.

Simple outbound call with TTS

Making an outbound call with TTS (Text-to-Speech) action. When the destination answers the call, it will speak the given text message.

$ curl --location --request POST 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "source": {
            "type": "tel",
            "target": "+15551234567"
        },
        "destinations": [
            {
                "type": "tel",
                "target": "+15559876543"
            }
        ],
        "actions": [
            {
                "type": "talk",
                "option": {
                    "text": "hello. welcome to voipbin. This is test message. This audio file is generated dynamically by the tts module. Please enjoy the voipbin service. Thank you. Bye",
                    "language": "en-US"
                }
            }
        ]
    }'

Simple outbound call with an existing flow

If you have already created a flow, you can reference it by flow_id instead of defining actions inline:

$ curl --request POST 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "source": {
            "type": "tel",
            "target": "<your-source-number>"
        },
        "destinations": [
            {
                "type": "tel",
                "target": "<your-destination-number>"
            }
        ],
        "flow_id": "<your-flow-id>"
    }'

Note

AI Implementation Hint

The flow_id (UUID) must reference an existing flow. Obtain one from the id field of GET /flows or create one via POST /flows. If the flow does not exist, the API returns 404 Not Found.

For more details on flows, see the Flow tutorial.

Simple outbound call with media file play

Making an outbound call with media file play action. When the destination answer the call, it will play the given media file.

$ curl --location --request POST 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "source": {
        "type": "tel",
        "target": "+15551234567"
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+15559876543"
        }
    ],
    "actions": [
        {
            "type": "play",
            "option": {
                "stream_urls": [
                    "https://github.com/pchero/asterisk-medias/raw/master/samples_codec/pcm_samples/example-mono_16bit_8khz_pcm.wav"
                ]
            }
        }
    ]
}'

[
    {
        "id": "a023bfa8-1091-4e94-8eaa-7f01fbecc71a",   // Save this as call_id (UUID)
        "user_id": 1,
        "flow_id": "f089791a-ac78-4ea0-be88-8a8e131f9fc5",   // Auto-generated flow (UUID)
        "conf_id": "00000000-0000-0000-0000-000000000000",
        "type": "flow",   // enum: flow, conference, sip-service
        "master_call_id": "00000000-0000-0000-0000-000000000000",
        "chained_call_ids": [],
        "recording_id": "00000000-0000-0000-0000-000000000000",
        "recording_ids": [],
        "source": {
            "type": "tel",
            "target": "+15551234567",
            "name": ""
        },
        "destination": {
            "type": "tel",
            "target": "+15559876543",
            "name": ""
        },
        "status": "dialing",   // enum: dialing, ringing, progressing, terminating, canceling, hangup
        "direction": "outgoing",   // enum: incoming, outgoing
        "hangup_by": "",
        "hangup_reason": "",
        "tm_create": "2021-02-04 04:44:20.904662",   // ISO 8601 timestamp
        "tm_update": "",
        "tm_progressing": "",
        "tm_ringing": "",
        "tm_hangup": ""
    }
]

Simple outbound call with TTS and connect

Making an outbound call with TTS(Text-to-Speech) and connect to other destination.

$ curl -k --location --request POST 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'Cookie: token=<YOUR_AUTH_TOKEN>' \
--data-raw '{
    "source": {
        "type": "tel",
        "target": "+15559876543"
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+15559876543"
        }
    ],
    "actions": [
        {
            "type": "talk",
            "option": {
                "text": "hello. welcome to voipbin. This is test message. This audio file is generated dynamically by the tts module. Please enjoy the voipbin service.",
                "language": "en-US"
            }
        },
        {
            "type": "connect",
            "option": {
                "source": {
                    "type": "tel",
                    "target": "+15559876543"
                },
                "destinations": [
                    {
                        "type": "tel",
                        "target": "+15551111111"
                    }
                ]
            }
        }
    ]
}'

[
    {
        "id": "9f6265bc-6b59-4e80-a906-2679aca11455",
        "user_id": 1,
        "flow_id": "d665fbc0-6dd8-44bc-99ea-2ae54bc59428",
        "conf_id": "00000000-0000-0000-0000-000000000000",
        "type": "flow",
        "master_call_id": "00000000-0000-0000-0000-000000000000",
        "chained_call_ids": [],
        "recording_id": "00000000-0000-0000-0000-000000000000",
        "recording_ids": [],
        "source": {
            "type": "tel",
            "target": "+15559876543",
            "name": ""
        },
        "destination": {
            "type": "tel",
            "target": "+15559876543",
            "name": ""
        },
        "status": "dialing",
        "direction": "outgoing",
        "hangup_by": "",
        "hangup_reason": "",
        "tm_create": "2021-02-06 09:52:49.941865",
        "tm_update": "",
        "tm_progressing": "",
        "tm_ringing": "",
        "tm_hangup": ""
    }
]

Simple outbound call with talk and digits_send

Making an outbound call. After answer the call, it will play the TTS and then send the DTMFs.

{
    "source": {
        "type": "tel",
        "target": "+15551234567"
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+15559876543"
        }
    ],
    "actions": [
        {
            "type": "talk",
            "option": {
                "text": "This is dtmf send test call. Please wait.",
                "language": "en-US"
            }
        },
        {
            "type": "dtmf_send",
            "option": {
                "dtmfs": "1234567890",
                "duration": 500,
                "interval": 500
            }
        },
        {
            "type": "talk",
            "option": {
                "text": "Thank you. DTMF send test has done.",
                "language": "en-US"
            }
        }
    ]
}

[
    {
        "id": "d7520a58-0b07-4dd7-ab72-a4e2d1979ec0",
        "user_id": 1,
        "flow_id": "0f4bd9bc-9df5-4a5b-9465-2189822a3019",
        "conf_id": "00000000-0000-0000-0000-000000000000",
        "type": "flow",
        "master_call_id": "00000000-0000-0000-0000-000000000000",
        "chained_call_ids": [],
        "recording_id": "00000000-0000-0000-0000-000000000000",
        "recording_ids": [],
        "source": {
            "type": "tel",
            "target": "+15551234567",
            "name": ""
        },
        "destination": {
            "type": "tel",
            "target": "+15559876543",
            "name": ""
        },
        "status": "dialing",
        "direction": "outgoing",
        "hangup_by": "",
        "hangup_reason": "",
        "tm_create": "2021-02-08 03:59:33.281711",
        "tm_update": "",
        "tm_progressing": "",
        "tm_ringing": "",
        "tm_hangup": ""
    }
]

Simple outbound call with Branch

Making an outbound call with branch. It will get the digits from the call and will execute the branch.

              Start
                |
                |
------------>  Talk("Press 1 for show must go on. Press 2 for bohemian rhapsody. Press 3 for another one bites the dust")
|               |
|               |
|              Digit(DTMF) receive
|               |
|               |
|       -----------------------------------------------
|       |           |                |                |
|     default      "1"              "2"              "3"
|       |           |                |                |
|       |           |                |                |
|       |          Talk(...)        Talk(...)        Talk(...)
|       |           |                |                |
|       |           |                |                |
|       |          Hangup          Hangup           Hangup
|       |
|       |
|      Talk(...)
|       |
----goto(loop 2 times)
        |
        |
       Talk(...)
        |
        |
       Hangup
$ curl --location --request POST 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'Cookie: token=<YOUR_AUTH_TOKEN>' \
--data-raw '{
    "source": {
        "type": "tel",
        "target": "+15551234567"
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+15559876543"
        }
    ],
    "actions": [
        {
            "id": "b8781e56-c524-11ec-889f-d37b0dbb7eb8",
            "type": "talk",
            "option": {
                "text": "Hello. This is branch test. Press 1 for show must go on. Press 2 for bohemian rhapsody. Press 3 for another one bites the dust",
                "language": "en-US"
            }
        },
        {
            "type": "digits_receive",
            "option": {
                "duration": 5000,
                "length": 1
            }
        },
        {
            "type": "branch",
            "option": {
                "default_target_id": "ed9705ca-c524-11ec-a3fb-8feb7731ad45",
                "target_ids": {
                    "1": "c3eb8e62-c524-11ec-94c5-abafec8af561",
                    "2": "dc87123e-c524-11ec-89c6-5fb18da14034",
                    "3": "e70fb030-c524-11ec-b657-ebec72f097ef"
                }
            }
        },
        {
            "id": "c3eb8e62-c524-11ec-94c5-abafec8af561",
            "type": "talk",
            "option": {
                "text": "Empty spaces, what are we living for? Abandoned places, I guess we know the score, on and on. Does anybody know what we are looking for? Another hero, another mindless crime. Behind the curtain, in the pantomime",
                "language": "en-US"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "dc87123e-c524-11ec-89c6-5fb18da14034",
            "type": "talk",
            "option": {
                "text": "Mama, Just killed a man. Put a gun against his head, pulled my trigger. Now he'\''s dead. Mama, life had just begun, But now I'\''ve gone and thrown it all away.",
                "language": "en-US"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "e70fb030-c524-11ec-b657-ebec72f097ef",
            "type": "talk",
            "option": {
                "text": "Steve walks warily down the street. With his brim pulled way down low. Ain'\''t no sound but the sound of his feet. Machine guns ready to go. Are you ready hey are you ready for this?",
                "language": "en-US"
            }
        },
        {
            "type": "hangup"
        },
        {
            "id": "ed9705ca-c524-11ec-a3fb-8feb7731ad45",
            "type": "talk",
            "option": {
                "text": "You didn'\''t choose the correct number. Default selected.",
                "language": "en-US"
            }
        },
        {
            "type": "goto",
            "option": {
                "target_id": "b8781e56-c524-11ec-889f-d37b0dbb7eb8",
                "loop_count": 2
            }
        },
        {
            "type": "talk",
            "option": {
                "text": "Loop over. Hangup the call. Thank you, good bye.",
                "language": "en-US"
            }
        },
        {
            "type": "hangup"
        }
    ]
}'

[
    {
        "id": "77517719-ffb9-4583-ba44-737ba991d685",
        "flow_id": "c0827e56-41ef-4fa1-9da0-a8a36fbb76c4",
        "confbridge_id": "00000000-0000-0000-0000-000000000000",
        "type": "flow",
        "master_call_id": "00000000-0000-0000-0000-000000000000",
        "chained_call_ids": [],
        "recording_id": "00000000-0000-0000-0000-000000000000",
        "recording_ids": [],
        "source": {
            "type": "tel",
            "target": "+15551234567",
            "target_name": "",
            "name": "",
            "detail": ""
        },
        "destination": {
            "type": "tel",
            "target": "+15559876543",
            "target_name": "",
            "name": "",
            "detail": ""
        },
        "status": "dialing",
        "action": {
            "id": "00000000-0000-0000-0000-000000000001",
            "type": ""
        },
        "direction": "outgoing",
        "hangup_by": "",
        "hangup_reason": "",
        "tm_create": "2022-02-24 02:08:14.469405",
        "tm_update": "9999-01-01 00:00:00.000000",
        "tm_progressing": "9999-01-01 00:00:00.000000",
        "tm_ringing": "9999-01-01 00:00:00.000000",
        "tm_hangup": "9999-01-01 00:00:00.000000"
    }
]

Get call list

Getting a list of calls.

$ curl -k --location --request GET 'https://api.voipbin.net/v1.0/calls?token=<YOUR_AUTH_TOKEN>'

{
    "result": [
        {
            "id": "9a7857ca-73ba-4000-8101-c47d3b48f9d1",
            "user_id": 1,
            "flow_id": "00000000-0000-0000-0000-000000000000",
            "conf_id": "00000000-0000-0000-0000-000000000000",
            "type": "sip-service",
            "master_call_id": "00000000-0000-0000-0000-000000000000",
            "chained_call_ids": [],
            "recording_id": "00000000-0000-0000-0000-000000000000",
            "recording_ids": [],
            "source": {
                "type": "tel",
                "target": "109",
                "name": "109"
            },
            "destination": {
                "type": "tel",
                "target": "972595897084",
                "name": ""
            },
            "status": "hangup",
            "direction": "incoming",
            "hangup_by": "remote",
            "hangup_reason": "normal",
            "tm_create": "2021-02-06 09:47:10.018000",
            "tm_update": "2021-02-06 09:48:14.630000",
            "tm_progressing": "2021-02-06 09:47:10.626000",
            "tm_ringing": "",
            "tm_hangup": "2021-02-06 09:48:14.630000"
        },
        ...
    ],
    "next_page_token": "2021-02-06 08:54:38.361000"
}

Get specific call

Getting a given call uuid’s call info.

$ curl -k --location --request GET 'https://api.voipbin.net/v1.0/calls/f457951b-9918-44af-a834-2216b1cc31bc?token=<YOUR_AUTH_TOKEN>'

{
    "id": "f457951b-9918-44af-a834-2216b1cc31bc",
    "user_id": 1,
    "flow_id": "246aeabe-fab5-4a1b-8e98-852b50e89dd7",
    "conf_id": "00000000-0000-0000-0000-000000000000",
    "type": "flow",
    "master_call_id": "00000000-0000-0000-0000-000000000000",
    "chained_call_ids": [],
    "recording_id": "00000000-0000-0000-0000-000000000000",
    "recording_ids": [
        "142e8ef8-392c-4514-abf0-8656da5d2fdf"
    ],
    "source": {
        "type": "tel",
        "target": "+15551234567",
        "name": ""
    },
    "destination": {
        "type": "tel",
        "target": "+15559876543",
        "name": ""
    },
    "status": "hangup",
    "direction": "outgoing",
    "hangup_by": "remote",
    "hangup_reason": "normal",
    "tm_create": "2021-01-29 03:17:54.349101",
    "tm_update": "2021-01-29 03:18:22.131000",
    "tm_progressing": "2021-01-29 03:18:07.810000",
    "tm_ringing": "2021-01-29 03:17:55.392000",
    "tm_hangup": "2021-01-29 03:18:22.131000"
}

Make a groupcall

Make a groupcall to the multiple destinations.

$ curl --location --request POST 'https://api.voipbin.net/v1.0/groupcalls?token=eyJhbGcslkj' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "source": {
            "type": "tel",
            "target": "+15552222222"
        },
        "destinations": [
            {
                "type": "endpoint",
                "target": "test11@test"
            },
            {
                "type": "endpoint",
                "target": "test12@test"
            }
        ],
        "actions": [
            {
                "type": "talk",
                "option": {
                    "text": "hello. welcome to voipbin. This is test message. This audio file is generated dynamically by the tts module. Please enjoy the voipbin service. Thank you. Bye",
                    "language": "en-US"
                }
            }
        ]
    }'

{
    "id": "d8596b14-4d8e-4a86-afde-642b46d59ac7",
    "customer_id": "5e4a0680-804e-11ec-8477-2fea5968d85b",
    "source": {
        "type": "tel",
        "target": "+15551234567",
        "target_name": "",
        "name": "",
        "detail": ""
    },
    "destinations": [
        {
            "type": "endpoint",
            "target": "test11@test",
            "target_name": "",
            "name": "",
            "detail": ""
        },
        {
            "type": "endpoint",
            "target": "test12@test",
            "target_name": "",
            "name": "",
            "detail": ""
        }
    ],
    "ring_method": "",
    "answer_method": "",
    "answer_call_id": "00000000-0000-0000-0000-000000000000",
    "call_ids": [
        "3c77eb43-2098-4890-bb6c-5af0707ba4a6",
        "2bcaff64-e05d-11ed-84a6-133172844032"
    ],
    "tm_create": "2023-04-21 15:33:28.569053",
    "tm_update": "9999-01-01 00:00:00.000000",
    "tm_delete": "9999-01-01 00:00:00.000000"
}

Troubleshooting

  • 400 Bad Request:
    • Cause: The source.target or destinations[].target phone number is not in E.164 format (contains dashes, spaces, or missing +).

    • Fix: Normalize all phone numbers to E.164 format: + followed by country code and number, no spaces or dashes (e.g., +15551234567).

  • 400 Bad Request (source number):
    • Cause: The source.target phone number is not owned by your VoIPBIN account.

    • Fix: Use a number from GET /numbers. Only numbers you own can be used as the source.

  • 402 Payment Required:
    • Cause: Insufficient account balance to make a call.

    • Fix: Check balance via GET /billing-accounts. Top up before retrying.

  • 404 Not Found (flow_id):
    • Cause: The flow_id does not exist or belongs to a different customer.

    • Fix: Verify the flow ID was obtained from GET /flows or POST /flows.

  • Call immediately hangs up:
    • Cause: No answer action at the beginning of the flow, or the destination is unreachable.

    • Fix: Ensure your actions list starts with {"type": "answer"} for outbound calls. Check the call’s hangup_reason field via GET /calls/{id} for details.

Internal Call Sequences

This section reveals how calls flow through VoIPBIN’s internal components. Understanding these sequences helps developers debug issues and optimize their integrations.

Note

AI Implementation Hint

These internal sequences are provided for debugging and understanding purposes. As an API consumer, you interact only with api-manager (via REST API) and receive events via webhooks or WebSocket. You do not need to interact with internal components (Kamailio, Asterisk, RabbitMQ) directly.

Inbound PSTN Call Flow

When someone calls your VoIPBIN number from a regular phone:

Inbound PSTN Call - Complete Internal Flow:

PSTN Carrier     Kamailio        Asterisk      asterisk-proxy    call-manager     flow-manager
     |              |               |               |                |                |
     | SIP INVITE   |               |               |                |                |
     +------------->|               |               |                |                |
     |              |               |               |                |                |
     |              | Route lookup  |               |                |                |
     |              | (destination  |               |                |                |
     |              |  number)      |               |                |                |
     |              |               |               |                |                |
     |              | SIP INVITE    |               |                |                |
     |              +-------------->|               |                |                |
     |              |               |               |                |                |
     |              |               | StasisStart   |                |                |
     |              |               | (ARI event)   |                |                |
     |              |               +-------------->|                |                |
     |              |               |               |                |                |
     |              |               |               | RabbitMQ:      |                |
     |              |               |               | asterisk.all.event              |
     |              |               |               +--------------->|                |
     |              |               |               |                |                |
     |              |               |               |                | Create Call    |
     |              |               |               |                | Record (MySQL) |
     |              |               |               |                |                |
     |              |               |               |                | Lookup Number  |
     |              |               |               |                | -> Flow ID     |
     |              |               |               |                |                |
     |              |               |               |                | RPC: Start     |
     |              |               |               |                | ActiveFlow     |
     |              |               |               |                +--------------->|
     |              |               |               |                |                |
     |              |               |               |                |                | Create
     |              |               |               |                |                | ActiveFlow
     |              |               |               |                |                |
     |              |               |               |                |                | Execute
     |              |               |               |                |                | Action 1
     |              |               |               |                |                |
     |              |               |               |  RPC: Answer   |                |
     |              |               |<--------------------------------------+---------+
     |              |               |               |                |                |
     |              | 200 OK        |               |                |                |
     |<-------------+<--------------+               |                |                |
     |              |               |               |                |                |
     | ACK          |               |               |                |                |
     +------------->+-------------->|               |                |                |
     |              |               |               |                |                |
     |   RTP Media  |   RTP Media   |               |                |                |
     |<============>|<=============>|               |                |                |
     |              |               |               |                |                |

Key Internal Components:

Component Responsibilities:

Kamailio (SIP Proxy):
+------------------------------------------+
| o Receives SIP from carriers             |
| o Authenticates SIP trunks               |
| o Routes to appropriate Asterisk         |
| o Load balances across Asterisk farm     |
| o Handles NAT traversal                  |
+------------------------------------------+

Asterisk (Media Server):
+------------------------------------------+
| o Manages call channels                  |
| o Handles media (RTP)                    |
| o Executes Stasis application            |
| o Provides ARI (Asterisk REST Interface) |
| o Bridges channels for conferencing      |
+------------------------------------------+

asterisk-proxy:
+------------------------------------------+
| o Connects to Asterisk ARI WebSocket     |
| o Translates ARI events to RabbitMQ      |
| o Publishes to asterisk.all.event queue  |
| o One proxy per Asterisk instance        |
+------------------------------------------+

call-manager:
+------------------------------------------+
| o Processes ARI events                   |
| o Creates/updates call records           |
| o Manages call lifecycle                 |
| o Triggers flow execution                |
| o Publishes call events                  |
+------------------------------------------+

flow-manager:
+------------------------------------------+
| o Executes flow actions sequentially     |
| o Sends ARI commands via call-manager    |
| o Manages activeflow state               |
| o Handles branching and loops            |
+------------------------------------------+

Note

AI Implementation Hint

For inbound calls, the flow that executes is determined by the phone number configuration. The destination number is looked up to find the associated flow_id. Configure your number’s flow assignment via PUT /numbers/{number-id} with the flow_id field. Verify your number configuration with GET /numbers/{number-id}.

Outbound API Call Flow

When you create a call via the API:

Outbound API Call - Complete Flow:

Your App      api-manager     call-manager    flow-manager     Asterisk       Destination
    |              |               |               |               |               |
    | POST /calls  |               |               |               |               |
    +------------->|               |               |               |               |
    |              |               |               |               |               |
    |              | Validate JWT  |               |               |               |
    |              |               |               |               |               |
    |              | RPC: Create   |               |               |               |
    |              | Call          |               |               |               |
    |              +-------------->|               |               |               |
    |              |               |               |               |               |
    |              |               | Create Call   |               |               |
    |              |               | Record        |               |               |
    |              |               |               |               |               |
    |              |               | Create temp   |               |               |
    |              |               | Flow (if      |               |               |
    |              |               | actions given)|               |               |
    |              |               |               |               |               |
    |              |               | RPC: Start    |               |               |
    |              |               | ActiveFlow    |               |               |
    |              |               +-------------->|               |               |
    |              |               |               |               |               |
    |              |               |               | Create        |               |
    |              |               |               | ActiveFlow    |               |
    |              |               |               |               |               |
    |              |               |               | RPC: Originate|               |
    |              |               |<--------------+               |               |
    |              |               |               |               |               |
    |              |               | ARI: Originate|               |               |
    |              |               +------------------------------>|               |
    |              |               |               |               |               |
    |              |               |               |               | SIP INVITE    |
    |              |               |               |               +-------------->|
    |              |               |               |               |               |
    |<-------------+<--------------+               |               |               |
    | Call object  |               |               |               |               |
    | status:dialing               |               |               |               |
    |              |               |               |               |               |
    |              |               |               |               | 180 Ringing   |
    |              |               |               |               |<--------------+
    |              |               |               |               |               |
    |              |               | ChannelState  |               |               |
    |              |               | (ringing)     |               |               |
    |              |               |<------------------------------+               |
    |              |               |               |               |               |
    | Webhook:     |               |               |               |               |
    | call_ringing |               |               |               |               |
    |<-------------+<--------------+               |               |               |
    |              |               |               |               |               |
    |              |               |               |               | 200 OK        |
    |              |               |               |               |<--------------+
    |              |               |               |               |               |
    |              |               | StasisStart   |               |               |
    |              |               | (answered)    |               |               |
    |              |               |<------------------------------+               |
    |              |               |               |               |               |
    |              |               | Update status |               |               |
    |              |               | = progressing |               |               |
    |              |               |               |               |               |
    |              |               | Event:        |               |               |
    |              |               | call_answered |               |               |
    |              |               +-------------->|               |               |
    |              |               |               |               |               |
    |              |               |               | Execute       |               |
    |              |               |               | Actions       |               |
    | Webhook:     |               |               |               |               |
    | call_answered|               |               |               |               |
    |<-------------+<--------------+               |               |               |
    |              |               |               |               |               |

Note

AI Implementation Hint

The POST /calls response returns immediately with status dialing. The call has not connected yet at this point. To know when the call is answered, either poll GET /calls/{call-id} for status progressing, or subscribe to the call_answered webhook event. If you provide actions in the POST /calls request, a temporary flow is created automatically – you do not need to create a flow separately via POST /flows.

WebRTC Call Flow

WebRTC calls (browser-to-phone or browser-to-browser):

WebRTC Inbound Call Flow:

Browser        api-manager    talk-manager     Asterisk        Destination
    |              |               |               |               |
    | WSS Connect  |               |               |               |
    +------------->|               |               |               |
    |              |               |               |               |
    | SDP Offer    |               |               |               |
    +------------->|               |               |               |
    |              |               |               |               |
    |              | RPC: Create   |               |               |
    |              | WebRTC Call   |               |               |
    |              +-------------->|               |               |
    |              |               |               |               |
    |              |               | ARI: Create   |               |
    |              |               | WebRTC Channel|               |
    |              |               +-------------->|               |
    |              |               |               |               |
    |              |               |<--------------+               |
    |              |               | SDP Answer    |               |
    |              |               |               |               |
    |<-------------+<--------------+               |               |
    | SDP Answer   |               |               |               |
    |              |               |               |               |
    | ICE Candidates               |               |               |
    |<------------>|<------------->|<------------>|               |
    |              |               |               |               |
    | DTLS-SRTP    |               |               |               |
    | Handshake    |               |               |               |
    |<============>|<=============>|<=============>|               |
    |              |               |               |               |
    |              |               |               | Bridge to     |
    |              |               |               | Destination   |
    |              |               |               +-------------->|
    |              |               |               |               |
    |     Secure Media (SRTP)      |               |               |
    |<============>|<=============>|<=============>|<=============>|
    |              |               |               |               |

WebRTC vs PSTN Differences:

Protocol Comparison:

+------------------+------------------+------------------+
| Aspect           | PSTN Call        | WebRTC Call      |
+------------------+------------------+------------------+
| Signaling        | SIP over UDP/TCP | WebSocket + SDP  |
| Media            | RTP              | SRTP (encrypted) |
| NAT Traversal    | Kamailio handles | ICE/STUN/TURN    |
| Codec negotiation| SIP SDP          | WebRTC SDP       |
| Entry point      | Kamailio         | api-manager      |
| Audio quality    | G.711 (64kbps)   | Opus (variable)  |
+------------------+------------------+------------------+

Note

AI Implementation Hint

WebRTC calls enter through api-manager via WebSocket (WSS), not through Kamailio like PSTN calls. This means WebRTC calls require a valid authentication token for the WebSocket connection. If a WebRTC call fails to connect, check that the ICE candidate exchange completes successfully – common issues include STUN/TURN server misconfiguration or corporate firewalls blocking UDP.

SIP Trunk Call Flow

Calls between registered SIP endpoints (extensions):

SIP Trunk Extension-to-Extension:

Extension A     Kamailio       registrar-mgr     Asterisk      Extension B
     |              |               |               |               |
     | REGISTER     |               |               |               |
     +------------->|               |               |               |
     |              | Store         |               |               |
     |              | Registration  |               |               |
     |              +-------------->|               |               |
     |              |               |               |               |
     |<-------------+               |               |               |
     | 200 OK       |               |               |               |
     |              |               |               |               |
     |              |               |               |               | REGISTER
     |              |               |               |               |<-----------
     |              |               |               |               |
     |              |               |               |               | 200 OK
     |              |               |               |               +----------->
     |              |               |               |               |
     | INVITE       |               |               |               |
     | (to ext B)   |               |               |               |
     +------------->|               |               |               |
     |              |               |               |               |
     |              | Lookup        |               |               |
     |              | Registration  |               |               |
     |              +-------------->|               |               |
     |              |               |               |               |
     |              |<--------------+               |               |
     |              | Contact URI   |               |               |
     |              |               |               |               |
     |              | Route via     |               |               |
     |              | Asterisk      |               |               |
     |              +------------------------------>|               |
     |              |               |               |               |
     |              |               |               | INVITE        |
     |              |               |               +-------------->|
     |              |               |               |               |
     |              |               |               |<--------------+
     |              |               |               | 200 OK        |
     |              |               |               |               |
     |<-------------+<------------------------------+               |
     | 200 OK       |               |               |               |
     |              |               |               |               |
     |   RTP Media (possibly via RTPEngine)         |               |
     |<============>|<=============>|<=============>|<=============>|
     |              |               |               |               |

Call Recording Sequence

How recording starts and stops:

Recording Start Sequence:

flow-manager    call-manager     Asterisk      storage-manager    GCS
     |               |               |               |              |
     | Action:       |               |               |              |
     | record_start  |               |               |              |
     |               |               |               |              |
     | RPC: Start    |               |               |              |
     | Recording     |               |               |              |
     +-------------->|               |               |              |
     |               |               |               |              |
     |               | Create        |               |              |
     |               | Recording     |               |              |
     |               | Record (DB)   |               |              |
     |               |               |               |              |
     |               | ARI: Record   |               |              |
     |               | Channel       |               |              |
     |               +-------------->|               |              |
     |               |               |               |              |
     |               |               | Start mixing  |              |
     |               |               | audio to file |              |
     |               |               |               |              |
     |<--------------+               |               |              |
     | Recording ID  |               |               |              |
     |               |               |               |              |
     |               |               | (Call continues...)          |
     |               |               |               |              |
     | Action:       |               |               |              |
     | record_stop   |               |               |              |
     | (or hangup)   |               |               |              |
     |               |               |               |              |
     | RPC: Stop     |               |               |              |
     | Recording     |               |               |              |
     +-------------->|               |               |              |
     |               |               |               |              |
     |               | ARI: Stop     |               |              |
     |               | Recording     |               |              |
     |               +-------------->|               |              |
     |               |               |               |              |
     |               |<--------------+               |              |
     |               | Local file    |               |              |
     |               | path          |               |              |
     |               |               |               |              |
     |               | RPC: Upload   |               |              |
     |               | File          |               |              |
     |               +------------------------------>|              |
     |               |               |               |              |
     |               |               |               | Upload to    |
     |               |               |               | GCS bucket   |
     |               |               |               +------------->|
     |               |               |               |              |
     |               |               |               |<-------------+
     |               |               |               | URL          |
     |               |               |               |              |
     |               |<------------------------------+              |
     |               | Recording URL |               |              |
     |               |               |               |              |
     |               | Update        |               |              |
     |               | Recording     |               |              |
     |               | Record        |               |              |
     |               |               |               |              |

Note

AI Implementation Hint

Recording upload to cloud storage is asynchronous – the recording URL is not available immediately after the call ends. Poll GET /recordings/{recording-id} until the url field is populated. Signed URLs expire after 1 hour; fetch a fresh URL from the API each time you need to download. If the call hangs up before record_stop executes, the recording is stopped and uploaded automatically.

Recording File Lifecycle:

Recording Storage Flow:

1. During Call:
   +------------------------------------------+
   | Location: Asterisk local disk            |
   | Format: WAV (uncompressed)               |
   | Path: /var/spool/asterisk/recording/     |
   +------------------------------------------+

2. After Call Ends:
   +------------------------------------------+
   | Action: Convert to final format          |
   | Format: MP3 or WAV (configurable)        |
   | Compress for storage efficiency          |
   +------------------------------------------+

3. Upload to Cloud:
   +------------------------------------------+
   | Destination: Google Cloud Storage        |
   | Bucket: recordings-<customer-id>         |
   | Path: /<date>/<recording-id>.mp3         |
   | Access: Signed URLs (time-limited)       |
   +------------------------------------------+

4. Cleanup:
   +------------------------------------------+
   | Local file: Deleted after upload         |
   | Cloud retention: 90 days (default)       |
   | Customer can download before expiry      |
   +------------------------------------------+

AI Voice Call Sequence

Calls with AI assistant (Pipecat integration):

AI Voice Call - Detailed Flow:

Caller      Asterisk    pipecat-manager    pipecat-runner       LLM
   |           |              |                  |                |
   | Call      |              |                  |                |
   | Answered  |              |                  |                |
   +---------->|              |                  |                |
   |           |              |                  |                |
   |           | Audiosocket  |                  |                |
   |           | Connect      |                  |                |
   |           | (port 9000)  |                  |                |
   |           +------------->|                  |                |
   |           |              |                  |                |
   |           |              | Spawn Python     |                |
   |           |              | Process          |                |
   |           |              +----------------->|                |
   |           |              |                  |                |
   |           |              |<-----------------+                |
   |           |              | WebSocket Ready  |                |
   |           |              |                  |                |
   |           |<-------------+                  |                |
   |           | Audiosocket  |                  |                |
   |           | Connected    |                  |                |
   |           |              |                  |                |
   | Speak:    |              |                  |                |
   | "Hello"   |              |                  |                |
   +---------->|              |                  |                |
   |           |              |                  |                |
   |           | Audio Frame  |                  |                |
   |           | (8kHz ulaw)  |                  |                |
   |           +------------->|                  |                |
   |           |              |                  |                |
   |           |              | Resample         |                |
   |           |              | 8kHz->16kHz      |                |
   |           |              | ulaw->PCM        |                |
   |           |              |                  |                |
   |           |              | Protobuf Frame   |                |
   |           |              | INPUT_AUDIO_RAW  |                |
   |           |              +----------------->|                |
   |           |              |                  |                |
   |           |              |                  | STT: Deepgram  |
   |           |              |                  | "Hello"        |
   |           |              |                  +--------------->|
   |           |              |                  |                |
   |           |              |                  |<---------------+
   |           |              |                  | LLM Response   |
   |           |              |                  |                |
   |           |              |                  | TTS: Generate  |
   |           |              |                  | Audio          |
   |           |              |                  |                |
   |           |              |<-----------------+                |
   |           |              | Protobuf Frame   |                |
   |           |              | OUTPUT_AUDIO_RAW |                |
   |           |              |                  |                |
   |           |              | Resample         |                |
   |           |              | 16kHz->8kHz      |                |
   |           |              | PCM->ulaw        |                |
   |           |              |                  |                |
   |           |<-------------+                  |                |
   |           | Audio Frame  |                  |                |
   |           |              |                  |                |
   |<----------+              |                  |                |
   | AI speaks |              |                  |                |
   |           |              |                  |                |

Note

AI Implementation Hint

The AI voice call uses Audiosocket (port 9000) to bridge Asterisk audio to the Pipecat pipeline. Audio is resampled from Asterisk’s native 8kHz ulaw to 16kHz PCM for the STT/LLM processing, then resampled back for playback. This resampling happens automatically. If the AI voice sounds unnatural or there is high latency, the issue is typically in the LLM response time or TTS generation, not in the audio pipeline.

AI Tool Calling Sequence:

LLM Tool Call (e.g., Transfer):

pipecat-runner    pipecat-manager    call-manager    transfer-manager
      |                 |                 |                |
      | Frame:          |                 |                |
      | LLM_FUNCTION_CALL                 |                |
      | tool: transfer_call               |                |
      | args: {dest: "sales"}             |                |
      +---------------->|                 |                |
      |                 |                 |                |
      |                 | RPC: Execute    |                |
      |                 | Tool            |                |
      |                 +---------------->|                |
      |                 |                 |                |
      |                 |                 | RPC: Transfer  |
      |                 |                 +--------------->|
      |                 |                 |                |
      |                 |                 |                | Initiate
      |                 |                 |                | Transfer
      |                 |                 |                |
      |                 |                 |<---------------+
      |                 |                 | Success        |
      |                 |                 |                |
      |                 |<----------------+                |
      |                 | Tool Result     |                |
      |                 |                 |                |
      |<----------------+                 |                |
      | Frame:          |                 |                |
      | FUNCTION_RESULT |                 |                |
      | result: success |                 |                |
      |                 |                 |                |
      | (LLM receives   |                 |                |
      |  result, speaks |                 |                |
      |  confirmation)  |                 |                |

Conference Bridge Sequence

Multi-party conference call setup:

Conference Join Sequence:

Participant    flow-manager    conf-manager      Asterisk
     |              |               |               |
     | Call         |               |               |
     | Answered     |               |               |
     +------------->|               |               |
     |              |               |               |
     |              | Action:       |               |
     |              | conf_join     |               |
     |              |               |               |
     |              | RPC: Join     |               |
     |              | Conference    |               |
     |              +-------------->|               |
     |              |               |               |
     |              |               | Get/Create    |
     |              |               | Conference    |
     |              |               | Record        |
     |              |               |               |
     |              |               | ARI: Create   |
     |              |               | Bridge        |
     |              |               | (if not exist)|
     |              |               +-------------->|
     |              |               |               |
     |              |               |<--------------+
     |              |               | Bridge ID     |
     |              |               |               |
     |              |               | ARI: Add      |
     |              |               | Channel to    |
     |              |               | Bridge        |
     |              |               +-------------->|
     |              |               |               |
     |              |               |               | Mix audio
     |              |               |               | with other
     |              |               |               | participants
     |              |               |               |
     |              |               |<--------------+
     |              |               | Success       |
     |              |               |               |
     |              |<--------------+               |
     |              | Participant   |               |
     |              | Joined        |               |
     |              |               |               |
     |<-------------+               |               |
     | Hear other   |               |               |
     | participants |               |               |
     |              |               |               |

Conference Audio Mixing:

Conference Bridge Audio Flow:

+----------------+       +----------------+       +----------------+
| Participant A  |       | Participant B  |       | Participant C  |
+-------+--------+       +-------+--------+       +-------+--------+
        |                        |                        |
        | Audio A                | Audio B                | Audio C
        v                        v                        v
+-----------------------------------------------------------------------+
|                        Asterisk Bridge                                |
|                                                                       |
|   Audio Mixing:                                                       |
|   +-----------------------------------------------------------+       |
|   |  To A: Mix(B + C)                                         |       |
|   |  To B: Mix(A + C)                                         |       |
|   |  To C: Mix(A + B)                                         |       |
|   +-----------------------------------------------------------+       |
|                                                                       |
|   Each participant hears everyone except themselves                   |
+-----------------------------------------------------------------------+
        |                        |                        |
        | Mix(B+C)               | Mix(A+C)               | Mix(A+B)
        v                        v                        v
+-------+--------+       +-------+--------+       +-------+--------+
| Participant A  |       | Participant B  |       | Participant C  |
+----------------+       +----------------+       +----------------+

Note

AI Implementation Hint

Conference audio mixing is handled by Asterisk bridges internally. As an API consumer, you join participants to a conference via the conference_join flow action with a conference_id. Each participant is a separate call (and separately billed). The conference bridge automatically handles audio mixing so each participant hears all others but not themselves.

Event Publication Sequence

How call events propagate through the system:

Event Publication Flow:

Asterisk       call-manager        RabbitMQ        webhook-mgr     billing-mgr
    |               |                  |               |               |
    | StasisEnd     |                  |               |               |
    | (call ended)  |                  |               |               |
    +-------------->|                  |               |               |
    |               |                  |               |               |
    |               | Update Call      |               |               |
    |               | Record:          |               |               |
    |               | status=hangup    |               |               |
    |               |                  |               |               |
    |               | Publish Event:   |               |               |
    |               | call_hungup      |               |               |
    |               +----------------->|               |               |
    |               |                  |               |               |
    |               |                  | Fanout to     |               |
    |               |                  | subscribers   |               |
    |               |                  +-------------->|               |
    |               |                  |               |               |
    |               |                  +------------------------------>|
    |               |                  |               |               |
    |               |                  |               | Lookup        |
    |               |                  |               | webhook       |
    |               |                  |               | config        |
    |               |                  |               |               |
    |               |                  |               | POST to       |
    |               |                  |               | customer      |
    |               |                  |               | endpoint      |
    |               |                  |               |               |
    |               |                  |               |               | Calculate
    |               |                  |               |               | call cost
    |               |                  |               |               |
    |               |                  |               |               | Update
    |               |                  |               |               | balance

Note

AI Implementation Hint

Events are published to RabbitMQ and fanned out to all subscribers. As an API consumer, you receive events via webhooks (HTTP POST to your endpoint) or via WebSocket subscription. Webhook delivery is retried up to 3 times with exponential backoff if your endpoint returns a non-2xx status code. Always return HTTP 200 immediately and process the webhook asynchronously to avoid timeouts.

Event Types and Subscribers:

Call Event Subscriptions:

Event Type          Subscribers
─────────────────────────────────────────────────────────
call_created        webhook-manager, campaign-manager
call_ringing        webhook-manager
call_answered       webhook-manager, billing-manager
call_hungup         webhook-manager, billing-manager,
                    campaign-manager, queue-manager,
                    transfer-manager, ai-manager
call_recording      webhook-manager, storage-manager
call_transcribing   webhook-manager, transcribe-manager

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 /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 /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/calls/{call-id}/transfer
{
    "type": "attended",
    "destination": {
        "type": "tel",
        "target": "+15553333333"
    },
    "context": {
        "customer_id": "cust-123",
        "issue": "billing dispute",
        "notes": "Customer called about incorrect charge on invoice #456"
    }
}

Response:
{
    "transfer_id": "transfer-uuid",
    "consult_call_id": "consult-call-uuid",
    "status": "consulting"
}

Step 2: Agent A talks to Agent B, then completes
POST /v1/transfers/{transfer-id}/complete

Step 3: Agent B receives context via webhook or screen pop
Webhook: transfer_completed
{
    "type": "transfer_completed",
    "data": {
        "transfer_id": "transfer-uuid",
        "from_agent": "agent-a-uuid",
        "to_agent": "agent-b-uuid",
        "context": {
            "customer_id": "cust-123",
            "issue": "billing dispute",
            "notes": "Customer called about incorrect charge on invoice #456"
        }
    }
}

Note

AI Implementation Hint

The call-id in POST /v1/calls/{call-id}/transfer must be an active call in progressing status. The transfer_id returned in the response is used for subsequent operations: POST /v1/transfers/{transfer-id}/complete to finish the transfer, or POST /v1/transfers/{transfer-id}/cancel to abort it. The context object is passed through to the transfer_completed webhook, allowing Agent B’s application to display caller information. 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.

Call Media and Codecs

This section covers audio and video media handling in VoIPBIN, including codec support, quality considerations, and encryption.

Note

AI Implementation Hint

Media operations (recording, transcription, TTS) require an active call in progressing status. Obtain the call-id from GET /calls or from a webhook event (e.g., call_answered) before issuing media-related API calls. Starting media operations on a call that has not yet been answered will fail.

Audio Codec Support

VoIPBIN supports multiple audio codecs for different use cases:

Supported Audio Codecs:

+----------+------------+-----------+------------------+------------------------+
| Codec    | Bitrate    | Sample    | Quality          | Use Case               |
|          |            | Rate      |                  |                        |
+----------+------------+-----------+------------------+------------------------+
| G.711    | 64 kbps    | 8 kHz     | Good (PSTN)      | PSTN calls, SIP trunks |
| (ulaw/   |            |           |                  |                        |
|  alaw)   |            |           |                  |                        |
+----------+------------+-----------+------------------+------------------------+
| G.722    | 64 kbps    | 16 kHz    | Excellent (HD)   | HD voice SIP calls     |
+----------+------------+-----------+------------------+------------------------+
| G.729    | 8 kbps     | 8 kHz     | Acceptable       | Low bandwidth links    |
+----------+------------+-----------+------------------+------------------------+
| Opus     | 6-510 kbps | 8-48 kHz  | Excellent        | WebRTC, adaptive       |
|          | (adaptive) |           |                  |                        |
+----------+------------+-----------+------------------+------------------------+
| PCMU     | 64 kbps    | 8 kHz     | Good             | Same as G.711 ulaw     |
+----------+------------+-----------+------------------+------------------------+
| PCMA     | 64 kbps    | 8 kHz     | Good             | Same as G.711 alaw     |
+----------+------------+-----------+------------------+------------------------+

Codec Selection:

Codec Selection by Call Type:

PSTN Calls:
+------------------------------------------+
| Codec: G.711 (ulaw for US, alaw for EU)  |
| Reason: Universal PSTN compatibility     |
| Quality: Standard telephone quality      |
+------------------------------------------+

WebRTC Calls:
+------------------------------------------+
| Codec: Opus (primary)                    |
| Reason: Adaptive bitrate, loss resilient |
| Quality: HD voice up to 48 kHz           |
+------------------------------------------+

SIP Trunk (HD):
+------------------------------------------+
| Codec: G.722 (if supported)              |
| Fallback: G.711                          |
| Quality: Wideband audio (16 kHz)         |
+------------------------------------------+

Low Bandwidth:
+------------------------------------------+
| Codec: G.729                             |
| Reason: Only 8 kbps required             |
| Quality: Acceptable for voice            |
+------------------------------------------+

Note

AI Implementation Hint

Codec selection is automatic. VoIPBIN negotiates the best codec supported by both endpoints. You do not need to specify a codec when creating calls. If you experience audio quality issues, check the call type: PSTN calls use G.711 (narrowband), while WebRTC calls use Opus (wideband). Transcoding between codec types adds minimal latency.

Audio Quality Factors

Several factors affect call audio quality:

Quality Factor: Network Latency

+------------------------------------------+
| < 150ms:  Excellent - natural conversation
| 150-300ms: Good - slight delay noticeable
| 300-500ms: Fair - conversation difficult
| > 500ms:  Poor - echo, overlap issues
+------------------------------------------+

VoIPBIN Infrastructure:
+------------------------------------------+
| Global edge locations minimize latency   |
| Typical added latency: < 30ms            |
+------------------------------------------+
Quality Factor: Packet Loss

+------------------------------------------+
| 0%:    Perfect audio
| 1-2%:  Minor artifacts, acceptable
| 3-5%:  Noticeable degradation
| > 5%:  Significant quality loss
+------------------------------------------+

VoIPBIN Mitigation:
+------------------------------------------+
| - Opus codec: Built-in packet loss       |
|   concealment up to 15%                  |
| - Jitter buffer: Smooths packet timing   |
| - FEC: Forward Error Correction (Opus)   |
+------------------------------------------+
Quality Factor: Jitter

+------------------------------------------+
| Definition: Variation in packet arrival  |
|                                          |
| < 20ms:  Excellent                       |
| 20-50ms: Good (jitter buffer handles)    |
| > 50ms:  Poor - buffer underruns         |
+------------------------------------------+

VoIPBIN Jitter Buffer:
+------------------------------------------+
| Type: Adaptive                           |
| Range: 20-200ms                          |
| Adapts to network conditions             |
+------------------------------------------+

RTP and Media Transport

Real-time Transport Protocol (RTP) carries audio:

RTP Packet Structure:

+-----------------------------------+
| V=2|P|X|CC |M| PT |  Sequence #  |   12 bytes
|           Timestamp              |   header
|             SSRC                 |
+-----------------------------------+
|            Payload               |   Audio
|        (codec-encoded audio)     |   data
+-----------------------------------+

Header Fields:
+------------------------------------------+
| V:  Version (always 2)                   |
| P:  Padding flag                         |
| X:  Extension flag                       |
| CC: CSRC count                           |
| M:  Marker bit (frame boundary)          |
| PT: Payload type (codec identifier)      |
| Sequence: Packet ordering                |
| Timestamp: Sampling instant              |
| SSRC: Synchronization source ID          |
+------------------------------------------+

RTP Port Ranges:

VoIPBIN RTP Ports:

Media Servers (Asterisk):
+------------------------------------------+
| Range: 10000-20000 UDP                   |
| Per call: 2 ports (RTP + RTCP)           |
+------------------------------------------+

RTPEngine (Media Proxy):
+------------------------------------------+
| Range: 20000-60000 UDP                   |
| Handles NAT traversal                    |
| Provides encryption bridging             |
+------------------------------------------+

Client Requirements:
+------------------------------------------+
| Outbound UDP to VoIPBIN ports required   |
| If blocked: WebRTC with TURN as fallback |
+------------------------------------------+

Note

AI Implementation Hint

If a client reports one-way audio or no audio, the most common cause is a firewall blocking UDP traffic on the RTP port ranges. For environments with restrictive firewalls, use WebRTC with TURN relay as a fallback. WebRTC encapsulates media over TCP/443, bypassing most firewall restrictions.

Media Encryption

VoIPBIN supports encrypted media for security:

SRTP (Secure RTP):

SRTP Encryption:

+------------------------------------------+
| Algorithm: AES-128-CM                    |
| Authentication: HMAC-SHA1-80             |
| Key exchange: DTLS-SRTP or SDES          |
+------------------------------------------+

SRTP Packet:
+-----------------------------------+
| RTP Header (not encrypted)        |
+-----------------------------------+
| Encrypted Payload                 |
| (AES-128 Counter Mode)            |
+-----------------------------------+
| Authentication Tag (10 bytes)     |
+-----------------------------------+

Encryption by Call Type:

Encryption Matrix:

+------------------+-------------+-----------+
| Call Type        | Signaling   | Media     |
+------------------+-------------+-----------+
| WebRTC           | WSS (TLS)   | SRTP      |
| SIP over TLS     | TLS         | SRTP*     |
| SIP over UDP     | None        | RTP       |
| PSTN             | N/A         | RTP**     |
+------------------+-------------+-----------+

* SRTP if negotiated via SDES or DTLS
** PSTN segment is unencrypted (carrier network)

End-to-End Encryption:

E2E Encryption Consideration:

WebRTC to WebRTC:
+------------------------------------------+
| Full SRTP encryption possible            |
| Keys never leave endpoints               |
+------------------------------------------+

WebRTC to PSTN:
+------------------------------------------+
| WebRTC leg: SRTP encrypted               |
| VoIPBIN: Decrypts to mix/process         |
| PSTN leg: Unencrypted (carrier limit)    |
+------------------------------------------+

Note: VoIPBIN must decrypt media for:
- Transcoding between codecs
- Recording
- Transcription
- Conferencing (mixing)

Note

AI Implementation Hint

WebRTC calls are always encrypted (SRTP). PSTN calls are unencrypted on the carrier segment – this is a carrier limitation, not a VoIPBIN limitation. If you need recording or transcription, VoIPBIN must access the unencrypted audio stream, so true end-to-end encryption is not possible when these features are enabled.

DTMF Handling

Dual-Tone Multi-Frequency (DTMF) for IVR input:

DTMF Methods:

RFC 2833 (RTP Events):
+------------------------------------------+
| DTMF sent as special RTP packets         |
| Payload type: 101 (commonly)             |
| Most reliable for VoIP                   |
| VoIPBIN default method                   |
+------------------------------------------+

In-band (Audio):
+------------------------------------------+
| DTMF tones in audio stream               |
| Can be compressed/distorted              |
| Fallback for legacy systems              |
+------------------------------------------+

SIP INFO:
+------------------------------------------+
| DTMF in SIP signaling messages           |
| Not affected by audio path               |
| Less common                              |
+------------------------------------------+

DTMF in API:

Sending DTMF:
POST /v1/calls/{call-id}/dtmf
{
    "digits": "1234#",
    "duration": 250,      // ms per digit
    "interval": 100       // ms between digits
}

Receiving DTMF (in flow):
{
    "type": "digits_receive",
    "option": {
        "length": 4,          // Expected digits
        "duration": 10000,    // Timeout ms
        "terminator": "#"     // Optional end char
    }
}

Note

AI Implementation Hint

The call-id in POST /v1/calls/{call-id}/dtmf must be an active call in progressing status. Obtain it from GET /calls or from a webhook event. The digits field accepts 0-9, *, and #. The duration controls how long each tone plays (in milliseconds) and interval controls the pause between tones.

Recording Formats

VoIPBIN supports multiple recording formats:

Recording Format Options:

+--------+------------+-----------+------------------+
| Format | Codec      | Quality   | File Size        |
+--------+------------+-----------+------------------+
| WAV    | PCM        | Lossless  | ~960 KB/min      |
| MP3    | MP3        | Good      | ~128 KB/min      |
| OGG    | Opus       | Excellent | ~96 KB/min       |
+--------+------------+-----------+------------------+

Default: MP3 (balance of quality and size)

Recording Configuration:

Recording Options:

{
    "type": "record_start",
    "option": {
        "direction": "both",    // "in", "out", "both"
        "format": "mp3",        // "wav", "mp3", "ogg"
        "channels": "mixed",    // "mixed", "stereo"
        "sample_rate": 16000    // Hz
    }
}

Direction Explained:
+------------------------------------------+
| "in":   Record only incoming audio       |
|         (what caller says)               |
|                                          |
| "out":  Record only outgoing audio       |
|         (what system/agent says)         |
|                                          |
| "both": Record entire conversation       |
|         (default, recommended)           |
+------------------------------------------+

Channels:
+------------------------------------------+
| "mixed":  Single track, both parties     |
|           combined. Smaller file.        |
|                                          |
| "stereo": Two tracks, parties separated  |
|           Left = inbound, Right = outbound|
|           Better for analysis/transcription|
+------------------------------------------+

Note

AI Implementation Hint

Recording must be started with a record_start flow action and stopped with record_stop or automatically when the call hangs up. Recordings are uploaded to cloud storage asynchronously after the call ends. The recording URL obtained from GET /recordings/{id} uses signed URLs that expire after 1 hour. Fetch a fresh URL each time you need to download.

Text-to-Speech (TTS)

TTS converts text to spoken audio:

TTS Providers:

Google Cloud TTS (default):
+------------------------------------------+
| Voices: 200+ in 40+ languages            |
| Quality: Neural and Standard             |
| SSML: Supported                          |
+------------------------------------------+

AWS Polly:
+------------------------------------------+
| Voices: 60+ in 30+ languages             |
| Quality: Neural and Standard             |
| SSML: Supported                          |
+------------------------------------------+

Provider Fallback:
+------------------------------------------+
| If the selected provider fails, the      |
| system falls back to the alternative     |
| provider with the default voice for the  |
| language.                                |
+------------------------------------------+

TTS Action Example:
{
    "type": "talk",
    "option": {
        "text": "Hello, welcome to our service.",
        "language": "en-US",
        "provider": "gcp",                  // Optional: "gcp" or "aws"
        "voice_id": "en-US-Neural2-C"       // Optional: provider-specific voice
    }
}

SSML Support:

SSML (Speech Synthesis Markup Language):

Basic Example:
{
    "type": "talk",
    "option": {
        "text": "<speak>Your balance is <say-as interpret-as='currency'>$123.45</say-as></speak>",
        "language": "en-US"
    }
}

Common SSML Tags:
+------------------------------------------+
| <break time='500ms'/>  - Pause           |
| <emphasis>            - Stress word      |
| <prosody rate='slow'> - Speed control    |
| <say-as>              - Format numbers   |
| <phoneme>             - Pronunciation    |
+------------------------------------------+

Speech-to-Text (STT)

Real-time transcription of audio:

STT Configuration:

{
    "type": "transcribe_start",
    "option": {
        "language": "en-US",
        "direction": "both",      // "in", "out", "both"
        "interim_results": false  // Real-time partials
    }
}

Supported Languages:
+------------------------------------------+
| 70+ languages and regional variants      |
| See: transcribe_overview for full list   |
+------------------------------------------+

STT Accuracy Tips:

Improve Transcription Accuracy:

1. Correct Language:
   +------------------------------------------+
   | Specify exact locale: "en-US" vs "en-GB" |
   | Affects vocabulary and accent models     |
   +------------------------------------------+

2. Audio Quality:
   +------------------------------------------+
   | Clear audio = better transcription       |
   | Minimize background noise                |
   | Use headsets for agents                  |
   +------------------------------------------+

3. Sample Rate:
   +------------------------------------------+
   | Higher sample rate (16kHz+) helps        |
   | VoIPBIN resamples automatically          |
   +------------------------------------------+

Note

AI Implementation Hint

Transcription events are delivered via WebSocket subscription, not via webhooks. Subscribe to customer_id:<your-id>:transcript:* to receive real-time transcript events. Each event contains the direction (in or out) so you can distinguish which party is speaking. The language parameter must use the exact locale code (e.g., en-US, not en).

Video Calls (WebRTC)

VoIPBIN supports video via WebRTC:

Video Codec Support:

+--------+------------+-----------------+
| Codec  | Resolution | Use Case        |
+--------+------------+-----------------+
| VP8    | Up to 720p | Default WebRTC  |
| VP9    | Up to 1080p| Higher quality  |
| H.264  | Up to 1080p| Hardware accel  |
+--------+------------+-----------------+

Video Constraints:
+------------------------------------------+
| Max resolution: 1280x720 (720p)          |
| Max framerate: 30 fps                    |
| Max bitrate: 2 Mbps                      |
+------------------------------------------+

Video Conferencing:

Video Conference Layout:

2 Participants:
+-------------+-------------+
|             |             |
|     A       |      B      |
|             |             |
+-------------+-------------+

4 Participants:
+------+------+------+------+
|  A   |  B   |  C   |  D   |
+------+------+------+------+

Active Speaker:
+---------------------------+
|                           |
|     Active Speaker        |
|                           |
+-------+-------+-------+---+
| P1    | P2    | P3    | ...|
+-------+-------+-------+---+

Bandwidth Requirements

Plan network capacity based on call types:

Bandwidth per Call:

Audio Only (G.711):
+------------------------------------------+
| RTP payload: 64 kbps                     |
| + Headers: ~15 kbps                      |
| = Total: ~80 kbps per direction          |
| Bidirectional: ~160 kbps per call        |
+------------------------------------------+

Audio Only (Opus):
+------------------------------------------+
| Adaptive: 6-128 kbps                     |
| Typical: 24-32 kbps                      |
| + Headers: ~15 kbps                      |
| Bidirectional: ~100 kbps per call        |
+------------------------------------------+

Video (720p):
+------------------------------------------+
| Video: 1-2 Mbps                          |
| Audio: ~100 kbps (Opus)                  |
| Bidirectional: ~4 Mbps per call          |
+------------------------------------------+

Capacity Planning:

Example: 100 Concurrent Calls

Audio Only (G.711):
+------------------------------------------+
| 100 calls x 160 kbps = 16 Mbps           |
| Recommended: 20 Mbps (headroom)          |
+------------------------------------------+

Audio Only (Opus):
+------------------------------------------+
| 100 calls x 100 kbps = 10 Mbps           |
| Recommended: 15 Mbps (headroom)          |
+------------------------------------------+

Video (720p):
+------------------------------------------+
| 100 calls x 4 Mbps = 400 Mbps            |
| Recommended: 500 Mbps (headroom)         |
+------------------------------------------+

Quality Monitoring

Monitor call quality with metrics:

Available Metrics (via API/Webhooks):

Call Level:
+------------------------------------------+
| duration         - Total call time       |
| ringing_duration - Time ringing          |
| talk_duration    - Connected time        |
| hangup_reason    - Why call ended        |
+------------------------------------------+

Media Level (when available):
+------------------------------------------+
| jitter           - Packet timing variance|
| packet_loss      - % packets lost        |
| rtt              - Round-trip time       |
| mos              - Mean Opinion Score    |
+------------------------------------------+

MOS Score Reference:
+------------------------------------------+
| 4.3-5.0: Excellent (HD quality)          |
| 4.0-4.3: Good (toll quality)             |
| 3.6-4.0: Fair (acceptable)               |
| 3.1-3.6: Poor (degraded)                 |
| < 3.1:   Bad (unacceptable)              |
+------------------------------------------+

Note

AI Implementation Hint

Call-level metrics (duration, hangup_reason) are available in the call object via GET /calls/{call-id} after the call ends. Media-level metrics (jitter, packet_loss, mos) may not be available for all call types. A MOS score below 3.6 typically indicates network issues (high latency, packet loss, or jitter) rather than a VoIPBIN platform problem.

Call Troubleshooting

This guide helps you diagnose and resolve common call issues. Each problem includes symptoms, causes, and solutions.

Note

AI Implementation Hint

When troubleshooting, always start by fetching the call details: GET /v1/calls/{call-id}. The status, hangup_by, hangup_reason, and timestamp fields provide the primary diagnostic information. If the call has an associated flow_id, also check GET /v1/activeflows/{activeflow-id} for flow execution errors.

Debugging Tools

Before troubleshooting, understand the tools available:

API Endpoints for Debugging:

Get call details:
GET /v1/calls/{call-id}

Get call events (webhooks sent):
GET /v1/calls/{call-id}/events

Get activeflow status:
GET /v1/activeflows/{activeflow-id}

Get recordings:
GET /v1/calls/{call-id}/recordings

Get transcripts:
GET /v1/calls/{call-id}/transcripts

Note

AI Implementation Hint

The call-id is a UUID returned when creating a call via POST /calls or from webhook events. The activeflow-id is obtained from the call’s associated flow execution. All debugging endpoints require a valid authentication token (JWT or access key).

WebSocket for Real-time Monitoring:

Connect:
wss://api.voipbin.net/v1.0/ws?token=<token>

Subscribe to all call events:
{
    "type": "subscribe",
    "topics": ["customer_id:<your-id>:call:*"]
}

Events you'll receive:
- call_created
- call_ringing
- call_answered (progressing)
- call_hungup
- call_recording_started
- call_transcribing

Call Never Connects

Symptom: Call status goes directly from dialing to hangup. The hangup_reason is failed. No ringing ever occurred (tm_ringing is 9999-01-01 00:00:00.000000).

Diagnostic API call:

GET /v1/calls/{call-id}

Look for:
{
  "status": "hangup",
  "hangup_reason": "failed",
  "hangup_by": "remote",
  "tm_ringing": "9999-01-01 00:00:00.000000"
}

Cause 1: Invalid Phone Number Format

Problem:
"+1 555-123-4567" (has spaces/dashes)

Fix:
"+15551234567" (E.164 format, digits only after +)

Cause 2: Number Not Provisioned

Problem:
Source number not in your account.

Diagnostic:
GET /v1/numbers
Verify the source number appears in the response.

Fix:
Purchase a number via POST /v1/numbers or use a number
you already own.

Cause 3: Insufficient Balance

Problem:
Account balance too low for call.

Diagnostic:
GET /v1/billing-accounts
Check that balance > 0 and status = "active".

Fix:
Add funds to your account.

Cause 4: Carrier Rejection

Problem:
Destination carrier rejected the call.

Symptoms:
- Works to some numbers, not others
- Specific area codes fail

Fix:
Contact support with the call-id for investigation.
Try alternate routes if available.

Call Rings But No Answer

Symptom: Call reaches ringing status, then hangs up. The hangup_reason is noanswer or dialout.

Understanding the difference:

"noanswer":
+------------------------------------------+
| The destination phone rang until the     |
| destination's voicemail or timeout       |
| kicked in.                               |
|                                          |
| Duration: Typically 30-60 seconds        |
| Cause: Nobody picked up                  |
+------------------------------------------+

"dialout":
+------------------------------------------+
| VoIPBIN's dial timeout expired before    |
| the call was answered.                   |
|                                          |
| Duration: Your configured timeout        |
| Cause: Your timeout is shorter than      |
|        typical ring time                 |
+------------------------------------------+

Fix for “noanswer”:

This is expected behavior when nobody answers.
- Consider using AMD to detect voicemail and leave a message
- Implement retry logic in your application
- Use groupcall with multiple destinations for fallback

Fix for “dialout”:

Increase dial_timeout in your call request:

POST /v1/calls
{
  "dial_timeout": 45000,
  "destinations": [...]
}

Default timeout is 30000 ms (30 seconds).
Recommended: 45000-60000 ms for PSTN calls.

Call Answers But No Audio

Symptom: Call reaches progressing status. One or both parties cannot hear each other. Call may disconnect after silence.

Diagnostic API call:

GET /v1/calls/{call-id}

Check these fields:
- status: should be "progressing"
- hold: should be false
- mute_direction: should be "" (empty = unmuted)

Cause 1: NAT/Firewall Issues (WebRTC)

Symptoms:
- WebRTC call connects (signaling OK)
- No audio in either direction

Fix:
- Ensure TURN server is configured
- Check client firewall allows UDP
- Verify ICE gathering completes
- Test with a different network

Cause 2: Codec Mismatch

Symptoms:
- SIP call connects
- RTP flows but audio is garbled or silent

Fix:
VoIPBIN auto-transcodes between codecs, but check
endpoint codec configuration if using SIP trunking.

Cause 3: Hold State Stuck

Symptoms:
- Call was working, then went silent
- One party can hear, other cannot

Diagnostic:
GET /v1/calls/{call-id}
{
  "mute_direction": "both",
  "hold": true
}

Fix:
POST /v1/calls/{call-id}/resume
POST /v1/calls/{call-id}/unmute

Note

AI Implementation Hint

For WebRTC no-audio issues, the problem is almost always network-related (firewall, NAT, TURN). Check the browser’s developer console for ICE connection state errors. For SIP calls with one-way audio, the issue is typically NAT – the RTP packets are being sent to the wrong IP address. VoIPBIN’s RTPEngine handles most NAT traversal automatically.

Flow Actions Not Executing

Symptom: Call answers but expected TTS/media does not play. Actions seem to be skipped.

Diagnostic API call:

GET /v1/activeflows/{activeflow-id}

Look for error in current_action:
{
  "current_action": {
    "type": "talk",
    "error": "TTS service unavailable"
  }
}

Cause 1: early_execution Timing

Problem:
Actions execute before call answers.

With early_execution: true, actions start on INVITE
(before 200 OK). The call may not be ready for audio.

Fix:
Set early_execution: false (default).
Actions start after the call is answered (200 OK).

Cause 2: Action Errors

Problem:
An action fails and flow stops.

Diagnostic:
GET /v1/activeflows/{activeflow-id}

Fix:
Check the error message in current_action.
Verify action configuration (correct fields, valid IDs).

Cause 3: Missing Action IDs for Branching

Problem:
Branch targets an action ID that does not exist.

Example:
{
  "type": "branch",
  "option": {
    "target_ids": {
      "1": "nonexistent-id"
    }
  }
}

Fix:
Verify all target_ids match an action "id" in the same flow.
Use GET /v1/flows/{flow-id} to inspect the flow definition.

Note

AI Implementation Hint

If flow actions are not executing at all, verify that the call has a flow_id set (not 00000000-0000-0000-0000-000000000000). For outbound calls, you must either provide actions inline in POST /calls or reference an existing flow via flow_id. For inbound calls, the flow is determined by the phone number configuration – check GET /numbers/{number-id} for the flow_id assignment.

Webhooks Not Received

Symptom: No webhooks arrive at your endpoint, or only some webhooks arrive.

Diagnostic API calls:

1. Verify webhook configuration:
GET /v1/webhooks
{
  "url": "https://your-server.com/webhook",
  "events": ["call_hungup", "call_answered"],
  "status": "active"
}

2. Check webhook delivery history:
GET /v1/webhooks/{webhook-id}/deliveries
{
  "deliveries": [
    {
      "id": "delivery-uuid",
      "event_type": "call_hungup",
      "status": "failed",
      "http_code": 500,
      "attempts": 3,
      "last_attempt": "2026-01-20T12:00:00Z",
      "error": "Connection timeout"
    }
  ]
}

Cause 1: Endpoint not accessible

Symptoms:
- Delivery status is "failed"
- Error indicates connection refused or timeout

Fix:
- Whitelist VoIPBIN IP ranges in your firewall
- Use valid SSL certificate (self-signed certs are rejected)
- Ensure your endpoint returns HTTP 200 OK

Cause 2: Endpoint too slow

Symptoms:
- Webhook times out (> 5 seconds)
- VoIPBIN retries, causing duplicate deliveries

Fix:
- Return HTTP 200 immediately
- Process the webhook payload asynchronously
- Use a message queue (e.g., SQS, RabbitMQ) for processing

Cause 3: Wrong event subscription

Symptoms:
- Subscribed to "call_created" but expecting "call_hungup"

Fix:
Update webhook events:
PUT /v1/webhooks/{webhook-id}
{"events": ["call_hungup", "call_answered", "call_created"]}

Note

AI Implementation Hint

Webhook delivery is retried up to 3 times with exponential backoff. If all retries fail, the event is dropped. Always return HTTP 200 immediately and process asynchronously. Check GET /v1/webhooks/{webhook-id}/deliveries to see delivery attempts and failure reasons. If you are not receiving any webhooks, verify your webhook status is active and the events array includes the event types you need.

Recording Issues

Symptom: Recording not found, recording is empty or truncated, or recording URL does not work.

Diagnostic API call:

GET /v1/calls/{call-id}
Check the recording_ids array:
{
  "recording_ids": []
}

Cause 1: Recording Not Created

Symptoms:
- recording_ids array is empty

Possible reasons:
- record_start action not in flow
- Call hung up before recording started
- Error in recording action

Fix:
Verify flow has record_start action.
Check GET /v1/activeflows/{activeflow-id} for errors.

Cause 2: Recording Empty (duration 0)

Symptoms:
- Recording exists but duration is 0

Possible reasons:
- Recording started after call ended
- Audio not flowing during recording (call on mute)

Fix:
Place record_start early in the flow action list.
Verify call had audio (not on mute/hold).

Cause 3: Recording URL Returns 403

Symptoms:
- GET /v1/recordings/{id} returns a URL
- Downloading the URL fails with HTTP 403

Cause:
Signed URLs expire after 1 hour.

Fix:
Fetch a fresh URL from the API:
GET /v1/recordings/{recording-id}
Download immediately after getting the URL.

Note

AI Implementation Hint

Recording upload to cloud storage is asynchronous. After a call ends, the recording may take a few seconds to become available. If GET /v1/recordings/{recording-id} returns a recording without a url, the upload is still in progress. Poll the endpoint until url is populated. Cloud storage retention is 90 days by default – download recordings before they expire.

Transfer Problems

Symptom: Transfer fails, caller dropped during transfer, or consult call does not connect.

Diagnostic API call:

GET /v1/transfers/{transfer-id}
{
  "status": "consulting",
  "consult_call": {
    "status": "hangup",
    "hangup_reason": "noanswer"
  }
}

Cause 1: Blind Transfer Fails

Symptoms:
- Caller disconnected during transfer

Possible reasons:
- Transfer destination busy or unavailable
- No failover configured

Fix:
Use attended transfer for important calls.
Configure fallback action on failure.

Cause 2: Attended Transfer - Consult Fails

Symptoms:
- Agent A cannot reach Agent B

Diagnostic:
GET /v1/transfers/{transfer-id}

Fix:
Cancel transfer and try a different agent:
POST /v1/transfers/{transfer-id}/cancel

Cause 3: Caller Hears Dead Air During Transfer

Symptoms:
- Hold music not playing during transfer

Possible reasons:
- MOH not configured
- Mute applied instead of hold

Fix:
Ensure transfer uses proper hold:
POST /v1/calls/{call-id}/transfer
{
  "hold_caller": true,
  "play_moh": true
}

Note

AI Implementation Hint

The transfer-id is returned in the response to POST /v1/calls/{call-id}/transfer. Use it to check transfer status (GET /v1/transfers/{transfer-id}), complete the transfer (POST /v1/transfers/{transfer-id}/complete), or cancel it (POST /v1/transfers/{transfer-id}/cancel). If a blind transfer fails, the caller may be disconnected with no way to recover. For critical calls, always prefer attended transfer.

Queue Problems

Symptom: Calls not distributed to agents, long wait times, or agents not receiving calls.

Diagnostic API calls:

Check queue status:
GET /v1/queues/{queue-id}
{
  "available_agents": 0,
  "waiting_calls": 5
}

Check agent status:
GET /v1/agents?queue_id={queue-id}
Verify agents have status: "available"

Cause 1: No Available Agents

Symptoms:
- available_agents is 0
- waiting_calls is increasing

Possible reasons:
- All agents in "busy" or "offline" status
- Agents not logged into queue
- Agent status not updated after previous call

Fix:
Verify agent status via GET /v1/agents.
Ensure agents set their status to "available" after calls.

Cause 2: Calls Timing Out in Queue

Symptoms:
- Calls hang up after short wait

Diagnostic:
GET /v1/queues/{queue-id}
{
  "timeout": 30000,
  "timeout_action": "hangup"
}

Fix:
Increase timeout and add a fallback action:
PUT /v1/queues/{queue-id}
{
  "timeout": 300000,
  "timeout_flow_id": "voicemail-flow-uuid"
}

Note

AI Implementation Hint

The queue-id is a UUID obtained from GET /queues. The timeout_flow_id must reference a valid flow (obtained from GET /flows) that handles the fallback (e.g., play a message and take a voicemail). Agent status is managed via PUT /v1/agents/{agent-id} with the status field. Common agent statuses are available, busy, away, and offline.

Error Reference

Hangup Reason Quick Reference:

+----------------+----------------------------------+------------------------+
| Reason         | Meaning                          | Action                 |
+----------------+----------------------------------+------------------------+
| normal         | Call completed successfully      | No action needed       |
| failed         | Network/routing failure          | Check number, routes   |
| busy           | Destination busy                 | Retry later            |
| noanswer       | No answer before timeout         | Leave voicemail        |
| cancel         | Caller cancelled                 | No action needed       |
| dialout        | VoIPBIN timeout                  | Increase dial_timeout  |
| timeout        | Max call duration exceeded       | Check timeout settings |
| amd            | Answering machine detected       | Expected behavior      |
+----------------+----------------------------------+------------------------+

Note

AI Implementation Hint

The hangup_reason field is the most important diagnostic field. failed means the call never reached the phone network (check number format, provisioning, balance). noanswer and dialout both mean nobody picked up, but dialout is your timeout while noanswer is the destination’s timeout. cancel means the originator hung up before the call was answered. amd means voicemail was detected and your AMD settings triggered a hangup.

HTTP Error Codes:

+------+----------------------------------+-------------------------------+
| Code | Meaning                          | Fix                           |
+------+----------------------------------+-------------------------------+
| 400  | Invalid request format           | Check request body JSON       |
|      |                                  | and required fields           |
+------+----------------------------------+-------------------------------+
| 401  | Authentication failed            | Check JWT token or access key |
|      |                                  | is valid and not expired      |
+------+----------------------------------+-------------------------------+
| 403  | Permission denied                | Check account permissions     |
|      |                                  | and resource ownership        |
+------+----------------------------------+-------------------------------+
| 404  | Resource not found               | Verify the UUID exists via    |
|      |                                  | the corresponding GET endpoint|
+------+----------------------------------+-------------------------------+
| 409  | Conflict (e.g., call ended)      | Resource state changed;       |
|      |                                  | re-fetch and retry            |
+------+----------------------------------+-------------------------------+
| 429  | Rate limit exceeded              | Slow down requests; implement |
|      |                                  | exponential backoff           |
+------+----------------------------------+-------------------------------+
| 500  | Server error                     | Contact support with the      |
|      |                                  | request ID from the response  |
+------+----------------------------------+-------------------------------+

Note

AI Implementation Hint

For HTTP 400 errors, the response body contains a detailed error message describing which field is invalid. For HTTP 404, always verify the resource ID by calling the corresponding list endpoint first (e.g., GET /calls to verify a call-id exists before operating on it). For HTTP 429, implement exponential backoff starting at 1 second. For HTTP 500, include the x-request-id response header when contacting support.

Getting Help

If issues persist after troubleshooting, see Support for contact information and additional resources.