Documentation Index
Fetch the complete documentation index at: https://docs.threetone.in/llms.txt
Use this file to discover all available pages before exploring further.
Webhook Overview
Webhooks enable real-time communication between ThreeTone and your applications by sending HTTP POST requests to your specified endpoints when events occur.
Supported Events
- Call Events: call_started, call_ended, call_transferred
- Agent Events: agent_available, agent_busy, agent_offline
- Conversation Events: conversation_started, conversation_ended, escalation_triggered
- System Events: system_error, maintenance_scheduled, quota_exceeded
Webhook Configuration
Creating Webhooks
Set up webhook endpoints for event notifications:
curl --request POST \
--url https://api.threetone.com/v1/voiceai/webhooks \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://your-api.com/webhooks/threetone",
"events": [
"call_started",
"call_ended",
"conversation_ended",
"escalation_triggered"
],
"secret": "your_webhook_secret_key",
"active": true,
"retry_config": {
"max_retries": 3,
"retry_delay": 5
}
}'
Webhook Management
List and manage existing webhooks:
# List all webhooks
curl --request GET \
--url https://api.threetone.com/v1/voiceai/webhooks \
--header 'x-api-key: YOUR_API_KEY'
# Update webhook configuration
curl --request PUT \
--url https://api.threetone.com/v1/voiceai/webhooks/{webhook_id} \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"events": ["call_started", "call_ended"],
"active": true
}'
# Delete webhook
curl --request DELETE \
--url https://api.threetone.com/v1/voiceai/webhooks/{webhook_id} \
--header 'x-api-key: YOUR_API_KEY'
Event Payloads
Call Started Event
Triggered when a new call begins:
{
"event": "call_started",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"call_id": "call_abc123",
"phone_number": "+1234567890",
"caller_id": "+1987654321",
"agent_id": "agent_456",
"direction": "inbound",
"call_source": "phone_system",
"metadata": {
"caller_location": "New York, NY",
"call_queue": "support_queue"
}
}
}
Call Ended Event
Triggered when a call completes:
{
"event": "call_ended",
"timestamp": "2024-01-15T10:35:00Z",
"data": {
"call_id": "call_abc123",
"duration_seconds": 300,
"end_reason": "completed",
"resolution_status": "resolved",
"conversation_summary": "Customer inquiry about billing resolved successfully",
"satisfaction_score": 4.5,
"transcript_available": true,
"recording_available": true
}
}
Conversation Events
Track conversation lifecycle:
{
"event": "conversation_ended",
"timestamp": "2024-01-15T10:35:00Z",
"data": {
"conversation_id": "conv_xyz789",
"call_id": "call_abc123",
"agent_id": "agent_456",
"turn_count": 15,
"topics_discussed": ["billing", "account_settings"],
"sentiment_analysis": {
"overall_sentiment": "positive",
"sentiment_score": 0.7
},
"knowledge_base_queries": 3,
"escalation_occurred": false
}
}
Escalation Events
Monitor when calls are escalated:
{
"event": "escalation_triggered",
"timestamp": "2024-01-15T10:32:00Z",
"data": {
"call_id": "call_abc123",
"conversation_id": "conv_xyz789",
"escalation_reason": "customer_requested_human",
"escalation_trigger": "keyword_detected",
"agent_id": "agent_456",
"target_queue": "human_agents",
"context_summary": "Customer needs help with complex billing issue",
"conversation_history": "Available via API"
}
}
Webhook Security
Signature Verification
Verify webhook authenticity using HMAC signatures:
import hmac
import hashlib
def verify_webhook_signature(payload, signature, secret):
"""Verify webhook signature for security"""
expected_signature = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(
f"sha256={expected_signature}",
signature
)
# Usage in your webhook handler
def handle_webhook(request):
signature = request.headers.get('X-ThreeTone-Signature')
payload = request.body
if verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
# Process webhook safely
process_webhook_event(payload)
else:
# Reject invalid webhook
return {"error": "Invalid signature"}, 401
Best Practices
- HTTPS Only: Always use HTTPS endpoints for webhooks
- Signature Verification: Verify all incoming webhooks
- Idempotency: Handle duplicate events gracefully
- Error Handling: Implement proper error responses
- Rate Limiting: Protect against webhook flooding
Webhook Implementation Examples
Node.js Express Handler
const express = require("express");
const crypto = require("crypto");
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/threetone", (req, res) => {
const signature = req.headers["x-threetone-signature"];
const payload = req.body;
// Verify signature
const expectedSignature = crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(payload)
.digest("hex");
if (`sha256=${expectedSignature}` !== signature) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(payload);
// Handle different event types
switch (event.event) {
case "call_started":
handleCallStarted(event.data);
break;
case "call_ended":
handleCallEnded(event.data);
break;
case "escalation_triggered":
handleEscalation(event.data);
break;
}
res.status(200).send("OK");
});
Python Flask Handler
from flask import Flask, request, jsonify
import hmac
import hashlib
import json
app = Flask(__name__)
@app.route('/webhooks/threetone', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-ThreeTone-Signature')
payload = request.get_data()
# Verify signature
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if f"sha256={expected_signature}" != signature:
return jsonify({"error": "Invalid signature"}), 401
event = json.loads(payload)
# Process event
if event['event'] == 'call_started':
process_call_started(event['data'])
elif event['event'] == 'call_ended':
process_call_ended(event['data'])
return jsonify({"status": "success"}), 200
Webhook Testing
Test Webhook Delivery
Test webhook endpoints during development:
curl --request POST \
--url https://api.threetone.com/v1/voiceai/webhooks/{webhook_id}/test \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"event_type": "call_started"
}'
Webhook Logs
Monitor webhook delivery status:
curl --request GET \
--url https://api.threetone.com/v1/voiceai/webhooks/{webhook_id}/logs \
--header 'x-api-key: YOUR_API_KEY'
Response example:
{
"webhook_id": "webhook_123",
"recent_deliveries": [
{
"timestamp": "2024-01-15T10:30:00Z",
"event": "call_started",
"status": "success",
"response_code": 200,
"delivery_time_ms": 150
},
{
"timestamp": "2024-01-15T10:25:00Z",
"event": "call_ended",
"status": "failed",
"response_code": 500,
"retry_count": 2,
"error": "Connection timeout"
}
]
}
Error Handling and Retries
Retry Configuration
Configure automatic retry behavior:
{
"retry_config": {
"max_retries": 5,
"retry_delay": 5,
"exponential_backoff": true,
"max_delay": 300,
"retry_on_status": [500, 502, 503, 504]
}
}
Handling Failed Webhooks
Implement proper error handling:
def handle_webhook_failure(webhook_data, error):
"""Handle failed webhook deliveries"""
# Log the failure
logger.error(f"Webhook delivery failed: {error}")
# Store for manual processing if needed
store_failed_webhook(webhook_data)
# Alert monitoring systems
send_alert("webhook_failure", {
"webhook_id": webhook_data.get("webhook_id"),
"error": str(error)
})
Monitoring and Debugging
Webhook Health Monitoring
Monitor webhook endpoint health:
curl --request GET \
--url https://api.threetone.com/v1/voiceai/webhooks/health \
--header 'x-api-key: YOUR_API_KEY'
Access detailed webhook debug information for troubleshooting delivery issues and payload validation.
Next Steps