{type: "exotel"} in the integrations collection.
Endpoints
All under/api/v1/integrations. Credential/DID writes require super_admin; test-call reads require admin.
| Method | Path | Role | Purpose |
|---|---|---|---|
GET | /exotel | super_admin | Get integration (credentials masked to a configured flag + account_sid) |
PUT | /exotel | super_admin | Upsert credentials (account_sid, api_key, api_token, api_base_url) |
POST | /exotel/dids | super_admin | Add a DID |
PUT | /exotel/dids/{did_id} | super_admin | Update DID label/bot_id/flow_url |
DELETE | /exotel/dids/{did_id} | super_admin | Remove a DID |
GET | /exotel/test-call-options | admin | Sanitized DIDs usable from the test-call UI |
POST | /exotel/dids/{did_id}/test-call | admin | Place a customer test call via Exotel |
Data model
ExotelDID fields: number, label, bot_id, flow_url. The response adds a derived websocket_url.
The websocket_url is generated from the fleet base, not stored:
_get_fleet_wss_basetakes the first entry ofcore_fleet, swapshttps→wss/http→ws(orwss://localhostif the fleet is unset)._websocket_url→{fleet_wss_base}/exotel/{bot_id}when abot_idis attached, else empty.
The integration response never returns
api_key/api_token. credentials_configured is true only when account_sid, api_key, and api_token are all present (_credentials_configured); status is configured/not_configured accordingly. CXB Core does not need Exotel credentials — call control is flow-based.Test call
start_exotel_test_call uses Exotel’s connect-to-flow REST API to ring a customer and bridge them into the configured flow:
Request details:
| Aspect | Value |
|---|---|
| API URL | {api_base_url}/v1/Accounts/{account_sid}/Calls/connect (base normalised, defaults https://api.exotel.com) |
| Auth | HTTP Basic api_key:api_token |
From | normalised to_number (the customer) |
CallerId | the DID number |
Url | the DID flow_url |
CallType | trans |
CustomField | cxb-test:{did_id} (truncated to 128 chars) |
_normalise_exotel_from_number) maps Indian formats to +91 E.164: a bare 10-digit [6-9]…, 91…, or 0091…. Responses are parsed from JSON first, then XML, extracting call_sid and provider_status. Exotel errors (RestException/Message) surface as 502.
Related docs
Exotel transport (CXB Core)
How CXB Core handles the Exotel WebSocket and the
/exotel/{bot_id} URL.Fleet routing
The
core_fleet list that seeds the generated WebSocket base.Carriers & trunks
SIP carriers, the non-Exotel telephony path.
Settings
Where
core_fleet is configured.