Webhooks let your systems receive real-time notifications when call events occur in your DialNexa workspace. Instead of polling the API for call status, you register an endpoint and DialNexa delivers events to it as they happen.
Webhooks are workspace-level subscriptions. A single webhook endpoint can receive events from all agents and phone numbers in the workspace, or you can configure per-agent filtering.
Access webhook configuration at Settings > Webhooks.
Available events
| Event | Fired when |
|---|
call.started | A call connects and the session begins |
call.ended | A call terminates (for any reason, including caller hangup, agent hangup, or timeout) |
call.transcript_ready | The full call transcript is available (typically seconds after call.ended) |
call.analysis_ready | Post-call analysis extraction is complete (available when PCA is configured on the agent) |
call.function_error | A function/tool call during the call returned an error |
alert.triggered | An alert threshold was crossed (if alert webhook delivery is configured) |
Registering a webhook
Open Webhook settings
Go to Settings > Webhooks and click Add Endpoint.
Enter the endpoint URL
Enter the HTTPS URL that will receive events. The URL must be publicly accessible. DialNexa does not support localhost or private network endpoints.
Select events
Choose which events to subscribe to. Only selected events are delivered to this endpoint. You can create multiple endpoints with different event subscriptions.
Save
Click Save. DialNexa sends a test ping event to verify the endpoint is reachable. Your endpoint must return a 2xx status code within 5 seconds.
Payload structure
All webhook payloads are JSON. Common fields present in every event:
{
"event": "call.ended",
"workspace_id": "ws_xxxxxxxx",
"session_id": "sess_xxxxxxxx",
"agent_id": "agent_xxxxxxxx",
"phone_number": "+15550001234",
"timestamp": "2024-03-15T14:32:00Z"
}
call.started
{
"event": "call.started",
"workspace_id": "ws_xxxxxxxx",
"session_id": "sess_xxxxxxxx",
"agent_id": "agent_xxxxxxxx",
"direction": "inbound",
"caller_number": "+15550001234",
"called_number": "+15550009876",
"timestamp": "2024-03-15T14:30:00Z"
}
call.ended
{
"event": "call.ended",
"workspace_id": "ws_xxxxxxxx",
"session_id": "sess_xxxxxxxx",
"agent_id": "agent_xxxxxxxx",
"duration_seconds": 127,
"end_reason": "user_disconnected",
"cost_usd": 0.043,
"timestamp": "2024-03-15T14:32:07Z"
}
end_reason uses the same canonical values as call logs, such as user_disconnected, agent_disconnected, user_did_not_pick_up, user_busy, voicemail_detected, network_failure, system_failure, and insufficient_balance. See Call End Reasons.
call.transcript_ready
{
"event": "call.transcript_ready",
"session_id": "sess_xxxxxxxx",
"transcript": [
{
"role": "agent",
"text": "Hello, thank you for calling. How can I help you today?",
"timestamp_ms": 1200
},
{
"role": "caller",
"text": "I'd like to book an appointment for next Tuesday.",
"timestamp_ms": 4800
}
],
"timestamp": "2024-03-15T14:32:12Z"
}
call.analysis_ready
{
"event": "call.analysis_ready",
"session_id": "sess_xxxxxxxx",
"analysis": {
"intent": "booking",
"appointment_date": "2024-03-19",
"sentiment": "positive",
"resolution_status": "resolved"
},
"timestamp": "2024-03-15T14:32:45Z"
}
Field names in analysis correspond to the PCA fields configured on the agent.
Verifying webhook signatures
Every webhook request includes a signature header that lets you verify the payload came from DialNexa and was not tampered with.
Header: X-DialNexa-Signature
Algorithm: HMAC-SHA256 of the raw request body, signed with your webhook secret.
Verification (Node.js example):
const crypto = require('crypto');
function verifyWebhook(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
);
}
Your webhook secret is shown once when you create the endpoint. Store it securely. If you lose it, regenerate it from the webhook settings page — this will invalidate all previous signatures.
Always verify the signature before processing webhook payloads. Accepting unsigned requests creates a security risk where anyone who knows your endpoint URL can send fake events.
Retry behavior
If your endpoint returns a non-2xx status code or does not respond within 5 seconds, DialNexa retries the delivery. Retry schedule:
| Attempt | Delay |
|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
After 3 failed retries, the event is marked as failed and no further delivery is attempted. Failed deliveries are visible in Settings > Webhooks > Delivery Log.
To replay a failed delivery, click Retry next to the failed event in the Delivery Log.
Implement idempotency in your webhook handler. DialNexa may deliver the same event more than once in retry scenarios. Use session_id + event as a deduplication key.
Filtering events by agent
To receive events only for a specific agent, add the agent_id filter when creating the endpoint. This is useful when different teams own different agents and should only receive their own notifications.