Twilio
You need a Twilio account, a phone number, and a SIP trunk that bridges to LiveKit Cloud.
1. Account credentials
From console.twilio.com, copy these values:
TWILIO_ACCOUNT_SID— starts withAC…TWILIO_AUTH_TOKEN— click "Show" to see the value
Put them in .env.
2. Phone number
Go to Phone Numbers → Buy a number. Select a number with the Voice capability. For outbound SMS, select a number that also has the SMS capability. The carrier fixes these capabilities when you buy the number; you cannot add SMS to a voice-only number later. Note the E.164 format (+1…).
3. SIP trunk
- Elastic SIP Trunking → Trunks → Create new Trunk.
- Under Termination, choose a unique termination domain such as
your-trunk.pstn.twilio.com. - Add a credential list with a SIP username and password. LiveKit's outbound trunk must use the same credentials.
- Under Numbers, attach the phone number from step 2.
- Continue with LiveKit Cloud setup, using the Twilio termination domain and credentials to create a LiveKit outbound trunk.
Do not add the termination domain to Hail's .env: Hail uses the resulting
LiveKit trunk ID (LIVEKIT_TWILIO_SIP_OUTBOUND_TRUNK_ID) at runtime. Twilio calls
traffic from LiveKit to the PSTN “termination.” Its “origination” settings
carry inbound calls to LiveKit: see §6.
Twilio requires outbound destinations and caller IDs in E.164 format. Trial accounts can call only verified destination numbers. See Twilio's Elastic SIP Trunking reference.
4. Outbound SMS
Hail sends SMS from a dedicated number.
- Acquire an SMS-capable number (step 2 above). Only numbers with the SMS capability can send.
- Hail sets the number up. When the number becomes active, Hail attaches
it to your organization's Twilio Messaging Service and creates that service
the first time, with its inbound webhook pointed at
<HAIL_API_URL>/sms/inbound. There is one Messaging Service per organization; every number joins the same shared sender pool. If that step failed (the API log says why), assigning a texts agent runs it again, andPOST /numbers/{id}/enable-smsruns it by hand. Both are idempotent. - Send. Call
POST /smswith the recipient and body. Hail sends from your organization's dedicated number.
A2P 10DLC (United States). US carriers deliver application-to-person SMS on long-code numbers only after you register an A2P 10DLC brand and campaign. Do this in the Twilio console (Messaging → Regulatory Compliance → A2P 10DLC) before you send to US numbers. Registration is a Twilio-side requirement; Hail does not manage it.
Sender ID (optional, rest-of-world). For destinations that allow it, set a
custom alphanumeric sender with PATCH /sms/sender-id (read the current value
with GET /sms/sender-id). Clear it by sending null. When you set none, Hail
falls back to the platform default sender. The United States and Canada do not
allow alphanumeric sender IDs — messages there always send from the dedicated
number, regardless of this setting.
Rate limits. Per-organization send velocity is capped by
HAIL_VELOCITY_SMS_PER_HOUR (default 100) and HAIL_VELOCITY_SMS_PER_DAY
(default 1000). An abuse monitor suspends an organization's SMS channel when its
opt-out rate is too high — see operations for the
HAIL_SMS_ABUSE_* variables and how to lift a suspension.
5. Inbound SMS & opt-out
Inbound texts arrive through the Messaging Service's inbound webhook, which
Hail sets to <HAIL_API_URL>/sms/inbound (HTTP POST) when it creates or reuses
the service. Nothing to set on the number itself. Hail verifies Twilio's
X-Twilio-Signature against HAIL_API_URL, so that value must be the public
URL that Twilio posts to.
Recognized keywords (Hail matches them on the message body, case-insensitive):
- Opt out (STOP):
STOP,STOPALL,UNSUBSCRIBE,CANCEL,END,QUIT - Opt in (START):
START,YES,UNSTOP - Help:
HELP,INFO
Hail records opt-outs in its own suppression list, regardless of the Twilio configuration. Hail checks this list before every send.
Opt-out replies: By default, Twilio replies automatically to
STOP/HELP/START and carrier-blocks opted-out numbers. In that setup, keep
HAIL_SMS_COMPLIANCE_REPLIES_ENABLED=false. If you want Hail to own the
replies (for example, a non-Twilio provider, or a custom keyword experience),
do the two steps that follow. Caution: if you disable Twilio's default
opt-out handling, the change is account-wide and requires a Twilio Support
request; there is no API for it. First, disable Twilio's default opt-out
handling. Then set HAIL_SMS_COMPLIANCE_REPLIES_ENABLED=true.
6. Inbound calls
Twilio sends a call to LiveKit when the number sits on an Elastic SIP trunk whose origination URI is LiveKit. Hail attaches the number when it routes calls to an agent; you set up the trunk once.
- On the trunk from step 3, open Origination and add the origination
URI
sip:<project>.sip.livekit.cloud;transport=tcp(your LiveKit SIP endpoint is on the project's settings page). - Copy the trunk SID (
TK...) into.envasTWILIO_SIP_TRUNK_SID. - Create the LiveKit inbound trunk and dispatch rule
(LiveKit Cloud §4) and set
LIVEKIT_SIP_INBOUND_TRUNK_ID.
Twilio Elastic SIP Trunking has no inbound username/password, so the LiveKit
trunk lists the numbers instead: PATCH /v1/numbers/{id} with
voice_agent_id adds the number to the Twilio trunk
(trunking.v1.trunks(TK...).phone_numbers) and to the LiveKit trunk; null
removes it from both (Agents).
LiveKit Cloud
LiveKit Cloud supplies the media (SIP bridge + WebRTC) in v1. A self-hosted SFU is a later milestone.
Telnyx
Second carrier for numbers, calls and SMS, next to Twilio. When both are configured, POST /numbers/quotes compares live inventory, prices and verification requirements from each and ranks the offers; POST /numbers buys one by quoteid. A number never changes carrier: calls from a Telnyx number go out through the Telnyx trunk, SMS through Telnyx messaging.