Skip to content

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.

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_PROVIDER and 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).

.env
ONY_TELEPHONY_PROVIDER=signalwire
ONY_SIGNALWIRE_SPACE_URL=https://<your-space>.signalwire.com
ONY_SIGNALWIRE_PROJECT_ID=<project-id>
ONY_SIGNALWIRE_API_TOKEN=<api-token>
ONY_SIGNALWIRE_FROM_NUMBER=+1XXXXXXXXXX # a SignalWire number you own
ONY_SIGNALWIRE_AUTH_TOKEN=PSK_... # the space SIGNING KEY, NOT an API token

Expose 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.

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/inbound

The 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.

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.