Channels
SMS with Twilio
Send Ray notifications as SMS through your own Twilio account. Account SID and Auth Token, sender numbers and Messaging Services, E.164 recipients, pacing and errors.
The twilio_sms channel sends text messages with Twilio's Messages API from your own Twilio account. Each send targets one phone number in international E.164 form. API calls go to https://ray-api.gege.mn with Authorization: Bearer $RAY_API_KEY.
| Channel type | twilio_sms |
| Template kind | sms_text (shared with sendsms.mn) |
| Recipient | { "phoneNumber": "+97699112233" } |
| Pacing | ratePerMinute, default 300, max 1600 |
| Suppression | None (Twilio itself blocks numbers that replied STOP) |
What you need from Twilio
- In the Twilio Console, copy the Account SID (starts with
AC) and Auth Token from the account dashboard. - Choose a sender:
- a Twilio phone number that can send SMS, in E.164 form such as
+15017122661; - an alphanumeric sender id such as
ACME(1 to 11 letters, digits or spaces), in countries that allow it; - or a Messaging Service (SID starts with
MG), which picks a sender from its pool.
- a Twilio phone number that can send SMS, in E.164 form such as
- Under Messaging → Settings → Geo permissions, enable every country you will send to.
Channel config
Create the config in the dashboard: Channels, New channel, SMS (Twilio). The Auth Token is stored encrypted and never shown again.
| Field | Required | Notes |
|---|---|---|
| Name | yes | Internal label, for example otp-sms. |
Account SID (accountSid) |
yes | AC followed by 32 hex characters. |
Auth Token (authToken) |
yes | When editing, leave blank to keep the stored token. Changing the Account SID requires a new token. |
From (from) |
one of these two | Sender number in E.164 or an alphanumeric sender id. |
Messaging Service SID (messagingServiceSid) |
one of these two | MG followed by 32 hex characters. Set either this or From, not both. |
Rate limit, messages per minute (ratePerMinute) |
no | Default 300, max 1600. |
Find the config's id with GET /channels; its kind is twilio_sms.
Template content
| Field | Type | Notes |
|---|---|---|
text |
string, 1 to 1600 | Plain text. Twilio splits long messages into segments (about 160 GSM-7 characters, or 70 when the text has Cyrillic or emoji), and each segment is billed as one SMS. |
Param values are inserted verbatim; SMS has no markup to escape. The same sms_text template also works with a sendsms.mn channel, which splits long messages into SMS of at most 159 plain Latin or 69 Cyrillic characters. Text longer than 1600 characters after params are filled in is rejected with 400.
Recipient
{ "phoneNumber": "+97699112233" }
| Field | Type | Notes |
|---|---|---|
phoneNumber |
string | Required. International number: +, the country code, then the number. Spaces, dashes, dots and parentheses are removed, and a leading 00 is read as +. A number without a country code is rejected with 400, because Ray can't tell which country it belongs to. |
Send a message
curl -X POST https://ray-api.gege.mn/send \
-H "Authorization: Bearer $RAY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: otp-8f2c" \
-d '{
"channelConfigId": "8e9f0a1b-2c3d-4e5f-8a6b-7c8d9e0f1a2b",
"content": { "text": "Your Acme code is {{code}}. It expires in 10 minutes." },
"params": { "code": "482913" },
"logTitle": "Login code",
"logDescription": "Login code sent by SMS",
"recipient": { "phoneNumber": "+97699112233" }
}'
The delivery row's providerMessageId is Twilio's message SID (SM…). delivered means Twilio accepted and queued the message; Ray doesn't subscribe to Twilio's status callbacks, so carrier delivery is visible in the Twilio Console's messaging logs.
Pacing
Ray paces each Twilio account at ratePerMinute (default 300). Configs on the same Account SID share one pace. Twilio queues messages beyond a sender's own throughput (about one message per second for a standard long code), so a burst still goes out in order, only more slowly.
Errors
Errors appear on the delivery row as providerError: { "name": "TwilioError", "message": "Twilio send failed: <status> (code <twilio code>) <message>" }.
| Result | Cases |
|---|---|
failed_terminal (not retried) |
Any 4xx except 429, for example 21211 invalid To number, 21408 country not enabled in geo permissions, 21610 recipient replied STOP, 21606 the From number can't send SMS, 20003 wrong Account SID or Auth Token |
failed_retryable (retried) |
429 (20429 too many requests), 5xx, network errors and timeouts |
Request errors from POST /send are listed in Errors.