Implementing your HTTPS event endpoint for real-time call events
18 min
overview exoml for programmable voice delivers live call events to your application so you can decide the next action while the caller is on the line to receive those events, host a public https event endpoint exotel sends each event as an http post with a json body and waits for your acknowledgement your application should return an http 2xx status as soon as the event is accepted decide the next step in your application logic issue the next call command using exoml apis (play, gather, dial, bridge, hangup, and so on) the http response acknowledges receipt of the event it does not return the next call verbs — those are always sent through exoml apis after the event live call / leg / bridge │ ▼ exotel exoml platform │ │ post application/json (https) │ waits for http 2xx ack ▼ your https event endpoint │ │ 1) return 2xx │ 2) decide next step ▼ exoml apis (dial, play, gather, bridge, hangup, …) │ ▼ exotel executes action → sends next event exotel acts as the http client you host the https server configuration steps 1\ implement your https event endpoint your service should accept post requests with content type application/json parse the json body described in payload fields return any http 2xx status once the event is accepted (a response body is not required; exotel treats the status as the ack) 2\ deploy a public https url use a publicly reachable url (any path), for example https //voice example com/exotel/events use a valid public tls certificate in production keep the handler low latency — this endpoint sits on the live call path prefer completing heavy crm or llm work after you acknowledge the event 3\ register the endpoint outbound / api driven calls when creating a resource, pass your https url in api field example create leg — leg event endpoint https //voice example com/exotel/events create bridge — bridge event endpoint https //voice example com/exotel/events exotel delivers live events over https when the url scheme is https // inbound programmable voice (exophone) share your https event url with exotel support or your exotel contact so it can be attached to your exophone for inbound live events 4\ (optional) enable basic auth if you would like exotel to authenticate when calling your endpoint, see authentication http contract item value method post content type application/json tls https is required in production success ack any http 2xx (response body is ignored) retries up to 3 attempts total for 408, 429, 5xx, timeouts, and connection errors other 4xx responses are not retried after the final attempt, the event is dropped next call action issue via exoml apis after acknowledging the event request headers header description content type application/json user agent exotel hermix/\<version> x exotel event sid same value as the body field event sid x exotel request id \<event sid> \<attempt number> (attempt numbers 1–3, for example … 1, … 2) authorization basic … when basic auth is configured on your account example request post /exotel/events http/1 1 host voice example com content type application/json user agent exotel hermix/1 0 x exotel event sid 3igzdxwxdn1yly5cgvfvyxnhezo00000 x exotel request id 3igzdxwxdn1yly5cgvfvyxnhezo00000 1 authorization basic dxnlcjpwyxnz { "event sid" "3igzdxwxdn1yly5cgvfvyxnhezo00000", "event type" "leg action event", "event name" "leg failed to create", "event timestamp" "2026 08 31t18 28 00 529z", "event data" { "data" {}, "error" { "error code" "1001", "message" "destination unreachable", "description" "carrier returned 480" } }, "data" { "leg sid" "3igzdzxuhsk9k67utaeupegvnai00000", "account sid" "exotel60", "contact uri" "09163816621", "exophone" "08030752400", "state" "completed", "terminal status" "failed", "start time" "2026 08 31t18 28 00 312z", "end time" "2026 08 31t18 28 00 403z", "date created" "2026 08 31t18 28 00 339z", "date updated" "2026 08 31t18 28 00 403z" } } example ack http/1 1 200 ok 201, 204, and other 2xx statuses are also accepted capacity and rate limits exotel does not apply a fixed requests per minute cap on live event posts to your https endpoint event volume follows your concurrent calls (several events can be emitted per call) please size your endpoint for peak concurrent traffic and return 2xx promptly — hermix waits up to about 1 second per delivery attempt prefer acknowledging quickly and doing heavier work asynchronously we recommend not using http 429 as backpressure on this path exotel treats 429 as retriable (up to 3 attempts), which can delay delivery and still drop the event after the final attempt separately, when your application calls exoml apis (create leg, actions, and so on), the default account limit is 100 requests per minute contact your exotel account manager if you need a higher api limit payload fields all json keys use snake case timestamps use rfc 3339 utc with millisecond precision, for example 2026 08 31t18 28 00 339z this applies to event timestamp and nested fields such as start time, end time, date created, date updated, answered time, and ringing time field type notes event sid string unique event id event type string coarse group (see below) event name string specific event (for example leg answered, gather success) event timestamp string time the event was generated action sid string present when an action produced the event; may be omitted when unset action custom parameter string echo of your custom parameter when set event data object action or error details when applicable; may be omitted when unset data object call context for the event (for example leg sid, account sid, state fields) event type values event type typical use leg lifecycle event call leg lifecycle (ringing, answered, terminated, …) leg action event action outcomes (play, gather, dial, failed to create, …) bridge lifecycle event bridge lifecycle bridge action event bridge action outcomes we recommend routing and logging primarily on event name, and using event type for coarse grouping example event names these are illustrative and not exhaustive call leg leg connecting, leg ringing, leg answered, leg terminated, leg failed to create, leg incoming action play started, play completed, recording started, recording available, gather success, dial success, … bridge bridge created, bridge terminal, leg joined bridge, leg left bridge exact fields inside data and event data depend on the event authentication you can optionally require authentication so your service only accepts callbacks from exotel http basic auth when basic auth is configured on your account, exotel includes the following header on every event post authorization basic \<base64(username\ password)> example if your configured credentials are username exotel user password exotel pass exotel sends authorization basic zxhvdgvsx3vzzxi6zxhvdgvsx3bhc3m= your server should read the authorization header decode the basic auth value validate the username and password reject the request if credentials are missing or invalid note custom headers such as x exotel token are not supported please validate the standard authorization basic auth header how to enable authentication decide on the username and password (or api key and token) your service will accept share those credentials with exotel support or your exotel contact so they can be configured on your account ensure your endpoint validates the authorization header on every callback once configured, exotel automatically attaches basic auth credentials to outbound https event requests for your account when authentication is not configured if basic auth credentials are not configured on your account, exotel still delivers events to your public https endpoint, without an authorization header in that case, protect your endpoint using tls and, optionally, ip allowlisting ip allowlisting if you restrict inbound traffic by ip, please allow the following exotel callback source addresses 35 154 174 161 13 233 217 51 98 130 5 99