Skip to main content

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
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:
cURL
# 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
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
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
curl --request GET \
  --url https://api.threetone.com/v1/voiceai/webhooks/health \
  --header 'x-api-key: YOUR_API_KEY'

Debug Information

Access detailed webhook debug information for troubleshooting delivery issues and payload validation.

Next Steps