Skip to main content

Send Gates

Beyond consent and suppression, several regulatory checks run at send time. Orbit groups them as send gates: each one can hold or drop a message or call before it dispatches. This page covers the gates you configure or query directly. All endpoints below are rooted at https://api.orbit.devotel.io/api/v1/compliance.
DNC and RND scrub against national registers — the FTC federal and state Do-Not-Call registers and the TCR Universal Opt-Out for DNC, and the FCC Reassigned Numbers Database for RND. These are not feeds you wire up or integrate per tenant: when a register snapshot is in place, the platform maintains it centrally rather than reading from your own integration. But the scrub is off by default — each gate reports federal_feeds_synced / feed_synced as false until a snapshot is actually synced for it, and stays behind a per- organization opt-in toggle. Until both are true these endpoints return a disabled response and a number only on a federal register reads back clear (see each gate below for its exact behaviour). This fail-closed-by-default caveat applies to DNC and RND only — the Do-Not-Originate gate ships with an empty baseline, so opting in extends the block list rather than activating a register (see the DNO section below). This page is not legal advice — confirm your TCPA/FCC obligations with counsel.

BAA — the HIPAA send gate

When your organization opts into HIPAA mode (you handle PHI), every outbound send — one-to-one messages and campaign blasts alike — is blocked until an executed, in-term Business Associate Agreement (BAA) is on file. Executing the BAA is the first step in the HIPAA sequence; the send gate is the enforcement backstop that cannot be bypassed. A blocked send returns 422 HIPAA_BAA_REQUIRED with a reason of pending, expired, or not_signed, and the docs_url in the error payload points at the BAA execution flow. A 500 HIPAA_BAA_GATE_DB_FAIL means the gate couldn’t verify BAA status — it fails closed (sends stay blocked) rather than risk a PHI transmission it can’t check. Retry shortly; if the issue persists contact support.
The gate checks the audit trail too: when the BAA status read can’t be validated, the send is blocked and the failure is logged to PHI audit rather than allowed through silently.
An executed BAA has a one-year term; expiry is re-derived from the execution timestamp at send time, so a BAA that aged out blocks again even if the daily expiry-check cron has not run yet. If your organization does not attest HIPAA mode, this gate is a no-op — it only ever inspects organizations that declared PHI is in scope. Follow the full sequence in HIPAA onboarding: from BAA to audit-ready.

Quiet hours

Quiet-hours rules block messages and calls that would land outside a recipient’s permitted local hours (e.g. the TCPA 8 am–9 pm window). Orbit resolves the recipient’s local time from their phone number’s region. GET /quiet-hours/preview tells you whether a send is allowed right now, and when the next allowed time is — use it to schedule around the window.
Quiet-hours gating is opt-in per channel and organization — every channel ships with the toggle off, so a new tenant’s SMS, WhatsApp, and other sends are not held by quiet hours until you enable the gate for that channel. Turn it on per channel from your organization’s quiet-hours settings in the Orbit dashboard; the listed windows then apply automatically. Once enabled, the windows are 08:00–21:00 (recipient-local) for SMS/voice and 09:00–21:00 for WhatsApp/Meta channels unless you set your own start_hour/end_hour. Email, fax, and push are not quiet-hours gated.
US voice TCPA window: advisory for ad-hoc dials, a hard block for campaigns. For outbound voice calls to US (+1) recipients, Orbit evaluates the federal TCPA 8 am–9 pm recipient-local dialing window on every call — but how it enforces the result depends on the call path:
  • Ad-hoc 1:1 dialing from the dashboard is advisory by default. A call outside the window records a structured advisory log but still dispatches. To hold these calls instead, enable the voice quiet-hours toggle for your organization; enabling it applies the 8 am–9 pm window as a hard hold.
  • Campaign and dialer voice traffic is always hard-blocked outside the window, regardless of your tenant settings. A campaign or dialer call placed outside 8 am–9 pm recipient-local is rejected with 422 TCPA_FEDERAL_DIALING_WINDOW_BLOCKED — there is no per-organization opt-out for automated or bulk voice, and the voice quiet-hours toggle does not relax it. If the recipient’s timezone cannot be resolved, the call fails closed and is also blocked.
Schedule campaign and dialer calls inside the recipient-local 8 am–9 pm window — use GET /quiet-hours/preview to find the next allowed time.

DNC — Do Not Call

GET /dnc/check reports whether a number is on a Do-Not-Call list before you dial or text it. For the end-to-end posture — sources, freshness, and the fail-open caveat — see DNC Scrubbing.
When enabled it returns:
The source indicates which layer flagged the number (your contact DNC flag, the DNC list, the suppression list, or a consent opt-out).
The gate applies only while no Do-Not-Call feed is synced. In that state the endpoint is held behind the org setting dnc_sync_enabled (default off) and returns 403 DNC_SYNC_NOT_ENABLED until you opt in — acknowledging that Orbit isn’t yet scrubbing against a federal register for you, so a number only on the FTC list reads back as on_dnc: false.Once Orbit has a federal, state, or TCR snapshot synced, the dnc_sync_enabled gate is bypassed: the endpoint serves directly and federal_feeds_synced returns true. Read that field on every response to confirm whether a federal scrub is actually backing the result.

Batch pre-flight

POST /dnc/scrub runs the same chain against a whole list in one call — up to 500 E.164 numbers per request, with an optional country jurisdiction filter. It returns per-number verdicts plus on_dnc / clear summary counts, is rate-limited to 10 requests per minute per organization, and sits behind the same gate described above.
For the campaign workflow — gating, chunking, routing flagged numbers to suppression, and re-scrub cadence — see Batch DNC Pre-Flight Scrubbing.

Troubleshooting a gated call

When either DNC endpoint holds at 403 DNC_SYNC_NOT_ENABLED:
  1. Confirm the gate state without running a check — call GET /dnc/availability. It reports the exact gate both endpoints enforce: available, your org_opt_in, and federal_feeds_synced.
  2. Enable the org acknowledgment — turn on dnc_sync_enabled in your dashboard compliance settings. The flag is per organization and fails closed: a flag never set, a value stored as a string or number instead of boolean true, or a settings lookup that fails all resolve to OFF — an org that has never visited compliance settings always gets the 403.
  3. Or wait for the snapshot — once the platform syncs a federal, state, or TCR feed, the gate retires by itself and federal_feeds_synced flips to true; the acknowledgment is no longer consulted.
  4. Separate the look-alikes401 is authentication, 422 is a malformed phone, and 429 on /dnc/scrub is its 10-requests-per- minute rate limit, not the gate.
The full walkthrough is Troubleshooting: DNC pre-flight 403.

RND — Reassigned Numbers Database

US phone numbers get reassigned to new people. The FCC’s Reassigned Numbers Database lets you check whether a number was disconnected after the date you obtained consent — a “safe harbor” against texting or calling the wrong person. GET /rnd/check takes the phone and the consent_date (YYYY-MM-DD):
While feed_synced is false this is the only response the endpoint returns, whatever the phone and consent_date — no disconnect dates are on record yet, so every verdict degrades to no_data. status is one of yes, no, or no_data — the FCC database’s verdict for the (phone, consent_date) pair: safe_harbor is true only when status is no. last_disconnect_date is the most-recent permanent-disconnect date on record (null when none), and feed_synced is false until RND feed ingestion is configured — while it is false every verdict is no_data. Gated behind rnd_scrub_enabled (default off); returns 403 RND_SCRUB_NOT_ENABLED while disabled.

Enabling and disabling RND scrubbing

Use PUT /api/v1/compliance/rnd/settings to control the rnd_scrub_enabled flag:
Enabling is blocked with HTTP 409 RND_FEED_NOT_CONFIGURED until the FCC Reassigned Numbers Database feed (SomosGov’s reassigned.us feed) is connected to your deployment. Turning the feature on before the feed is ingested would create a compliance control that performs no actual reassigned-number screening — you’d flip the flag, but every /rnd/check lookup would still return no_data. The 409 block prevents this false sense of protection. Disabling (enabled: false) is always permitted, even if no feed is yet connected.

RMD — Robocall Mitigation Database

US voice originators must file a Robocall Mitigation Database registration describing their STIR/SHAKEN status and mitigation plan. Orbit stores and tracks your filing.
  • GET /rmd — read your registration plus a recertification block with renewal_deadline and action_required.
  • POST /rmd — create or update the filing.
  • POST /rmd/submit → status submitted.
  • POST /rmd/certify → status active.
  • POST /rmd/remediation (with a reason) → status remediation_required.
  • POST /rmd/resolve → back to active.
  • POST /rmd/withdraw → status withdrawn.
stir_shaken_status is complete, partial, or none. A mitigation_plan is required unless status is complete. The lifecycle is draft → submitted → active → remediation_required → active | withdrawn.

Emergency stop

The emergency stop is an org-wide kill switch that immediately halts all outbound SMS, MMS, voice, and dialer traffic — use it during an incident (a misconfigured campaign, a compromised key, a content mistake). For the full operator runbook, see the emergency stop guide.
GET /emergency-stop returns the current active flag plus activated_at, activated_by, and reason. Activation and deactivation require an admin/owner key.
While the emergency stop is active, all outbound SMS, MMS, voice, and dialer campaign traffic for the organization is blocked. Transactional Verify/OTP sends and email are not gated by the emergency stop — they run on separate delivery paths, so a contact can still receive a login code while the switch is active. If you also need to pause those, disable the relevant Verify profile or email sender. Deactivate the stop as soon as the incident is resolved.

Emergency short-code block (VOICE)

Every outbound voice call resolves its destination against the platform-wide emergency short-code table before any SIP leaves the platform — US 911, EU 112, UK 999, AU 000. A destination that matches any of them is rejected pre-dispatch:
  • Error code: 422 EMERGENCY_CALLING_NOT_SUPPORTED
  • Reason payload: the details carry the redacted destination and the matched short code (to, emergency_code) plus a docs_url pointer to the emergency-calling page; a campaign, an ad-hoc dial, and a SIP-trunk origination all take the identical block.
  • Tenant knob: none — the table is a fixed platform constant and the reject is a hard guard. No tenant setting, support request, or API parameter lifts it, and because the block fires pre-flight, no carrier dispatch happens and nothing is billed.
This is the one block on this page a posture review can never frame as “tenant-owned”: unlike the opt-in gates above, you cannot toggle it off, and unlike DNO below, there is no list to curate — the rejected destination is the problem, and the fix is to route the call to a real PSTN number and direct users to dial emergency services from a mobile or landline phone. The full behavior, the E911 rationale, and your operator obligations (disclose the limitation wherever your product surfaces a softphone or agent call flow) are on the Emergency calling page; the Error Code Reference lists the code under Voice.

Do-Not-Originate caller-id reject (VOICE)

After the destination passes the emergency check, the resolved caller-id (the from you present) is screened against the Do-Not-Originate (DNO) list — numbers that must never appear as a calling-party number because they are invalid, unallocated, or inbound-only (spoofed government, bank, or IRS lines; inbound-only toll-free; unassigned ranges). A from matching a DNO entry is hard-rejected at origination time, before dispatch:
  • Error code: 422 VOICE_DNO_BLOCKED
  • Reason payload: a 422 at origination time, before any SIP goes out; matching is prefix-based, so a full E.164 entry matches exactly that number while a shorter prefix matches an unallocated or inbound-only range.
  • Tenant knob: opt-in at the organization level. The platform baseline ships empty by default — there is no universally-safe DNO set, and a bad default would block legitimate caller-ids — so the check is a cheap no-op until you opt in. You curate the list through your organization settings with the same extend / replace / subtract override modes the blocked-prefix layer uses. A settings lookup failure fails open to the (usually empty) platform baseline, deliberately: a transient DB blip must not hold every outbound call.
The fail-default here is the opposite of the DNC/RND caveat at the top of this page: nothing is blocked until you add entries, and errors open rather than close. Present a verified DID you own and the gate is quiet. Configure the list as described in Do-Not-Originate (DNO) Caller-ID Blocking; for a rejected call, follow Troubleshooting: voice destination and emergency blocks.

Per-country voice rate window (VOICE)

Outbound voice also passes a per-destination-country sliding-window rate guard. A burst concentrated on one high-cost country trips the cap even when no single call looked excessive, and the call is rejected:
  • Error code: 429 VOICE_COUNTRY_RATE_LIMITED
  • Reason payload: the body names the country, its per-minute limit, and the window, e.g. { "limit": 60, "country": "GB", "window": "1m" }. The window is sliding (the current minute weighted against the tail of the previous minute), not a hard block.
  • Tenant knob: none to toggle — this is a voice-traffic rail, not a compliance control, and there is no allow-list to edit. Smoothing the send clears it without a config change; the rejected call can dial again as soon as the window rolls over.
It is documented here alongside the gates because it fires on the same pre-dispatch path — and operators routinely misread it as a “compliance block” in posture reviews. It is not one: no regulatory verdict attaches to it, and a campaign pinned at the country limit re-trips on every attempt, so the fix is to pause and distribute, not to retry in place. The fix loop is Troubleshooting: voice destination and emergency blocks.

Preference center

The preference center is a public, token-signed page where a contact manages their own channel opt-ins, message frequency, and (if enabled) requests data deletion — without logging in. Updates flow straight into consent, suppression, and the STOP-fence. Configure it once, then generate a per-contact link. The full walkthrough — every config field, link placement, and the update-flow surfaces — is in the preference center guide:
  • POST /preference-center (admin/owner) — set branding, the channels offered, frequency options, and the GDPR-delete toggle.
  • GET /preference-center — read the current config.
  • POST /preference-center/link with { "contactId": "cnt_…" } — mint a signed link (HMAC-SHA256, 30-day TTL) to email or text to the contact.
The contact then uses the public link (GET/PUT /compliance/preferences/{token}) to view and update their preferences. Opting out here records a consent revocation, adds a suppression entry, and sets the STOP-fence; opting back in reverses it.
Requesting deletion from the preference center records a legacy GDPR deletion request only — it flags the contact for deletion but does not start the tracked DSAR pipeline. It has no SLA clock, no decrypted data export, and no Article-17 erasure certificate. To file a right-to-erasure request that is SLA-tracked, exports the contact’s data, and produces an erasure certificate, use the DSAR endpoint (POST /compliance/dsar, owner/admin only) — see Data Subject Access Requests.

Country rules

GET /country-rules is the read-only regulatory reference behind these gates — per country and channel it reports the allowed sender types, whether Sender-ID registration is none / recommended / required, STOP-keyword requirements, two-way support, DLR support, and default throughput.
Use it to understand, before you launch in a market, what each destination requires — see Country Compliance Requirements for a field-by-field guide to reading this reference.