Docs
Calls API

Calls API

Manage phone call webhooks and call center integrations.

The Calls API enables integration with voice communication platforms, handling webhooks from call providers and tracking call activities within your organization.

Call Webhook

Handle incoming webhooks from voice communication platforms like Retell, Vapi, or Bland AI.

POST /api/calls/webhook

Headers

HeaderRequiredDescription
X-API-KeyYesYour API key for authentication
Content-TypeYesMust be application/json
X-Webhook-SignatureNoSignature for webhook verification (provider-specific)

Request Body

The webhook payload varies by provider. Common structure:

{
  "callId": "call_abc123",
  "provider": "retell",
  "event": "call.completed",
  "from": "+14155551234",
  "to": "+14155555678",
  "duration": 180,
  "status": "completed",
  "recording_url": "https://example.com/recordings/abc123.mp3",
  "transcript": "Full conversation transcript...",
  "metadata": {
    "contactId": "contact_456def",
    "agentId": "agent_789ghi"
  },
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Webhook Events

EventDescription
call.initiatedCall has been initiated
call.ringingPhone is ringing
call.answeredCall was answered
call.completedCall has ended normally
call.failedCall failed to connect
call.recording_readyRecording is available

Response

Status Code: 200 OK

{
  "success": true,
  "message": "Webhook processed successfully",
  "callId": "call_abc123"
}

Example Request

curl -X POST "https://api.evon.com/api/calls/webhook" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "callId": "call_abc123",
    "provider": "retell",
    "event": "call.completed",
    "from": "+14155551234",
    "to": "+14155555678",
    "duration": 180,
    "status": "completed"
  }'

Supported Providers

Retell AI

Retell AI provides conversational AI for phone calls.

{
  "provider": "retell",
  "event": "call.completed",
  "call_id": "retell_call_123",
  "agent_id": "agent_retell_456",
  "call_status": "ended",
  "end_timestamp": 1705318200,
  "transcript": "...",
  "recording_url": "https://...",
  "metadata": {}
}

Vapi

Vapi enables voice AI assistants.

{
  "provider": "vapi",
  "type": "end-of-call-report",
  "call": {
    "id": "vapi_call_123",
    "status": "ended",
    "startedAt": "2025-01-15T10:30:00.000Z",
    "endedAt": "2025-01-15T10:33:00.000Z",
    "transcript": "...",
    "recordingUrl": "https://..."
  }
}

Bland AI

Bland AI provides conversational AI capabilities.

{
  "provider": "bland",
  "event_type": "call_ended",
  "call_id": "bland_call_123",
  "from": "+14155551234",
  "to": "+14155555678",
  "call_length": 180,
  "transcript": "...",
  "recording_url": "https://..."
}

Webhook Security

Signature Verification

Verify webhook signatures to ensure requests come from authorized sources:

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

Error Responses

401 Unauthorized

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}

400 Bad Request

{
  "error": "Invalid webhook payload",
  "message": "Missing required field: callId"
}

500 Internal Server Error

{
  "error": "Internal server error",
  "message": "Failed to process webhook"
}

Use Cases

Call Tracking and Analytics

Capture call data for analytics and reporting:

// Webhook endpoint receives call data
app.post('/api/calls/webhook', async (req, res) => {
  const callData = req.body;
 
  // Store call metrics
  await analytics.track('call_completed', {
    duration: callData.duration,
    outcome: callData.status,
    contactId: callData.metadata?.contactId
  });
 
  res.json({ success: true });
});

Automatic Contact Updates

Update contact records based on call outcomes:

if (callData.event === 'call.completed') {
  await updateContact(callData.metadata.contactId, {
    lastCallDate: callData.timestamp,
    callCount: { increment: 1 },
    lastCallDuration: callData.duration
  });
}

Trigger Follow-up Actions

Automate workflows based on call events:

if (callData.status === 'no-answer') {
  // Schedule follow-up call
  await scheduleCall({
    contactId: callData.metadata.contactId,
    scheduledFor: addHours(new Date(), 2)
  });
} else if (callData.status === 'completed') {
  // Send thank you email
  await sendEmail({
    to: contact.email,
    template: 'post_call_thank_you'
  });
}