Tutorial¶
Prerequisites¶
Before configuring webhooks, you need:
An authentication token. Obtain one via
POST /auth/loginor use an access key fromGET /accesskeys.A publicly accessible HTTPS endpoint URL where VoIPBIN will send event notifications.
Knowledge of which event types you want to receive (e.g.,
call_created,message_created). See Webhook Structure for the full list.
Note
AI Implementation Hint
Webhooks are configured at the customer account level, not as separate resources. Use PUT https://api.voipbin.net/v1.0/customer to set the webhook_uri and webhook_method fields on your customer profile. There is no /webhooks CRUD endpoint. Your webhook endpoint must be publicly reachable from the internet and respond with HTTP 200 within 5 seconds. For local development, use tools like ngrok to expose a local server.
Configure Webhook Endpoint¶
Set your webhook delivery URL and HTTP method by updating your customer profile. VoIPBIN will send all event notifications to this URL.
$ curl --location --request PUT 'https://api.voipbin.net/v1.0/customer?token=<YOUR_AUTH_TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
"webhook_uri": "https://your-server.com/voipbin/webhook",
"webhook_method": "POST"
}'
Note
AI Implementation Hint
The webhook_method field accepts one of: POST, PUT, GET, DELETE. Most implementations use POST. The webhook_uri should be a valid HTTPS URL for production use. To verify your current webhook configuration, call GET https://api.voipbin.net/v1.0/customer and check the webhook_uri and webhook_method fields in the response.
Verify Webhook Configuration¶
Retrieve your current customer profile to confirm the webhook settings.
$ curl --location --request GET 'https://api.voipbin.net/v1.0/customer?token=<YOUR_AUTH_TOKEN>'
Check the webhook_uri and webhook_method fields in the response to verify your configuration.
Disable Webhooks¶
To stop receiving webhook notifications, set the webhook_uri to an empty string.
$ curl --location --request PUT 'https://api.voipbin.net/v1.0/customer?token=<YOUR_AUTH_TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
"webhook_uri": "",
"webhook_method": ""
}'
Webhook Event Types¶
VoIPBIN sends different event types to your webhook endpoint. For the complete list, see Webhook Structure.
Call Events:
call_created- Call initiatedcall_ringing- Call is ringingcall_answered- Call was answeredcall_updated- Call status changedcall_hungup- Call ended
Message Events:
message_created- Message createdmessage_updated- Message status changedmessage_deleted- Message deleted
Recording Events:
recording_created- Recording startedrecording_updated- Recording status changedrecording_deleted- Recording deleted
Transcription Events:
transcribe_created- Transcription startedtranscribe_updated- Transcription progress updatetranscribe_deleted- Transcription deletedtranscript_created- Transcript segment created
Queue Events:
queue_created- Queue createdqueue_updated- Queue updatedqueuecall_created- Call joined queuequeuecall_kicking- Agent assigned to queue callqueuecall_serviced- Queue call being handled
Conference Events:
conference_created- Conference createdconference_updated- Conference updatedconfbridge_created- Conference bridge createdconfbridge_updated- Participant joined/left
Activeflow Events:
activeflow_created- Flow execution startedactiveflow_updated- Flow execution progressedactiveflow_deleted- Flow execution ended
Receiving Webhook Events¶
Your webhook endpoint should accept POST requests and process the JSON payload. Here’s an example webhook server implementation:
Python (Flask) Example:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/voipbin/webhook', methods=['POST'])
def voipbin_webhook():
# Get the webhook payload
payload = request.get_json()
# Process different event types
event_type = payload.get('type')
if event_type == 'call_hungup':
call_id = payload['data']['id']
status = payload['data']['hangup_reason']
print(f"Call {call_id} ended: {status}")
# Your business logic here
# - Update CRM
# - Send notifications
# - Trigger workflows
elif event_type == 'message_created':
message_id = payload['data']['id']
from_number = payload['data']['source']['target']
text = payload['data']['text']
print(f"Message from {from_number}: {text}")
# Process the message
# - Auto-reply
# - Route to agent
# - Store in database
elif event_type == 'recording_updated':
recording_id = payload['data']['id']
status = payload['data']['status']
print(f"Recording {recording_id} status: {status}")
# Handle recording
# - Download and store
# - Transcribe
# - Send to customer
# Return 200 OK to acknowledge receipt
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Node.js (Express) Example:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/voipbin/webhook', (req, res) => {
const payload = req.body;
const eventType = payload.type;
console.log(`Received event: ${eventType}`);
switch(eventType) {
case 'call_hungup':
handleCallHungup(payload.data);
break;
case 'message_created':
handleMessageCreated(payload.data);
break;
case 'recording_updated':
handleRecordingUpdated(payload.data);
break;
default:
console.log(`Unknown event type: ${eventType}`);
}
// Acknowledge receipt
res.status(200).json({ status: 'received' });
});
function handleCallHungup(data) {
console.log(`Call ${data.id} ended`);
// Your logic here
}
function handleMessageCreated(data) {
console.log(`Message from ${data.source.target}: ${data.text}`);
// Your logic here
}
function handleRecordingUpdated(data) {
console.log(`Recording ${data.id} status: ${data.status}`);
// Your logic here
}
app.listen(5000, () => {
console.log('Webhook server listening on port 5000');
});
Testing Webhooks¶
Local Development:
Use tools like ngrok to expose your local server for testing:
# Install ngrok
$ brew install ngrok # macOS
$ snap install ngrok # Linux
# Start your webhook server locally
$ python webhook_server.py
# Expose it via ngrok
$ ngrok http 5000
# Use the ngrok URL in your webhook configuration
# Example: https://abc123.ngrok.io/voipbin/webhook
Testing with curl:
Simulate a webhook event to test your endpoint:
$ curl --location --request POST 'http://localhost:5000/voipbin/webhook' \
--header 'Content-Type: application/json' \
--data-raw '{
"type": "call_hungup",
"data": {
"id": "test-call-id",
"hangup_reason": "normal",
"source": {
"type": "tel",
"target": "+15551234567"
},
"destination": {
"type": "tel",
"target": "+15559876543"
}
}
}'
Webhook Payload Structure¶
All webhook events follow this structure:
{
"type": "call_hungup",
"data": {
// Event-specific data
// Structure varies by event type
}
}
Fields:
type: Type of event that occurred (e.g.,call_hungup,message_created)data: Event-specific data (varies by event type). See Webhook Structure for details.
Best Practices¶
1. Acknowledge Quickly: - Return 200 OK immediately upon receiving the webhook - Process time-consuming tasks asynchronously (queue jobs, background workers) - VoIPBIN expects a response within 5 seconds
2. Handle Duplicates: - Webhooks may be delivered more than once - Use the event ID or timestamp to detect and ignore duplicates - Implement idempotent processing
3. Secure Your Endpoint: - Use HTTPS for production webhooks - Validate webhook authenticity (check source IP, use signatures) - Implement rate limiting to prevent abuse
4. Error Handling: - Log all webhook events for debugging - Return appropriate HTTP status codes - Implement retry logic for failed processing
5. Event Filtering:
- Filter events in your webhook handler based on the type field
- Process only events relevant to your application
6. Monitoring: - Track webhook delivery success/failure rates - Set up alerts for high failure rates - Monitor webhook processing times
Common Use Cases¶
CRM Integration: Automatically update your CRM when calls end:
if event_type == 'call_hungup':
call_data = payload['data']
# Update CRM contact record
crm.update_contact(
phone=call_data['destination']['target'],
last_call_date=call_data['tm_hangup'],
hangup_reason=call_data['hangup_reason']
)
Auto-Reply to Messages: Respond automatically to incoming messages:
if event_type == 'message_created':
message = payload['data']
from_number = message['source']['target']
# Send auto-reply
voipbin_api.send_message(
to=from_number,
text="Thanks for your message! We'll respond soon."
)
Recording Distribution: Email recordings to stakeholders when ready:
if event_type == 'recording_updated':
recording = payload['data']
if recording['status'] == 'ended':
# Send email with recording info
email.send(
to='[email protected]',
subject='Call Recording Available',
body=f'Recording ID: {recording["id"]}'
)
For more information about webhook configuration and event types, see Webhook Overview.