RelayAPI

SMS API

Connect a validated Twilio sender and deliver SMS or MMS with per-recipient outcomes.

Current RelayAPI capability

PropertyRelayAPI behavior
Platform keysms
ProviderTwilio Programmable Messaging
ConnectionAccount SID, Auth Token, and an owned SMS-capable default sender
BodyUp to 1,600 characters; Twilio may bill/deliver it as multiple segments
Recipients1–100 E.164 numbers, sent as separate Twilio messages
MMSUp to 10 public media URLs per recipient
SchedulingYes, through RelayAPI
Native analytics endpointsNo

RelayAPI's current SMS publisher is Twilio-only. It does not select Telnyx or another provider from account metadata.

Connect Twilio

curl -X POST https://api.relayapi.dev/v1/connect/sms \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "ws_example",
    "account_sid": "your-twilio-account-sid",
    "auth_token": "your-twilio-auth-token",
    "from_number": "+15017122661"
  }'

Before storing the encrypted credential, RelayAPI verifies all three facts with Twilio:

  1. The Account SID and Auth Token authenticate.
  2. The Twilio account is active.
  3. from_number is an SMS-capable incoming number owned by that account.

The verified number and its reported MMS capability are stored as connection-owned metadata. That sender is authoritative for outbound requests: generic account metadata cannot replace it, and a credential already connected in another workspace cannot be moved by reconnecting it implicitly.

Send SMS

curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: example-idempotency-key" \
  -d '{
    "content": "Order 12345 has shipped.",
    "targets": ["acc_sms_example"],
    "scheduled_at": "now",
    "target_options": {
      "sms": {
        "phone_numbers": ["+14155238886"]
      }
    }
  }'

The account ID selects one exact Twilio connection. The broader sms selector is also valid, but it expands to every authorized SMS account in the post's workspace boundary. The connected sender is always used. Legacy target_options.sms.from_number is accepted only as a matching identity assertion; a different number fails with SMS_SENDER_MISMATCH before any Twilio request.

Send MMS to several recipients

{
  "content": "Your receipt is attached.",
  "targets": ["acc_sms_example"],
  "media": [
    {"url": "https://cdn.example.com/receipt.png", "type": "image"}
  ],
  "scheduled_at": "now",
  "target_options": {
    "sms": {
      "phone_numbers": [
        "+14155238886",
        "+14155238887"
      ]
    }
  }
}

RelayAPI creates one Twilio Message resource per recipient. This is not a group message. Twilio fetches every MediaUrl, so each URL must remain publicly reachable and meet Twilio/carrier requirements. MMS availability, file support, deliverability, registration, and pricing depend on the sender and destination; an account being connected does not guarantee every MMS will be accepted.

target_options.sms

FieldTypeRequiredBehavior
phone_numbersE.164 string arrayYes1–100 recipients; each becomes a separate provider effect
from_numberE.164 stringNoDeprecated matching assertion only. It must equal the connector-verified sender and cannot override it.
contentstringNoSMS-specific body override
mediaarrayNoSMS-specific media override, up to 10 URLs

The message must contain a body, at least one media URL, or both.

Delivery lifecycle

An HTTP success from Twilio normally means the message was accepted, not delivered. RelayAPI records each returned Message SID and maps provider states as follows:

Twilio stateRelayAPI disposition
accepted, scheduled, queued, sendingPending/accepted
sentSent
delivered, readDelivered
failed, undelivered, canceledFailed
Undocumented stateOutcome unknown

Multi-recipient operations can be partial. RelayAPI preserves one effect per recipient; it does not report the whole post as successful when one recipient was rejected. Message SID reconciliation checks each accepted message independently.

Reuse the original RelayAPI idempotency key and exact body when retrying a request that did not cross the provider boundary. If the response is partial or outcome-unknown, reconcile the recorded SIDs instead of resending every recipient.

Credential and compliance lifecycle

  • Twilio Auth Tokens do not refresh through OAuth. Reconnect after rotation or revocation.
  • Reconnecting can validate a different sender. A publish-time field cannot change or persist another sender.
  • You are responsible for sender registration, recipient consent, opt-out handling, quiet hours, carrier rules, and Twilio charges in the jurisdictions where you send.
  • Disconnecting RelayAPI does not close the Twilio account or release its phone number.

Official Twilio references

Found something wrong? Help us improve this page.

On this page