Webhooks deliver real-time event notifications to your server via HTTP POST requests. Use them to sync call data with your CRM, trigger follow-up workflows, log activity, or alert your team.
Prerequisites: Neuratel account, a publicly accessible HTTPS endpoint
How webhooks work
You register a webhook URL and select which event types to receive.
When an event occurs, Neuratel sends an HTTP POST request to your URL.
Your server verifies the HMAC signature, processes the event, and returns 200 OK.
Failed deliveries are retried up to 3 times (5s, 30s, 2min delays).
Event types
Event
When it fires
call.started
A call has begun
call.ended
A call has ended (fires immediately, before analysis)
call.ringing
Outbound call is ringing
call.answered
Call has been answered
call.failed
An error occurred during a call
call.transferred
Call transferred to another destination
recording.ready
Coming soon — defined but not yet emitted. The recording URL is currently surfaced on call.summary.ready and on the voice session record.
call.summary.ready
Post-call analysis (summary, transcript, evaluation) is complete
The secret is returned only once at creation time. Store it securely — you will need it to verify signatures.
Verify webhook signatures
Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret.
Always verify signatures before processing events to ensure requests are authentic.
Code
import hmacimport hashlibfrom fastapi import FastAPI, Request, HTTPExceptionapp = FastAPI()WEBHOOK_SECRET = "whsec_a1b2c3d4e5f6g7h8i9j0"def verify_webhook(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() return hmac.compare_digest(signature, expected)@app.post("/webhooks/neuratel")async def handle_webhook(request: Request): signature = request.headers.get("X-Webhook-Signature", "") payload = await request.body() if not verify_webhook(payload, signature, WEBHOOK_SECRET): raise HTTPException(status_code=401, detail="Invalid signature") event = await request.json() event_type = event["type"] data = event["data"] if event_type == "call.summary.ready": # Process completed call with full analysis print(f"Call {data['call_id']} completed — {data['duration_seconds']}s") elif event_type == "call.failed": # Alert your team print(f"Error on call {data['call_id']}: {data['error_message']}") return {"status": "ok"}
If your secret is compromised, rotate it immediately. The old secret becomes invalid as soon as the new one is generated.
Code
curl -X POST https://api.neuratel.ai/v1/webhooks/wh_abc123/secret/rotate \ -H "Authorization: Bearer nk_live_your_api_key"
Response:
Code
{ "secret": "whsec_new_secret_value"}
Update your server with the new secret before the next event delivery.
Retry policy
Attempt
Delay
1
5 seconds
2
30 seconds
3
2 minutes
After 3 failed attempts the delivery is marked as failed. Webhooks are automatically disabled after 10 consecutive delivery failures — re-enable via the dashboard or PATCH /v1/webhooks/{id} with is_active: true. Your server must return a 2xx status code within 5 seconds for the delivery to count as successful.
Best practices
Practice
Reason
Return 200 immediately, process async
Webhook timeout is 5 seconds — queue the event and process in the background
Always verify signatures
Prevents spoofed requests from reaching your business logic
Handle events idempotently
The same event may be delivered more than once during retries