API ReferenceInbound Bindings
Inbound Bindings overview
How API-first inbound bindings work — registration, lookup, mutation, and deregistration.
An inbound binding is the link between a phone number on your provider (Twilio / Vobiz / Tata Smartflo) and an agent in zoxaAI. For webhook providers (Twilio / Vobiz), the number rings → the provider POSTs to zoxaAI → the dispatcher looks up the binding, verifies the signature, and bridges the call to the agent. For streaming-native Smartflo, the media stream arrives at the config's signed WSS URL and the binding is matched by dialed DID — credentials come from the saved telephony config at registration, not inline (see Smartflo setup).
Lifecycle
[POST /call type=inbound] → upserts binding (idempotent on provider+phoneNumber)
→ PATCHes provider's number/app to point at our webhook
→ stores credentials + agent snapshot
[GET / PATCH / DELETE] → manage the binding's lifecycle without re-provisioning
(PATCH only changes the agent;
DELETE deprovisions on the provider side)
[provider POSTs to /telephony/run] → dispatcher matches (provider, dialedNumber)
→ verifies signature with binding's creds
→ creates a calls row tied to the binding
→ returns provider XML opening the WS to the agentEndpoints
| Method | Path | Purpose |
|---|---|---|
POST | /call type=inbound | Register / re-register (idempotent upsert). |
GET | /telephony/inbound/bindings | List your registrations. |
GET | /telephony/inbound/bindings/{id} | Detail incl. credentials in debug mode. |
PATCH | /telephony/inbound/bindings/{id} | Swap the agent without re-provisioning the provider. |
DELETE | /telephony/inbound/bindings/{id} | Deprovision + delete. |
Key design points
| Behavior | Rationale |
|---|---|
(provider, phoneNumber) is the unique key | One number can be bound to one agent. Re-POST overwrites; no duplicates. |
| Provider webhook URL is set at register time, not at PATCH | PATCH is the cheap path for swapping agents. Use re-POST if credentials changed. |
| Credentials stored encrypted (Fernet) in prod | DEBUG_TELEPHONY_CREDS_PLAINTEXT flag controls plaintext vs. encrypted storage. The detail endpoint always returns masked values (last 4 chars) regardless. |
Inbound bindings win over dashboard telephony_phone_numbers for the same number | API-first explicitly takes precedence so re-registering steals routing back. |
Related
POST /call type=inbound— register- Calls overview