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

# Outbound country allowlist — a tenant-owned opt-in gate

> The model behind /settings/compliance/country-allowlist: why Orbit imposes no platform-global country block, how the allowed_countries list and allow_all_countries override resolve on every send, and how the gate composes with the fraud stack.

# 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 with `422 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](/api-reference/settings). For a send that
rejected and you want the decision tree, see
[SMS destination blocks](/troubleshooting/sms-destination-blocks).

<Warning>
  This control gates **outbound destinations only**. Checking an inbound
  origin is a different gate — see
  [Inbound Country Gate](/compliance/inbound-country-gate). Nothing on
  this page makes Orbit a compliance regulator for your traffic:
  jurisdiction and content decisions stay yours.
</Warning>

***

## 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 under `settings.fraud` on your organization record decide the
posture:

| Setting               | Meaning                                                                                                                                                      |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `allowed_countries`   | An array of ISO-3166-1 alpha-2 codes, for example `["US","CA","GB"]`. When non-empty, destinations must resolve to a listed country or the send is rejected. |
| `allow_all_countries` | Boolean. When `true`, the gate is explicitly set to "send anywhere" — an on-record override, not just an empty list.                                         |

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:

1. **Non-phone destination** (an email address, a synthetic chat
   identifier): passes. The gate speaks phone channels only.
2. **Resolution fails** (no confident country): passes. The gate never
   rejects on an unresolved input.
3. **`allow_all_countries === true`**: passes. The explicit override
   short-circuits before the list is consulted.
4. **`allowed_countries` is empty or unset**: passes. This is the
   fail-open default — a blank posture blocks nothing.
5. **`allowed_countries` is non-empty and the resolved country is on
   it**: passes.
6. **`allowed_countries` is non-empty and the resolved country is not
   on it**: hard reject, `422 COUNTRY_NOT_ALLOWED`.

Codes are normalized to upper-case ISO-2 and deduped at write time, so
the shape you read back is the shape the gate evaluates. `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-set `allowed_countries` list.

```text theme={null}
no allowlist + no allow-all + destination in high-risk set
  → advisory log (send proceeds)       # platform-global, advisory-only

explicit allowed_countries set + destination off the list
  → 422 COUNTRY_NOT_ALLOWED (hard)     # tenant-owned, enforced
```

If you want the advisory destinations to actually block, you opt in by
configuring the allowlist yourself; that restriction is then
tenant-owned and enforced, because tenant-owned is exactly the class of
control that is permitted to be hard.

***

## 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](/compliance/fraud-shield))
  score a destination and apply `flag` / `block` mode. 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.

Every one of those controls is tenant-owned and defaults open, for the
same reason the allowlist is: Orbit keeps the ledger of what you
decided, and enforces exactly that. The
[tenancy posture audit map](/concepts/tenancy-posture-audit-map)
places this gate on Plane B — tenant opt-in gates — with quiet hours,
DNC/RND, and the attestation floors, and against the handful of
platform asymmetries (the TCPA federal voice window and the
emergency-routing rail) that sit on Plane A. When someone asks "is
country policy platform- or tenant-owned?", the answer is that the
allowlist is Plane B, and nothing on Plane A blocks countries.

***

## 6. Posture checklist

Decide the policy first, then state it explicitly on the org, then keep
the audit map current.

1. **Decide.** Is there a hard "we do not send outside X" statement?
   If yes, set `allowed_countries` to the exact list. If no, set
   `allow_all_countries: true` so the open posture is recorded, not
   accidentally unset.
2. **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.
3. **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.
4. **Keep the audit map current.** Treat a flip of either field like
   any other Plane B toggle: it belongs in the
   [toggle inventory](/compliance/posture-overview) review, and the
   [posture audit map](/concepts/tenancy-posture-audit-map) should show
   your current entry.
5. **Interpret a reject.** `422 COUNTRY_NOT_ALLOWED` with a configured
   list means the system did what you asked. If the reject surprises
   you, walk
   [SMS destination blocks](/troubleshooting/sms-destination-blocks)
   before adding a country.

***

## Related references

* [API Reference → Settings](/api-reference/settings) — the GET/PUT
  endpoint shape and the `COUNTRY_NOT_ALLOWED` response.
* [Tenant compliance defaults model](/concepts/tenant-compliance-defaults-model) —
  the same opt-in-envelope discipline applied to GDPR erasure and
  quiet-hours defaults.
* [Tenancy posture audit map](/concepts/tenancy-posture-audit-map) —
  where this gate sits on the three-plane map.
* [Fraud Shield](/compliance/fraud-shield) — the risk-tier rails the
  allowlist composes with.
* [Inbound Country Gate](/compliance/inbound-country-gate) — the
  counterpart control for inbound origins.
* [SMS destination blocks](/troubleshooting/sms-destination-blocks) —
  the decision tree for a blocked send.
