Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.voicy.co/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Webhooks allow you to receive HTTP POST notifications when events occur in your Voicy account. When a call ends, Voicy sends the full call data — transcript, summary, extracted variables, and more — to your server in real time. Each agent supports up to 5 webhooks, all firing in parallel. Use them to push call data to your CRM, analytics platform, or any custom integration.

Creating a Webhook

1

Open Agent Settings

In the Voicy Dashboard, navigate to your agent and open the Settings tab. Scroll down to the Webhooks section and expand it.
2

Add a Webhook

Click the + button to add a new webhook. Fill in the fields:
FieldRequiredDescription
NameYesA label to identify this webhook (e.g. “CRM”, “Analytics”, “Slack”)
URLYesThe HTTPS endpoint that will receive POST requests
Signing SecretNoA secret string for HMAC-SHA256 signature verification
Click Add to save.
3

Deploy the Agent

Webhooks are part of the agent configuration. After adding or modifying webhooks, deploy the agent for changes to take effect on phone calls.
Changes take effect immediately for web (test) calls, but phone calls use the deployed version.
4

Test It

Make a test call from the dashboard’s built-in call simulator. When the call ends, your endpoint will receive a POST request with the full call payload.
Use a service like webhook.site to inspect payloads during development.

Managing Webhooks

  • Edit — Click the pencil icon on any webhook to change its name, URL, or secret. Leave the secret field blank to keep the existing secret.
  • Delete — Click the trash icon to remove a webhook.
  • Limit — Up to 5 webhooks per agent. The badge shows your current count (e.g. “2/5”).

Events

call_ended

Fired after all post-call processing completes (summary generation, variable extraction, email notifications). The payload contains the full call data in the same format as the Get Call API. Headers:
HeaderDescription
Content-Typeapplication/json
x-voicy-eventEvent name (call_ended)
x-voicy-signatureHMAC-SHA256 signature (only if signing secret is configured)
Payload:
{
  "event": "call_ended",
  "call": {
    "call_id": "550e8400-e29b-41d4-a716-446655440000",
    "call_type": "phone_call",
    "call_status": "user_hangup",
    "agent": {
      "id": "agent-uuid",
      "name": "My Agent",
      "version": 3
    },
    "from_number": "+972501234567",
    "to_number": "+972521234567",
    "direction": "incoming",
    "start_timestamp": 1710000000000,
    "duration_ms": 45000,
    "transcript": [
      { "role": "agent", "content": "שלום, איך אוכל לעזור?" },
      { "role": "user", "content": "אני צריך עזרה" }
    ],
    "summary": "הלקוח ביקש עזרה בנושא...",
    "vars_provided": { "from_number": "+972501234567" },
    "vars_extracted": { "customer_name": "משה" },
    "vars_collected": { "email": "user@example.com" },
    "call_cost": { "combined_cost": 0.0234, "currency": "usd" }
  }
}

Handling Webhooks

When your server receives a webhook, respond with a 200 status code to acknowledge receipt. Here’s a minimal handler:
const express = require('express');
const app = express();

app.post('/voicy-webhook', express.json(), (req, res) => {
  const { event, call } = req.body;

  console.log(`Event: ${event}`);
  console.log(`Call ID: ${call.call_id}`);
  console.log(`Status: ${call.call_status}`);
  console.log(`Duration: ${call.duration_ms}ms`);

  if (call.summary) {
    console.log(`Summary: ${call.summary}`);
  }

  if (call.vars_extracted) {
    console.log('Extracted vars:', call.vars_extracted);
  }

  res.status(200).send('OK');
});

app.listen(3000);

Signature Verification

If a signing secret is configured, each webhook request includes an x-voicy-signature header containing an HMAC-SHA256 signature of the raw request body. Always verify signatures in production to ensure requests are genuinely from Voicy.
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express middleware
app.post('/voicy-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-voicy-signature'];
  if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  console.log('Call ended:', event.call.call_id);
  res.status(200).send('OK');
});

Behavior

PropertyValue
MethodPOST
Timeout5 seconds
RetriesNone (fire-and-forget)
Content-Typeapplication/json
ParallelAll agent webhooks fire simultaneously
If a webhook endpoint is unreachable or returns an error, the failure is logged but does not affect call processing or other webhooks.