Available Events
Webhooks are not sent for test calls. External call events are sent once per call, and not for calls that started more than 24 hours before they were ingested, such as an initial sync or a historical import. Keep polling the External Calls API as a fallback for any delivery you miss.
Setting Up Webhooks
You can create webhooks in the dashboard under Configuration > Webhooks (/organization/settings/webhooks) or through the API. When you create a webhook, you provide:
- URL — the endpoint on your server that will receive the events
- Events — which event types you want to subscribe to. If you do not choose any, the endpoint receives all of them.
rate_limit when you create the webhook to cap how many deliveries per second your endpoint receives.
In the dashboard you can also add custom headers that are sent with every delivery (for example an Authorization header your server checks), send a test event, and pause a webhook by disabling it.
Webhook Format
Every event is a JSON object that names the event and the call it belongs to:call.started also includes direction, from_number, and to_number. See each event’s reference page for its full payload.
Events are notifications, not snapshots. To read the call’s status, transcript, recording, or analysis, get the call using the call_id from the event. For external_call.* events, get the external call instead.
Each request also carries these headers, following the Standard Webhooks specification. Every value is sent under both names, so you can read either:
Verifying Signatures
Every webhook is signed with a secret that is unique to your endpoint. Verify the signature before you process an event so that you only act on requests sent by Simple AI. Find the signing secret on the webhook’s page under Configuration > Webhooks in the dashboard. It starts withwhsec_. Any Standard Webhooks library can verify the signature; the examples below use the open-source svix library.
Verify against the raw request body, before any JSON parsing. Parsing and re-serializing the body changes it and causes verification to fail.
verify returns the parsed event and throws if the signature does not match or the timestamp is too old.
To verify without a library, compute an HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{raw body} using the base64-decoded part of the secret after whsec_, base64-encode the result, and compare it to the signatures in webhook-signature. That header holds one or more space-separated entries in the form v1,<signature>; accept the request if any of them matches.
When you rotate a webhook’s signing secret in the dashboard, deliveries are signed with both the old and the new secret for the next 24 hours, so you can update your server without rejecting any events.
Pre-Call and Post-Call Workflows
Webhooks are the building blocks for full pre-call and post-call workflows. Rather than just reacting to a single event, you can use them to trigger entire journeys — looking up caller data before a call, or orchestrating a multi-step follow-up process after a call ends. See Workflows for detailed guidance on building pre-call and post-call workflows, including examples of multi-step orchestration.Retry Policy
If your endpoint is unavailable, takes longer than 15 seconds to respond, or returns a non-2xx status code (redirects included), Simple AI retries the delivery. Retries are sent about 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours after each failed attempt, for 8 attempts in total. A retried delivery has the samewebhook-id as the original.
Each delivery and the response your endpoint returned are listed on the webhook’s page in the dashboard for 30 days, where you can also resend any of them.
Best Practices
- Respond quickly — return a 2xx status code as soon as you receive the webhook. If you need to do heavy processing, queue the work and respond immediately.
- Handle duplicates — due to retries, you may receive the same event more than once. Record the
webhook-idof each message you process and skip any you have already seen. - Verify signatures — always check the webhook signature to confirm the request is authentic.
- Do not rely on order — events for a call can arrive out of order. Get the call to read its current state.
- Think in workflows — a
call.completedevent does not have to map to a single action. Use it as the trigger for a full post-call journey that branches based on tags, analyzer results, or call outcome. - Monitor failures — if your endpoint starts returning errors, webhooks will be retried but eventually dropped. The webhook’s page in the dashboard lists each delivery attempt with the response your endpoint returned, and lets you resend a message.