Outbound country allowlist
The outbound country allowlist is the hard “if it is not on the list, we will not send” rail for your SMS, messaging-channel, and voice traffic. You set it once on the organization record, and every outbound send that resolves to a phone destination checks it before dispatch. When the destination’s country is resolvable and not on your list, the send rejects with422 COUNTRY_NOT_ALLOWED. When you have set no list, or
when the destination cannot be resolved to a country, the send passes.
This page is the concept guide: what the gate is, why it is deliberately
yours and not the platform’s, and how to keep it honest over time. For
the request/response schema see
API Reference → Settings. For a send that
rejected and you want the decision tree, see
SMS destination blocks.
1. Why there is no platform-global block
Orbit takes a deliberate stance on destination policy: the platform imposes no global country block of any kind, for any channel. There is no list of countries Devotel refuses on your behalf, no embargo rail folded into routing, and no default that decides a whole region is off limits before your sends get a chance. That stance is what makes this gate an opt-in device rather than a restriction you work around. Fraud teams at customers that fan out traffic (OTPs, wallet top-ups, API-driven senders) asked for one hard statement they can make to auditors and to their own engineers: “we do not send outside these countries, ever.” The country allowlist is that rail — it exists so the statement is enforceable, not merely written down. The upshot for a new tenant is that nothing is blocked until you block it; the upshot for a compliance review is that an explicitly-set list is a hard, enforced answer, not a dashboard preference.2. The two settings
Two values undersettings.fraud on your organization record decide the
posture:
Read and write them through
GET / PUT /api/v1/settings/compliance/country-allowlist — the PUT
upper-cases and dedupes codes before persisting, and owner role is
required to write.
allow_all_countries: true exists so the “we intentionally send
anywhere” posture is a decision recorded on the org, not merely an
empty list someone hopes nobody has set. When you see a confusing
reject, check both fields; the checklist at the end of this page names
this explicitly.
3. Resolution model — fail-open until you opt in
On a send, the gate resolves the destination to a country and then decides. The order matters and the defaults are always the open ones:- Non-phone destination (an email address, a synthetic chat identifier): passes. The gate speaks phone channels only.
- Resolution fails (no confident country): passes. The gate never rejects on an unresolved input.
allow_all_countries === true: passes. The explicit override short-circuits before the list is consulted.allowed_countriesis empty or unset: passes. This is the fail-open default — a blank posture blocks nothing.allowed_countriesis non-empty and the resolved country is on it: passes.allowed_countriesis non-empty and the resolved country is not on it: hard reject,422 COUNTRY_NOT_ALLOWED.
422 (rather
than a more alarming 5xx) is deliberate: client SDKs should treat the
reject as the “do not retry” class, parity with carrier blocklist
rejects such as CHANNEL_BLOCKED_DESTINATION.
The gate’s own lookup also fails open. If the settings row cannot be
read at send time, the send proceeds — a database blip must not
black-hole legitimate traffic, and the rest of the fraud chain (IRSF
prefix blocks, velocity caps, wallet admission) still runs downstream.
4. The platform-global reading is advisory-only
There is one piece of platform-global behavior left in the gate, and it is deliberately non-blocking. When a tenant has no allowlist and no allow-all flag, destinations that resolve to a small set of high-risk or sanctioned regions would historically be denied by a bare default. That default is now advisory-only: the send proceeds, and a structured log entry records the country and the reason, so operators and auditors retain visibility without a platform-mandated block. The same posture holds for the OFAC-sanctions read, which runs in the gate’s chain for observability only. Both advisories exist to be read, not obeyed — the only thing that can hard-block a send on this path is your own explicitly-setallowed_countries list.
5. How it composes with the fraud stack
The allowlist sits in the send chain alongside the other outbound protection rails, and it is deliberately placement-scoped, not a replacement for them:- IRSF prefix blocks stop known artificial-traffic prefixes. The allowlist is a coarser country-level rail; the two compose (a destination must survive both).
- Destination blocklists on the messaging side are prefix- or carrier-shaped. The allowlist answers the “never leave these regions” policy a blocklist cannot express.
- Fraud Shield risk tiers (see Fraud Shield)
score a destination and apply
flag/blockmode. The Shield’s verdicts are about risk; the allowlist is about scope. A tenant with a hard “EU only” posture wants the allowlist; a tenant with a hard “watch these risky routes” posture wants the Shield. Most fraud-aware tenants want both, each catching what the other cannot.
6. Posture checklist
Decide the policy first, then state it explicitly on the org, then keep the audit map current.- Decide. Is there a hard “we do not send outside X” statement?
If yes, set
allowed_countriesto the exact list. If no, setallow_all_countries: trueso the open posture is recorded, not accidentally unset. - State the posture on the org. Do not leave both fields empty unless blank-open is the intended answer; either the list or the override should carry your explicit decision.
- Compose with the other rails. Check the destination against prefix blocks and the Fraud Shield separately; the allowlist is one gate in the chain, not the chain.
- Keep the audit map current. Treat a flip of either field like any other Plane B toggle: it belongs in the toggle inventory review, and the posture audit map should show your current entry.
- Interpret a reject.
422 COUNTRY_NOT_ALLOWEDwith a configured list means the system did what you asked. If the reject surprises you, walk SMS destination blocks before adding a country.
Related references
- API Reference → Settings — the GET/PUT
endpoint shape and the
COUNTRY_NOT_ALLOWEDresponse. - Tenant compliance defaults model — the same opt-in-envelope discipline applied to GDPR erasure and quiet-hours defaults.
- Tenancy posture audit map — where this gate sits on the three-plane map.
- Fraud Shield — the risk-tier rails the allowlist composes with.
- Inbound Country Gate — the counterpart control for inbound origins.
- SMS destination blocks — the decision tree for a blocked send.