Skip to main content

SMS sending services

A messaging service is a reusable sender profile: one container that bundles the sender pool (which of your numbers send), the opt-out list (which STOP/HELP keywords and auto-replies apply), and the inbound-reply webhook (where incoming messages land). Once a service exists, you point sends at its id and get the same configuration on every message instead of repeating from numbers and webhook URLs per send. This guide covers the full lifecycle: create a service in the console or with POST /api/v1/messaging/services, attach numbers, wire the opt-out list and inbound webhook, and send through it. For the endpoint shapes, see the Messaging Services API reference; for the sender-pool rotation strategies a service’s pool can use, see Sender pools.

1. When to create a service vs an ad-hoc sender

Create a service when any of these hold:
  • More than one sender per channel — a single hardcoded from number throttles and burns carrier reputation; a service with a pool rotates senders per recipient.
  • Branded compliance — if you send under more than one brand, you want that brand’s STOP/HELP copy on every message, not the platform defaults.
  • Two-way SMS — inbound replies need one webhook URL that every sender number in the service points at.
  • Migration from Twilio — if you’re mapping a MessagingServiceSid (MGxxx) over, the Orbit service is the equivalent container.
If a send is genuinely one-off (one number, default STOP/HELP copy, no inbound replies), an ad-hoc from is fine. The service exists to stop the “same four fields on every send” repetition once you’re past that.

2. Create a service

In the console

Open Messages → SMS → Services (/messages/sms/services) and click New service. The list page creates, edits, and deletes services; drilling into a service opens its Config, Phone Numbers, and Inbound Webhook tabs. Anything you can do in those tabs is available through the API below on the same service id.

Via the API

Only label is required — the rest of the config attaches later:
The response carries the service’s Orbit id (msvc_xxx), which is what sends reference. Owner or admin scope is required; a duplicate external_id (used for Twilio MGxxx migration) returns 409.

3. Attach numbers, opt-out list, and inbound webhook

Sender numbers

You have two ways to give a service senders, and most services want the pool:
  • Sender pool (recommended) — set sender_pool_id (or per-country country_sender_pools) so the service resolves from through a named pool’s strategy. See Sender pools for sticky / round_robin / random / geomatch behavior.
  • Direct phone-number attachment — for a fixed DID rather than a pool, attach specific tenant-owned numbers. SMS-capable DIDs only; voice/MMS-only DIDs are rejected with 422, and re-attaching the same number is idempotent:
A service with no sender at all resolves with a 4xx at send time, so attach at least one before you send through it.

Opt-out (STOP/HELP) list

Set opt_out_list_id on the service to point at a custom list — extra keyword aliases plus branded STOP/HELP/START auto-reply text. The platform’s carrier-mandated defaults always merge in; your list can add to but never remove STOP itself. For list creation and field details, see Custom Opt-Out Keyword Lists. Set opt_out_list_id back to null to fall back to the platform defaults.

Inbound-reply webhook

Set inbound_webhook_url (and optional inbound_method, default POST) so every inbound reply to any sender in the service POSTs to your endpoint. Optional fallback_url and status_callback fields further direct delivery-status events. Webhook URLs are validated server-side to block internal/private addresses — use a public HTTPS URL.

4. Send through the service

Pass messaging_service_id on the message instead of per-field from/webhook values. Any field you set explicitly on the message still wins; the service supplies the rest, matching Twilio’s MessagingServiceSid contract:
The send path resolves the service once at send time and stamps the resolved sender onto the message, so a later edit to the service never retroactively changes already-sent messages. Throughput and routing guardrails (per-service mps_cap, quiet hours, send gates) apply the same way as any other send; per-service mps_cap lets you throttle one profile below the tenant limit.

5. Multi-sender rotation and fallback

Rotation behavior is the sender pool’s strategy, not the service’s — the service just resolves through the pool each send:
  • sticky keeps a recipient on the same sender so two-way threads stay on one number.
  • round_robin spreads volume evenly across pool members.
  • geomatch picks a sender from the recipient’s country when one exists in the pool, falling back to the pool’s remaining senders rather than failing the send.
  • random rotates statelessly per send.
If every sender in the pool degrades or a pool goes empty, the send fails with a sender-resolution error — fix it from the pool health readout rather than reworking your send code. To preempt, preview which sender a recipient would get (GET /messaging/sender-pools/{id}/preview) before routing traffic.

6. Troubleshooting

See also