Least-cost routing (LCR) policy
For every outbound SMS there are two selection problems: which sender the message goes out from, and which upstream route carries it to the destination operator. Sender resolution owns the first. The LCR policy owns the second — your per-organization preference for ordering Devotel’s wholesale trunk against your own connected (BYO) carriers. This page covers what the policy controls, how routes are scored, and the dry-run quote you can run before saving a change. Routing behaviour only — the request and response schemas live in the API reference.Where LCR sits in the routing chain
LCR evaluates recipients on three inputs — the recipient’s identifier class, the destination it implies, and the per-route price — and runs after sender resolution:- Sender resolution picks the sending identity (a sender pool, an explicit
from, a messaging-service default, or the fallback chain). - LCR upstream selection — the stage this page covers — ranks the wholesale trunk and your BYO carriers for that destination.
- Delivery proceeds over the top-ranked route; route health and circuit breakers then meter every route continuously (see Outbound route quality and circuit breakers).
How routes are scored
Each BYO carrier you have connected for a destination is scored on four axes, multiplied together:
The highest composite score is the route the live gateway prefers. Your policy decides how that scorer-first order relates to the Devotel wholesale entry:
trafficType: "cost"— rank BYO carriers strictly by the cost axis.trafficType: "quality"(default) — rank BYO carriers by the composite score.preferByo: false(default) — the Devotel wholesale trunk leads; BYO carriers follow in scorer order.preferByo: true— every active BYO carrier ranks before the Devotel entry, without you enumerating them.candidateOrder— an explicit list of candidate ids (the reserved iddevotel, and BYO carrier ids) that completely overrides the editorial order. Unknown or stale ids are dropped at evaluation time, and unnamed candidates fold back into scorer order — a misconfigured list degrades, it never errors.
The dry-run quote preview
You don’t have to commit a policy to see what it would do. The quote endpoint ranks routes for a destination and returns the full breakdown:- Request: a destination in E.164 (
to), an optional messagequantity(drives per-segment totals), and an optionalpolicybody. With nopolicy, your saved policy is used; pass one to preview a candidate policy before saving it. - Response:
winnerId/winnerKind, the policy actually in force, anenabledflag, and acandidatesarray in rank order. Each candidate carriesrank(1 = winner), a plain-languagereason(for example “Devotel first (preferByo: false)” or “BYO before Devotel (preferByo)”),estimatedUnitCents/estimatedTotalCentsfor the Devotel entry, andcompositeScorefor BYO entries.
null cents because your upstream spend with that carrier isn’t computable — a fabricated 0 would mislead the preview. GET /messaging/lcr/policy returns the saved policy (or the defaults on absence), and PUT /messaging/lcr/policy upserts yours idempotently.
Common configuration patterns
- Cheapest-first — set
trafficType: "cost"withpreferByo: true. Your lowest-priorityBYO carriers lead, and the Devotel trunk becomes the runner-up rather than the fallback default. - Filtered to a region — scope carriers per-country on the carrier profile (matching by destination MCC list). The quote only considers carriers whose country scope matches the destination, and the Devotel entry is priced for the resolved destination country.
- Sticky incumbents — keep the default
qualitymode: the route a message last succeeded on keeps a small advantage until its health degrades, so near-equal scores don’t cause route flapping.
Auditability
Every policy write is recorded: eachPUT /messaging/lcr/policy call writes an audit entry naming the enabled flag, traffic type, BYO preference, and candidate order, so a route-ordering change is always attributable to a user and a timestamp. Reads also surface the effective policy even when no policy has been saved (the wire defaults).
See also
- Sender resolution — the step LCR runs after: which sender a message goes out from
- Outbound route quality and circuit breakers — continuous per-route health metering and auto-suspension
- How routing picks a sender — and where a reply lands — the two-sided routing reference (outbound chain summary + inbound rules)