Skip to Content
DocsAPI ReferenceWebhook Events

Webhook Events

Agency plan required

Webhooks let your server receive real-time notifications when call events occur. Configure a webhook URL and BuildVoiceAI will send POST requests to your endpoint whenever a call starts, completes, or fails.

Configuration

Setting Up a Webhook URL

  1. Navigate to Integrations → API & Webhooks
  2. Enter your webhook endpoint URL in the Webhook URL field
  3. Click Save
Webhook URL configuration field in API & Webhooks settings

Your endpoint must:

  • Be publicly accessible (not behind a firewall or VPN)
  • Accept POST requests with a JSON body
  • Return a 200 status code within 10 seconds
  • Use HTTPS (HTTP endpoints are not supported)

Event Types

BuildVoiceAI sends the following event types:

EventFired When
call.startedA call is initiated and the connection is established
call.completedA call ends normally
call.failedA call fails due to an error (provider issue, invalid number, etc.)

Payload Format

All webhook payloads follow this structure:

POSTyour-webhook-url

BuildVoiceAI sends this payload to your configured endpoint.

call.completed

{ "event": "call.completed", "call_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210", "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "agent_name": "Sales Qualifier", "direction": "outbound", "phone_number": "+15551234567", "duration_seconds": 185, "started_at": "2025-06-15T14:30:00Z", "ended_at": "2025-06-15T14:33:05Z", "sentiment": "positive", "summary": "Caller expressed interest in the enterprise plan and requested a follow-up demo.", "transcript": [ { "role": "agent", "content": "Hello, how can I help you today?", "timestamp": "2025-06-15T14:30:01Z" }, { "role": "human", "content": "I was wondering about your pricing.", "timestamp": "2025-06-15T14:30:05Z" } ], "metadata": { "source": "hubspot", "deal_id": "deal_12345" } }

call.started

{ "event": "call.started", "call_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210", "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "agent_name": "Sales Qualifier", "direction": "outbound", "phone_number": "+15551234567", "started_at": "2025-06-15T14:30:00Z", "metadata": {} }

call.failed

{ "event": "call.failed", "call_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210", "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "agent_name": "Sales Qualifier", "direction": "outbound", "phone_number": "+15551234567", "error": "Phone number is not reachable", "failed_at": "2025-06-15T14:30:03Z", "metadata": {} }

Signature Verification

Every webhook request includes an X-Signature header containing an HMAC-SHA256 signature. Verify this to confirm the request came from BuildVoiceAI and was not tampered with.

Verification Steps

  1. Get the raw request body (do not parse it first)
  2. Compute HMAC-SHA256 using your API key as the secret
  3. Compare the result with the X-Signature header value

Example (Node.js)

const crypto = require('crypto'); function verifyWebhookSignature(rawBody, signature, apiKey) { const expected = crypto .createHmac('sha256', apiKey) .update(rawBody) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ); }
⚠️

Always use a timing-safe comparison function to prevent timing attacks. Do not use === for signature comparison.

Retry Policy

If your webhook endpoint returns a non-2xx status code or does not respond within 10 seconds, BuildVoiceAI retries the request:

AttemptDelay
1st retry30 seconds after initial attempt
2nd retry5 minutes after 1st retry
3rd retry30 minutes after 2nd retry

After 3 failed retries, the event is dropped. Failed deliveries are logged and visible on the API & Webhooks integration page.

💡

Return a 200 response immediately and process the webhook payload asynchronously. This prevents timeouts if your processing logic takes time.

Testing Webhooks

To test your webhook integration during development:

  1. Use a service like webhook.site  or ngrok  to get a public URL
  2. Set that URL as your webhook URL in BuildVoiceAI
  3. Trigger a test call
  4. Inspect the received payload

Best Practices

  • Respond quickly — Return 200 within 10 seconds to avoid retries
  • Process asynchronously — Queue webhook payloads for background processing
  • Verify signatures — Always validate the X-Signature header in production
  • Handle duplicates — Use call_id to deduplicate in case of retries
  • Log payloads — Store raw webhook payloads for debugging
Last updated on