Carrier setup
Self-hosting is bring-your-own-carrier: there is no bundled phone number. You connect one supported telephony account and Ony.ai places calls and sends SMS through it. Four carriers are supported:
| Carrier | Status | Notes |
|---|---|---|
| SignalWire | Default, most battle-tested | The reference adapter; the rest of the docs use it |
| Twilio | Supported | cXML/TwiML-compatible, same voice flow |
| Telnyx | Beta | Webhooks verified with an Ed25519 public key |
| Plivo | Beta | Renders Plivo XML; auth token signs webhooks |
All four speak a TwiML-family dialect, so the voice decision flow is identical; only credentials and webhook-signature verification differ per carrier.
Two ways to configure
Section titled “Two ways to configure”You can use either, and a dashboard-configured carrier takes precedence over env values.
- From the dashboard (recommended, no restart). Settings -> Integrations -> Telephony. Pick a provider, paste the credentials plus the number you will call from, hit Test to confirm them, and Save to make it the active carrier. Credentials are encrypted at rest (never in logs or the audit trail) and picked up live.
- From the environment (config-as-code). Set
ONY_TELEPHONY_PROVIDERand that carrier’s variables in.env. Only the selected provider’s credentials are needed. See the configuration reference and.env.example.
You need a SignalWire space with a phone number, and four values from its API Credentials page:
the space URL, a project ID, an API token, and the space’s Signing Key (it starts with
PSK_, next to the Project ID).
ONY_TELEPHONY_PROVIDER=signalwireONY_SIGNALWIRE_SPACE_URL=https://<your-space>.signalwire.comONY_SIGNALWIRE_PROJECT_ID=<project-id>ONY_SIGNALWIRE_API_TOKEN=<api-token>ONY_SIGNALWIRE_FROM_NUMBER=+1XXXXXXXXXX # a SignalWire number you ownONY_SIGNALWIRE_AUTH_TOKEN=PSK_... # the space SIGNING KEY, NOT an API tokenSet the provider to twilio and supply the account SID, auth token, and a Twilio number. The account
auth token also verifies inbound webhook signatures.
ONY_TELEPHONY_PROVIDER=twilioONY_TWILIO_ACCOUNT_SID=<account-sid>ONY_TWILIO_AUTH_TOKEN=<auth-token>ONY_TWILIO_FROM_NUMBER=+1XXXXXXXXXXSet the provider to telnyx. Telnyx verifies webhooks with an Ed25519 public key rather than a shared
secret, so both the API key and the base64 public key are required.
ONY_TELEPHONY_PROVIDER=telnyxONY_TELNYX_ACCOUNT_SID=<texml-application-id>ONY_TELNYX_API_KEY=<api-key>ONY_TELNYX_PUBLIC_KEY=<base64-ed25519-public-key> # verifies inbound webhooksONY_TELNYX_FROM_NUMBER=+1XXXXXXXXXXSet the provider to plivo. The auth token both signs inbound webhooks and authenticates REST calls.
ONY_TELEPHONY_PROVIDER=plivoONY_PLIVO_AUTH_ID=<auth-id>ONY_PLIVO_AUTH_TOKEN=<auth-token>ONY_PLIVO_FROM_NUMBER=+1XXXXXXXXXXExpose the webhooks and verify your number
Section titled “Expose the webhooks and verify your number”The carrier reaches Ony.ai at ${ONY_PUBLIC_BASE_URL}/webhooks/..., so ONY_PUBLIC_BASE_URL must point
at a publicly reachable https:// host. See the three edge options in
self-hosting. For a quick local test,
cloudflared tunnel --url http://127.0.0.1:8001 prints a https://...trycloudflare.com you can use.
Then verify your phone number in the dashboard (Settings -> Profile). Until a number is verified,
handoffs surface in the dashboard rather than ringing; ony doctor warns about exactly this.
Outbound approval calls need no manual webhook configuration - Ony.ai builds the callback URL from
ONY_PUBLIC_BASE_URL and hands it to the carrier.
Inbound: “call your agent”
Section titled “Inbound: “call your agent””To let a verified user call the number to check on their agent, point the number’s When a Call Comes In voice webhook (in the carrier console) at:
POST https://<your-public-host>/webhooks/signalwire/voice/inboundThe route path is shared across all TwiML-family carriers (the module name is historical). The inbound flow identifies the caller by caller ID (a spoofable hint only), texts a one-time code to the verified number, and requires it back by keypad before reading a short, non-sensitive status summary.
US SMS requires 10DLC approval
Section titled “US SMS requires 10DLC approval”To send application-to-person SMS to US numbers, you must register a 10DLC brand and campaign with your carrier. Until that carrier approval clears, US SMS delivery is unreliable or blocked regardless of Ony.ai configuration. Voice calls are not affected. SMS is used for the inbound one-time code, the escalation SMS step, and the details deep link.
Related
Section titled “Related”- Self-hosting - the edge options and the full stack.
- Escalation and fallbacks - retries and SMS/chat channels when a call goes unanswered.
- Threat model - why every inbound webhook is signature-verified and fail-closed.