Webhooks

Telephony.io uses webhooks to send real-time event notifications to your server. When an event occurs (such as a call completing or a verification code being checked), we send an HTTP POST request to the webhook URL you've configured in your dashboard.

Supported Events

You can subscribe to the following events when configuring your webhook endpoints:

call.completed

Triggered when a voice call ends. This event includes the call duration, cost, and other metadata about the completed call.

verify.checked

Triggered when a 2FA verification code is successfully validated. This event confirms that a user has completed the verification flow.

Security

All webhook requests are signed to ensure they originate from Telephony.io. We include an X-Telephony-Signature header with every webhook request.

This signature is an HMAC-SHA256 hash of the request body, computed using your endpoint's signing secret. You must verify this signature to ensure the webhook is authentic and hasn't been tampered with.

Verifying the Signature

Here's how to verify the webhook signature in Node.js:

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-telephony-signature'];
  const body = JSON.stringify(req.body);
  
  const hash = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  
  if (hash === signature) {
    // Signature is valid - webhook is authentic
    return true;
  } else {
    // Invalid signature - reject this webhook
    return false;
  }
}

Important: Always verify the signature before processing the webhook payload. Reject any requests with invalid signatures.

Payload Structure

All webhook payloads follow a consistent structure with an event field indicating the event type, a data field containing event-specific information, and metadata fields.

call.completed Payload

{
  "event": "call.completed",
  "data": {
    "callId": "550e8400-e29b-41d4-a716-446655440000",
    "duration": 30,
    "cost": 0.05,
    "from_number": "+61412345678",
    "to_number": "+61487654321"
  },
  "timestamp": "2024-12-10T12:30:00.000Z",
  "user_id": "user_abc123"
}

verify.checked Payload

{
  "event": "verify.checked",
  "data": {
    "phone": "+61412345678",
    "status": "valid",
    "code": "123456"
  },
  "timestamp": "2024-12-10T12:30:00.000Z",
  "user_id": "user_abc123"
}

Best Practices

  • Always verify signatures: Never process a webhook without verifying the HMAC signature first
  • Respond quickly: Return a 200 OK response as soon as you receive the webhook. Process the event asynchronously if needed
  • Handle duplicates: Due to network issues, you may receive the same webhook multiple times. Use the event ID or timestamp to deduplicate
  • Secure your endpoint: Use HTTPS for your webhook URL to ensure the payload is encrypted in transit
  • Monitor delivery logs: Check the webhook delivery logs in your dashboard to debug any issues

Debugging

If your webhooks aren't being delivered:

  • Check that your endpoint is publicly accessible and returns a 2xx response
  • Verify your webhook URL is correct in the dashboard
  • Review the delivery logs in the Webhooks section of your dashboard
  • Ensure your server can handle the request within 10 seconds