Implementing your HTTPS event endpoint for real-time call events
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.
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
Example ack
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:
Example
If your configured credentials are:
- Username: exotel_user
- Password: exotel_pass
Exotel sends:
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: