Sender resolution
Every outbound message needs a sender. You can name one on the request, point at a sender pool, or point at a messaging service — and you can sometimes supply more than one of these on the samePOST /messages body. This page is the single source of truth for the whole outbound chain: which source wins, how the pool’s strategy picks exactly one member (and what happens when that pick fails), how per-country pool overrides work, and what happens when no source resolves. How routing picks a sender is the companion page — a compact summary of this chain plus the inbound (MO) rule routing on the other side of the send.
Where this fits
- This page (outbound, full depth) — the complete precedence chain, all four pool strategies with their fail-safes, messaging-service defaults and the per-country
country_sender_poolsmap, channel-specific rules, and the fallback chain. Read this when you need to know exactly which sender a specific send will use, or why a send went out from an unexpected sender. When the question is instead which construct to build — pool, service, or inline sender — that decision belongs to Choosing a sender construct. - How routing picks a sender — the same chain as a compact reference, plus the inbound (MO) side: tenant-level rules that match a received message and route it to a webhook, queue, inbox, team, or SMS menu. Read that page when the question is “where does a reply/inbound message land,” not “which sender goes out.”
1. sender_pool_id beats a bare from
Passing from on the request body names the sender directly — as long as no sender_pool_id travels with it. When you send both from and sender_pool_id on the same POST, the pool resolves after the explicit-from read and wins (Twilio Messaging Service parity: a pool/service reference is an explicit identity choice for the send). The message goes out from the pool’s pick and the from you passed is silently ignored.
pool_abc123, not +14155559999. To pin the sender, pass from alone and drop the pool id. Three adjacent rules:
- Empty
fromcounts as omitted. Afrom: ""body behaves exactly like nofromat all and falls through to the rest of the chain (this is what the dashboard’s “Use account default” option submits). - A validated
fromstill needs to be deliverable. It must be a number your tenant owns, a valid short code, or a registered alphanumeric sender ID for the destination’s rule set; afromthat fails that validation returns a 422 with a field-level detail namingfrom. from_extensionis a sibling offrom, not of the pool. It resolves a UCaaS extension to its DID identity; it cannot be combined with a pool id on the same request —from_extensionandsender_pool_idare mutually exclusive and sending both returns422 VALIDATION_ERROR.
2. sender_pool_id resolution order per strategy
When you pass sender_pool_id (without an explicit from), the pool picks exactly one of its members at send time:
Pool resolution happens before org defaults and platform fallbacks, so a pool id always wins over the fallback chain below. One override to know: if the parent messaging service has
area_code_geomatch enabled, the pool resolves via geomatch even when its own stored strategy is sticky, round_robin, or random.
Each pool member accumulates a health tier from delivery outcomes, and the rotation scheduler auto-swaps a degraded member for a warmed replacement, so rotation keeps preferring senders that deliver. Creating pools, previewing which sender a recipient would get, and reading health are covered in the Sender pools guide.
Common misconfigurations
- Pool with no senders — an empty pool returns
422 SENDER_POOL_EMPTYat send time. Add at least one DID or sender ID to the pool before routing traffic through it. - Passing both
fromandsender_pool_id— the pool wins and the explicitfromis silently ignored. If you expected your explicitfromto beat the pool you also passed, the pool’s pick is used instead. Drop the pool when you want a fixed sender, or dropfromwhen you want pool rotation. - Mixed sender types in one pool — a pool may hold E.164 long codes, short codes, and alphanumeric sender IDs together. Each pick is routed by the member’s type (numeric members go down the numeric path, alphanumeric members down the alphanumeric path), so a mixed pool does not mis-route — but check the destination’s rules before mixing: US and Canada corridors reject alphanumeric MT, so if an alphanumeric member can be picked for a
+1recipient, the carrier may drop the message. Keep per-corridor pools in regions where alphanumeric senders apply.
3. Messaging-service defaults and the per-country pool map
A messaging service binds a default sending identity plus per-message settings (status_callback, validity_period) — the entity itself is defined on Messaging services. When you pass messaging_service_id, the service’s own sender source fills in only if you did not pass a sender yourself:
- You passed
fromorfrom_extension→ the service’s sender config is ignored for thefromdecision. - You passed
sender_pool_id→ your pool wins; the service’s pool is ignored. - You passed neither → the service’s pool becomes the sender source.
The per-country country_sender_pools map
A messaging service can also carry a country_sender_pools map: ISO-3166-1 alpha-2 country code (uppercase) → pool id, up to 250 entries. At send time the recipient’s country is derived from to (or taken from an explicit recipient_country you passed), the map is looked up for that country, and — if it has an entry — that pool is used before the service’s default sender_pool_id. The chain is:
country_sender_pools[<recipient country>]— per-country override poolsender_pool_id— the service’s default pool- Nothing — the send proceeds without a service-supplied pool and falls to the rest of the chain
- The map never overrides you. Both the per-country override and the default pool fill in only when you did not set
sender_pool_idon the request. A pool you passed on the body always wins. - Keep per-country pools corridor-correct. Like pointing each country at the pool you maintain for that corridor — same-country members for geomatch, numeric-only pools for US/Canada entries (see the channel rules below).
4. Channel-specific rules
- WhatsApp — Meta owns the sender: a business-initiated message must use an approved template, and only a message inside the 24-hour session window opened by the user’s last inbound may be free-form. There is no sender pool or arbitrary
fromon this channel; the sender is your WABA phone number, and the template/window rules are what gate the send. - SMS alphanumeric sender ID — in countries where local regulation or carrier practice requires a pre-registered alphanumeric sender ID (much of Europe, the Middle East, and Asia), keep that sender in a pool or pass it as
from; in US/Canada corridors alphanumeric MT is not accepted, so a+1destination falls back to a platform phone number while other destinations use the platform alphanumeric sender (see below). Keep the two pools separate per corridor. - Two-way SMS replies — when you reply on an existing conversation without naming a sender, Orbit pins the sender to the DID the contact originally texted, so the thread stays on one number. This only fires for SMS and only when no
from,from_extension, or pool already named a sender.
5. The fallback chain, when nothing named a sender
With nofrom, no extension, no pool, no service, and no sticky inbound sender, the sender resolves in this order — the first source that produces a sender wins:
- Your organization’s default sender, if one is set for the channel.
- Your first active phone number.
- The platform default: a platform phone number for US/Canada (
+1) destinations, or theDevotelalphanumeric sender ID for other destinations.
+1 carriers reject the shared alphanumeric sender, so the implicit default for a +1 recipient is always a phone number. If you confirm a shared alphanumeric sender for a US send and see a phone number on the delivered message, this is the reason — pass from or a pool to pin the identity instead.
6. Worked example — one send through the whole chain
A tenant with two sender pools and one messaging service sends an order update. The messaging servicems_ops01 carries sender_pool_id: pool_default and a country_sender_pools map { "GB": "pool_gb" }; pool_gb is configured geomatch and holds two UK numbers plus one DE number, while pool_default is sticky and holds two US numbers.
- No explicit sender on the body. No
from, nofrom_extension, nosender_pool_id— nothing in section 1 fires, so the send falls to the messaging service. - The service’s per-country map fires first. The recipient country derived from
+447700900123isGB, andcountry_sender_pools["GB"]is set, sopool_gbwins over the service’s defaultpool_default. - The pool’s strategy picks one member.
pool_gbrunsgeomatch: the recipient’s countryGBmatches the two UK members, and the pick lands on one of them. - The fail-safe never fires here. If neither UK member had been deliverable,
geomatchwould have fallen back tostickyover the whole pool (the DE member included) — the send still picks a member, so it never reaches… - The fallback chain — untouched. The send leaves the chain at step 2’s pool pick; the org default, first active number, and platform default are never consulted.
country_sender_pools has no US entry, so the service’s default pool_default supplies the sender via sticky — a deterministic, persisted pick that keeps the same US recipient on the same sender across sends.
Two ways to short-circuit the walk: pass sender_pool_id on the body to skip the service’s pools entirely (your pool wins), or pass from alone to pin one sender and make the whole pool/service/fallback chain irrelevant.
Troubleshooting quick reference
See also
- TelQ live-number testing model — the deliverability probe to run against the sender this chain resolves, before the first production send
- Choosing a sender construct — the decision model this chain plugs into: pool vs service vs inline sender, and which inbound layer owns a reply
- Unified termination routing — the stage after this chain: resolution picks the sender; termination may still move the message off SMS onto another channel
- How routing picks a sender — the compact two-sided reference: this chain in summary plus inbound (MO) rule routing
- Messaging services — the entity definition: what a service bundles, when its defaults fill in, and its lifecycle
- Sender pools guide — create pools, preview picks, read health
- Messaging credentials & services — attach a pool (or per-country pool map) as a service’s sending identity
- Send and receive messages — end-to-end walkthrough