API Reference
Webhooks
Receive real-time notifications when events occur in your workspace.
Webhooks allow your application to receive real-time notifications when events occur in Flametalk. Instead of polling the API, webhooks push data to your endpoint as events happen.
Webhook Events
call.started— Call has been initiatedcall.completed— Call has ended with transcriptcall.failed— Call failed or was not answeredappointment.booked— Agent booked an appointmentcampaign.enrollment.completed— Contact finished campaign workflowConfiguration
Configure webhook endpoints from your campaign settings. Each campaign can have its own webhook URL.
- 1
Navigate to Campaign Settings
Open your campaign and go to the Integrations tab.
- 2
Add Webhook URL
Enter your HTTPS endpoint URL where you want to receive events.
- 3
Copy Signing Secret
Copy the webhook secret to verify incoming requests.
HTTPS Required
Webhook endpoints must use HTTPS. HTTP endpoints will not receive events.
Payload Format
All webhook payloads follow a consistent structure:
{ "id": "evt_abc123", "type": "call.completed", "created_at": "2024-01-25T14:35:30Z", "data": { "call_id": "call_xyz789", "direction": "inbound", "from_number": "+14155551234", "to_number": "+18005550100", "duration_seconds": 330, "status": "completed", "call_outcome": "appointment_booked", "transcript": "Agent: Hello, thank you for calling...", "transcript_summary": "Customer requested a demo...", "metadata": { "campaign_id": "camp_def456", "contact_id": "contact_ghi789" } }}Event Types
call.completed
Sent when a call ends successfully. Includes full transcript and outcome.
{ "id": "evt_abc123", "type": "call.completed", "created_at": "2024-01-25T14:35:30Z", "data": { "call_id": "call_xyz789", "direction": "inbound", "from_number": "+14155551234", "to_number": "+18005550100", "started_at": "2024-01-25T14:30:00Z", "ended_at": "2024-01-25T14:35:30Z", "duration_seconds": 330, "status": "completed", "call_outcome": "appointment_booked", "agent_name": "Sales Agent", "channel_name": "Main Line", "transcript": "Agent: Hello, thank you for calling...", "transcript_summary": "Customer called to schedule a demo...", "recording_url": "https://storage.flametalk.ai/recordings/...", "metadata": { "campaign_id": "camp_def456", "contact_id": "contact_ghi789" } }}call.failed
Sent when a call fails, is not answered, or encounters an error.
{ "id": "evt_def456", "type": "call.failed", "created_at": "2024-01-25T14:31:00Z", "data": { "call_id": "call_abc123", "direction": "outbound", "from_number": "+18005550100", "to_number": "+14155559999", "started_at": "2024-01-25T14:30:00Z", "ended_at": "2024-01-25T14:31:00Z", "status": "no-answer", "failure_reason": "no-answer", "error_message": null, "metadata": { "campaign_id": "camp_def456", "contact_id": "contact_xyz123" } }}appointment.booked
Sent when an agent successfully books an appointment via Cal.com integration.
{ "id": "evt_ghi789", "type": "appointment.booked", "created_at": "2024-01-25T14:33:00Z", "data": { "call_id": "call_xyz789", "appointment": { "id": "apt_123456", "title": "Product Demo", "start_time": "2024-01-30T14:00:00Z", "end_time": "2024-01-30T15:00:00Z", "attendee_email": "customer@example.com", "attendee_name": "John Doe" }, "contact_id": "contact_ghi789", "agent_name": "Sales Agent" }}Signature Verification
Every webhook request includes a signature header to verify authenticity. Always verify signatures before processing webhook data.
Headers
| Header | Description |
|---|---|
| X-Flametalk-Signature | HMAC-SHA256 signature of the request body |
| X-Flametalk-Timestamp | Unix timestamp when the webhook was sent |
Verification Example
const crypto = require('crypto'); function verifyWebhook(payload, signature, timestamp, secret) { // Reject if timestamp is too old (5 minutes) const now = Math.floor(Date.now() / 1000); if (now - parseInt(timestamp) > 300) { return false; } // Compute expected signature const signedPayload = `${timestamp}.${payload}`; const expectedSignature = crypto .createHmac('sha256', secret) .update(signedPayload) .digest('hex'); // Compare signatures return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) );} // Express.js exampleapp.post('/webhooks/flametalk', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-flametalk-signature']; const timestamp = req.headers['x-flametalk-timestamp']; const payload = req.body.toString(); if (!verifyWebhook(payload, signature, timestamp, WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(payload); console.log('Received event:', event.type); // Process the event... res.status(200).send('OK');});Best Practices
Respond Quickly
Return a 2xx response within 5 seconds. Process events asynchronously if needed to avoid timeouts.
Handle Duplicates
Webhooks may be sent multiple times. Use the event id to deduplicate.
Verify Signatures
Always verify the webhook signature before processing to prevent spoofed requests.
Use Idempotent Operations
Design your handlers so processing the same event twice has no adverse effects.
Retry Policy
If your endpoint returns a non-2xx status code or times out, we'll retry the webhook with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
After 4 failed attempts, the webhook is marked as failed and no further retries are attempted.