Webhook Events
Webhook targets receive only the events they subscribe to.
| Event | Trigger | Typical use |
|---|---|---|
call.completed | Call connected and ended successfully. | Save transcript, structured results, duration, and recording URL. |
call.failed | Call failed during setup or could not connect. | Alert, debug, or mark the attempt failed. |
call.busy | Recipient line was busy. | Update CRM status and wait for retry policy. |
call.no_answer | Recipient did not answer. | Schedule follow-up or wait for retry. |
call.socket_failure | Call connected at telephony layer but voice streaming did not start. | Investigate voice streaming or provider issues. |
call.telephony_failed | Telephony provider failed after call initiation. | Alert operations and reconcile provider status. |
call.unreachable | Destination number could not be reached. | Mark number invalid/unreachable or request a new contact. |
Event fields
Every event uses the same top-level envelope:
| Field | Type | Description |
|---|---|---|
event_id | string | Unique ID for this webhook delivery. Use for dedupe. |
event_type | string | One of the event types above. |
timestamp | string | ISO 8601 timestamp when FormantAI created the event. |
data | object | Event-specific payload. |
Event handling pattern
1 app.post("/webhooks/formant", async (req, res) => { 2 const event = req.body; 3 4 await saveEventOnce(event.event_id, event); 5 6 switch (event.event_type) { 7 case "call.completed": 8 await handleCompletedCall(event.data); 9 break; 10 case "call.no_answer": 11 case "call.busy": 12 await markRetryableAttempt(event.data); 13 break; 14 default: 15 await logCallOutcome(event.data); 16 } 17 18 res.status(204).send(); 19 });