> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sender resolution — the sender pool → from → messaging service fallback chain

> How Orbit picks a sender when more than one source claims it: a sender pool beats a bare from, service-level defaults fill in only when you did not name a sender yourself, and the fallback chain only fires when nothing else named a sender.

# 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 same `POST /messages` body. This page is the authoritative statement of which one wins, what the pool does with its members, and what happens when no source resolves.

## 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.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/sms \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155550100",
    "from": "+14155559999",
    "sender_pool_id": "pool_abc123",
    "body": "Order shipped"
  }'
```

This send uses a member of `pool_abc123`, not `+14155559999`. To pin the sender, pass `from` alone and drop the pool id. Three adjacent rules:

* **Empty `from` counts as omitted.** A `from: ""` body behaves exactly like no `from` at all and falls through to the rest of the chain (this is what the dashboard's "Use account default" option submits).
* **A validated `from` still 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; a `from` that fails that validation returns a 422 with a field-level detail naming `from`.
* **`from_extension` is a sibling of `from`, 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_extension` and `sender_pool_id` are mutually exclusive and sending both returns `422 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:

| Strategy           | How it picks                                                                                              | Fail-safe                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `sticky` (default) | Deterministic per-recipient pick; the assignment is persisted so the same recipient keeps the same sender | —                                                                                                 |
| `round_robin`      | Cycles through members in order                                                                           | Falls back to a deterministic pick if the rotation counter is unavailable — the send never blocks |
| `random`           | Uniform pick, no state                                                                                    | —                                                                                                 |
| `geomatch`         | Matches the recipient's country to a same-country pool member                                             | Falls back to `sticky` over the whole pool when no member matches, so the send never fails        |

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`.

### Common misconfigurations

* **Pool with no senders** — an empty pool returns `422 SENDER_POOL_EMPTY` at send time. Add at least one DID or sender ID to the pool before routing traffic through it.
* **Passing both `from` and `sender_pool_id`** — the pool wins and the explicit `from` is silently ignored. If you expected your explicit `from` to beat the pool you also passed, the pool's pick is used instead. Drop the pool when you want a fixed sender, or drop `from` when 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 `+1` recipient, the carrier may drop the message. Keep per-corridor pools in regions where alphanumeric senders apply.

## 3. Messaging-service default sender fallback

A messaging service binds a default sending identity plus per-message settings (`status_callback`, `validity_period`). 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 `from` or `from_extension` → the service's sender config is ignored for the `from` decision.
* 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.

If the service carries a `country_sender_pools` map, the recipient-country's entry (looked up from `to`) is preferred over the service's default pool — again only when you did not set `sender_pool_id` on the request. Message-level fields always beat service-level config: the service is a fallback, not an override.

For the full service schema, see the [Messaging credentials & services reference](/api-reference/messaging-credentials).

## 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 `from` on 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 `+1` destination 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 no `from`, 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:

1. Your organization's default sender, if one is set for the channel.
2. Your first active phone number.
3. The platform default: a platform phone number for US/Canada (`+1`) destinations, or the `Devotel` alphanumeric sender ID for other destinations.

The US/Canada substitution exists because `+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.

## Troubleshooting quick reference

| Symptom                                                        | Cause                                                      | Fix                                                                                     |
| -------------------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `422 SENDER_POOL_EMPTY`                                        | The pool has no senders                                    | Add a DID or sender ID to the pool                                                      |
| `422` on `from_extension` + `sender_pool_id` together          | The two are mutually exclusive                             | Send only one of them                                                                   |
| Message went out from a pool member, not the `from` you passed | `sender_pool_id` beats a bare `from` by design             | Drop the pool id to pin a fixed sender                                                  |
| US recipient sees an unexpected phone number                   | The `+1` fallback replaced the shared alphanumeric default | Pass an explicit `from` or a pool containing that sender                                |
| Recipient's replies land on a different number                 | A rotating default sender broke two-way                    | Use a `sticky` pool, or reply via the conversation so the sticky inbound sender applies |

## See also

* [Sender pools guide](/guides/sender-pools) — create pools, preview picks, read health
* [Messaging credentials & services](/api-reference/messaging-credentials) — attach a pool as a service's sending identity
* [How routing picks a sender](/concepts/sender-and-routing) — the same chain in compact reference form, plus inbound (MO) routing rules
* [Send and receive messages](/guides/send-receive-messages) — end-to-end walkthrough
