Ray
PricingDocsSign inStart free
Browse the docs

Getting started

Ray documentationAuthenticationUsing Ray with AI coding agentsMCP serverTypeScript SDK

Guides

Sending notificationsIdempotencyTemplatesScheduling and test sendsStatus and feedsClick trackingDelivery webhooks

Channels

Email with Amazon SESEmail with SMTPPush notifications with Firebase Cloud MessagingSlack notificationsDiscord notificationsTelegram notificationsSMS with TwilioSMS with sendsms.mnHTTPS webhook channel

Reference

Rate limits and quotasErrors

Getting started

Ray documentationAuthenticationUsing Ray with AI coding agentsMCP serverTypeScript SDK

Guides

Sending notificationsIdempotencyTemplatesScheduling and test sendsStatus and feedsClick trackingDelivery webhooks

Channels

Email with Amazon SESEmail with SMTPPush notifications with Firebase Cloud MessagingSlack notificationsDiscord notificationsTelegram notificationsSMS with TwilioSMS with sendsms.mnHTTPS webhook channel

Reference

Rate limits and quotasErrors

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.

View as Markdownllms.txtAPI reference

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

  1. In the Twilio Console, copy the Account SID (starts with AC) and Auth Token from the account dashboard.
  2. 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.
  3. 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.

PreviousTelegram notificationsNextSMS with sendsms.mn

On this page

  • What you need from Twilio
  • Channel config
  • Template content
  • Recipient
  • Send a message
  • Pacing
  • Errors
Ray

Notification delivery for teams that already have providers.

Product

PricingDocsAPI referenceMCP serverTypeScript SDKAgent skillsllms.txt

Legal

TermsPrivacyRefunds

Contact

[email protected]

© 2026 L’Atelier Gege LLC