Skip to main content
🤖 LLM Friendly: This page is available in raw Markdown format for LLM consumption:overview.md|Get full documentation:llms.txt/llms-full.txt

Webhooks Overview

Webhooks allow your application to receive real-time HTTP notifications when events occur in your Firetell workspace.

How Webhooks Work​

  1. You register a webhook URL via the Webhooks API or the Firetell Console
  2. When an event occurs, Firetell sends an HTTP POST request to your URL
  3. Your server processes the event and responds with a 200 status code

Webhook Payload Format​

All webhook payloads follow a standard envelope structure:

{
"event": "call.ended",
"data": {
"workspace_id": "yourcompany",
"occurred_at": "2026-07-24T00:56:02.000Z",
"attempt": 1,
"call_id": "call_abc789",
"direction": "inbound",
"status": "completed",
"type": "audio",
"from": {
"name": "+84901234567",
"number": "+84901234567"
},
"to": {
"name": "+84909876543",
"number": "+84909876543"
},
"started_at": "2026-07-24T00:55:00.000Z",
"answered_at": "2026-07-24T00:55:02.000Z",
"ended_at": "2026-07-24T00:56:02.000Z",
"duration": 62,
"billsec": 60,
"cost": 0.0517,
"hangup_cause": "NORMAL_CLEARING"
}
}

Event Payload Examples​

call.created​

{
"event": "call.created",
"data": {
"workspace_id": "yourcompany",
"occurred_at": "2026-07-24T00:55:00.000Z",
"attempt": 1,
"call_id": "call_abc789",
"direction": "inbound",
"status": "started",
"type": "audio",
"from": { "name": "+84901234567", "number": "+84901234567" },
"to": { "name": "+84909876543", "number": "+84909876543" },
"started_at": "2026-07-24T00:55:00.000Z",
"answered_at": null,
"ended_at": null,
"duration": 0,
"billsec": 0,
"cost": 0,
"hangup_cause": null
}
}

call.recording.ready​

{
"event": "call.recording.ready",
"data": {
"workspace_id": "yourcompany",
"occurred_at": "2026-07-24T00:56:05.000Z",
"attempt": 1,
"recording_id": "rec_call_abc789",
"call_id": "call_abc789",
"url": "https://storage.firetell.app/workspaces/yourcompany/recordings/call_abc789.mp3",
"duration": 60,
"size_bytes": 1440000,
"format": "mp3",
"created_at": "2026-07-24T00:56:05.000Z"
}
}

call.transcription.completed​

{
"event": "call.transcription.completed",
"data": {
"workspace_id": "yourcompany",
"occurred_at": "2026-07-24T00:56:06.000Z",
"attempt": 1,
"call_id": "call_abc789",
"dialogues": [
{
"id": "diag_01h900000000000000000001",
"speaker": "caller",
"channel_index": 0,
"text": "Hello, I would like to check my order status for #FT10294.",
"confidence": 0.98,
"duration_ms": 3200,
"timestamp": "2026-07-24T00:55:10.000Z"
},
{
"id": "diag_01h900000000000000000002",
"speaker": "agent",
"channel_index": 1,
"text": "Certainly! I have retrieved order #FT10294 for Alex Rivera. It is scheduled for delivery today with Express Courier.",
"confidence": 0.99,
"duration_ms": 5400,
"timestamp": "2026-07-24T00:55:20.000Z"
}
],
"entities": [
{
"type": "order_id",
"value": "#FT10294",
"confidence": 0.99
},
{
"type": "customer_name",
"value": "Alex Rivera",
"confidence": 0.98
},
{
"type": "carrier",
"value": "Express Courier",
"confidence": 0.97
}
],
"total_dialogues": 2,
"completed_at": "2026-07-24T00:56:06.000Z"
}
}

call.transcription.summary​

{
"event": "call.transcription.summary",
"workspace_id": "yourcompany",
"timestamp": "2026-07-24T00:56:12.000Z",
"data": {
"transcription_id": "trans_01h900000000000000000001",
"call_id": "call_abc789",
"workspace_id": "yourcompany",
"summary": "Customer inquired about enterprise cloud contact center solutions and pricing.",
"sentiment": "positive",
"action_items": [
"Send Enterprise pricing sheet to customer",
"Schedule live product demo"
],
"language": "en"
}
}

message.delivered​

{
"event": "message.delivered",
"workspace_id": "yourcompany",
"timestamp": "2026-09-26T00:00:05.000Z",
"attempt": 1,
"data": {
"id": "msg_05f18045cba1452204774f",
"phone_number_id": "pn_e71c8caddbe5603f1d0522",
"direction": "outbound",
"from": "+13074295456",
"to": "+18647123123",
"body": "Hello from Firetell",
"status": "delivered",
"error_code": null,
"error_message": null,
"created_at": "2026-09-26T00:00:00.000Z",
"updated_at": "2026-09-26T00:00:05.000Z"
}
}

Event Types​

EventDescription
call.createdA new call has been initiated
call.answeredA call was answered by an agent or user
call.endedA call has ended
call.recording.readyA call recording audio file has finished processing, uploaded, and is ready for playback/download
call.transcription.completedReal-time call transcription and Named Entity Recognition (NER) completed
call.transcription.summaryAI post-call executive summary, customer sentiment analysis, and action items
contact.createdA new contact was created in the workspace
contact.updatedAn existing contact was updated
contact.deletedA contact was deleted
agent.stateAn agent's presence state was changed (available, busy, away, offline)
agent.createdA new workspace agent account was created
agent.updatedAn existing workspace agent account was updated
agent.deletedA workspace agent account was deleted
workspace.credit.updatedWorkspace credit balance was updated (e.g. call charge deduction, top-up)
message.receivedAn inbound SMS/MMS message was received
message.sentAn outbound SMS/MMS message was accepted by the carrier and sent
message.deliveredAn outbound SMS/MMS message was confirmed delivered to recipient
message.failedAn outbound SMS/MMS message failed to send or deliver
message.undeliveredAn outbound SMS/MMS message could not be confirmed delivered

Retry Policy​

If your endpoint returns a non-2xx status code or times out (30 seconds), Firetell will retry the delivery:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours

After 4 failed retries, the webhook is marked as failed and no further attempts are made.

Security​

Validate incoming webhooks by checking the X-Webhook-Signature header. This header contains an HMAC-SHA256 signature of the JSON request body, signed with your webhook secret (prefixed with whse-).

const crypto = require('crypto');

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

// Usage in an Express handler:
app.post('/webhooks/firetell', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifySignature(
JSON.stringify(req.body),
signature,
'whse-your-webhook-secret'
);

if (!isValid) return res.status(401).send('Invalid signature');

// Process event...
res.status(200).send('OK');
});

Best Practices​

  • Respond quickly — Return 200 immediately and process asynchronously
  • Handle duplicates — Use the event ID for idempotency
  • Use HTTPS — Always use HTTPS endpoints in production
  • Validate signatures — Verify the X-Webhook-Signature header