Skip to main content

Overview

Webhooks allow you to receive real-time HTTP notifications when specific events occur in your 60db account. This enables you to build event-driven workflows and integrations.

How Webhooks Work

1

Create Webhook

Register a webhook URL and select events to monitor
2

Event Occurs

When a subscribed event happens, 60db sends a POST request
3

Process Event

Your server receives and processes the webhook payload
4

Respond

Return a 200 OK response to acknowledge receipt

Available Events

Text-to-Speech

  • tts.completed - TTS generation completed successfully
  • tts.failed - TTS generation failed

Speech-to-Text

  • stt.completed - STT transcription completed
  • stt.failed - STT transcription failed

Custom Voices

  • voice.created - Custom voice creation started
  • voice.ready - Custom voice is ready to use
  • voice.failed - Custom voice creation failed

Creating a Webhook

const webhook = await client.createWebhook({
  url: 'https://example.com/webhook',
  events: ['tts.completed', 'voice.ready'],
  secret: 'your-webhook-secret'
});

console.log('Webhook ID:', webhook.id);

Webhook Payload

When an event occurs, we send a POST request with this structure:
{
  "event": "tts.completed",
  "timestamp": "2026-01-29T11:35:00Z",
  "webhook_id": "wh-123",
  "data": {
    "id": "tts-456",
    "text": "Hello, world!",
    "voice_id": "default-voice",
    "audio_url": "https://cdn.60db.com/audio/tts-456.mp3",
    "duration": 2.5,
    "characters": 13
  }
}

Handling Webhooks

Express.js Example

const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

app.post('/webhook', (req, res) => {
  // Verify webhook signature
  const signature = req.headers['x-60db-signature'];
  const isValid = verifySignature(req.body, signature);
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  const { event, data } = req.body;
  
  switch (event) {
    case 'tts.completed':
      console.log('TTS completed:', data.id);
      // Handle TTS completion
      break;
    
    case 'voice.ready':
      console.log('Voice ready:', data.id);
      // Handle voice ready
      break;
  }

  // Acknowledge receipt
  res.status(200).send('OK');
});

function verifySignature(payload, signature) {
  const secret = process.env.WEBHOOK_SECRET;
  const hash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return hash === signature;
}

app.listen(3000);

Flask Example

from flask import Flask, request, jsonify
import hmac
import hashlib
import json

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    # Verify webhook signature
    signature = request.headers.get('X-60db-Signature')
    if not verify_signature(request.data, signature):
        return 'Invalid signature', 401

    # Process the event
    payload = request.json
    event = payload['event']
    data = payload['data']

    if event == 'tts.completed':
        print(f"TTS completed: {data['id']}")
        # Handle TTS completion
    
    elif event == 'voice.ready':
        print(f"Voice ready: {data['id']}")
        # Handle voice ready

    # Acknowledge receipt
    return 'OK', 200

def verify_signature(payload, signature):
    secret = os.getenv('WEBHOOK_SECRET')
    hash_obj = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    )
    return hash_obj.hexdigest() == signature

if __name__ == '__main__':
    app.run(port=3000)

Security

Signature Verification

Always verify webhook signatures to ensure requests are from 60db:
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(signature)
  );
}

HTTPS Required

Webhook URLs must use HTTPS for security.

IP Whitelisting

Optionally whitelist 60db IP addresses:
  • 52.89.214.238
  • 34.212.75.30
  • 54.218.53.128

Best Practices

  • Return 200 OK immediately
  • Process events asynchronously
  • Don’t wait for long operations
  • We retry failed webhooks up to 3 times
  • Implement idempotency to handle duplicates
  • Use event IDs to track processed events
  • Log all webhook events
  • Monitor webhook failures
  • Set up alerts for repeated failures
  • Test with ngrok or similar tools during development
  • Verify signature validation works
  • Test all event types you subscribe to

Monitoring

Track webhook health in your dashboard:
  • Delivery Rate: Percentage of successful deliveries
  • Response Time: Average response time
  • Error Rate: Failed webhook deliveries
  • Recent Events: Last 100 webhook events

API Reference