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 /callsreturns immediately with statusdialing. PollGET /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.
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.
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.
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 viaPOST /callsor when listing calls viaGET /calls.flow_id(UUID): The flow associated with this call. Obtained from theidfield ofGET /flows. Set to00000000-0000-0000-0000-000000000000if 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’sidfield. If set, this call follows the master call’s hangup. Set to00000000-0000-0000-0000-000000000000if this call has no master.chained_call_ids(Array of UUID): List of chained call IDs linked to this call. Each ID is a callidfromGET /calls. When this call hangs up, all chained calls also hang up.recording_id(UUID): The currently active recording’s ID. Obtained fromGET /recordings. Set to00000000-0000-0000-0000-000000000000if 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 withGET /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
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 |
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 viaGET /groupcalls.customer_id(UUID): The customer who owns this groupcall. Obtained from theidfield ofGET /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 to00000000-0000-0000-0000-000000000000until a destination answers. Obtained fromGET /calls.call_ids(Array of UUID): List of call IDs created for each destination. Each ID can be used withGET /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/loginor use an access key fromGET /accesskeys.A source phone number in E.164 format (e.g.,
+15551234567). This must be a number you own. Obtain your numbers viaGET /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 /flowsor obtain fromGET /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.targetordestinations[].targetphone 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.targetphone 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_iddoes not exist or belongs to a different customer.Fix: Verify the flow ID was obtained from
GET /flowsorPOST /flows.
- Call immediately hangs up:
Cause: No
answeraction 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’shangup_reasonfield viaGET /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.
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.