DNC Scrubbing: Sources, Freshness, and the Check Endpoint
A Do-Not-Call scrub answers one question before you send: is this number on a list that blocks or restricts contacting it? Orbit checks your own lists (contact flags, DNC entries, suppression, consent), the platform-wide list, the US federal/state/TCR feeds, and several international national registries — and the same chain the send path enforces is readable as an API, so you can pre-flight a cold list without risking a violating send. This page is the end-to-end picture: when scrubbing matters, how to turn it on, where the synced data comes from, how to read the check endpoint’ssource and last_synced_at, and the one fail-open caveat
you need to manage. For the send-time gates that consume the result,
see Send Gates.
All endpoints below are rooted at
https://api.orbit.devotel.io/api/v1/compliance.
When DNC scrubbing matters
DNC obligations come from more than one registry, and they layer:- US federal DNC (FTC National Registry). Telemarketing calls and marketing texts to a federally registered number are restricted; a scrub against the federal registry is the baseline defense before any outbound campaign.
- US state registries. Several states run their own DNC lists on top of the federal one. A number can be absent federally but registered in, say, Pennsylvania — so a federal-only scrub is not complete for US traffic.
- TCR Universal Opt-Out. The Campaign Registry’s universal opt-out list captures numbers that opted out of A2P texting at the registry level. Honoring it is part of US 10DLC texting hygiene regardless of your own suppression list.
- International national registries. Outside the US, equivalent
national lists apply — the UK TPS and CTPS, Australia’s Do Not Call
Register, India’s NDNC. These are per-jurisdiction: you scrub a UK
campaign against UK registers, which is why the check endpoint
accepts a
countryfilter (below).
Enable the tenant toggle
The check endpoint is off by default per organization. Until you opt in — or until Orbit has a feed synced for the platform — the endpoint returns403 DNC_SYNC_NOT_ENABLED:
dnc_sync_enabled setting — see the
posture map, which lists this toggle
and its default). One flip enables both the single-number check and the
bulk scrub.
The gate auto-retires once feeds are synced. The org toggle is
the acknowledgment that, while no federal feed is synced, Orbit is
not scrubbing against the FTC register for you. Once the platform has
a federal/state/TCR (or international) snapshot synced, the endpoint
serves directly and the 403 gate no longer applies — the
federal_feeds_synced field on every response tells you which state
you’re in. Your own DNC, suppression, and consent enforcement on the
send path is unaffected either way.Where the list comes from (feed wiring)
The synced DNC data arrives from upstream feeds, refreshed daily into the platform-wide DNC list. What an operator configures determines which of thesource values you see back from the check endpoint.
These are operator-level environment variables. On Orbit’s hosted
(SaaS) platform they are set for you; the SaaS operator controls which
feeds are live. They matter to you directly only if you self-host Orbit
— in that case configure them in your deployment:
DEVOTEL_DNC_FEED_FILE— a mounted volume containing a procured federal/state/TCR snapshot. The daily sync reads it, parses each opted-out number, and upserts it into the platform DNC list tagged with its source (federal_dnc,state_dnc:XX, ortcr).DEVOTEL_DNC_FEED_URL— an authenticated download of the same snapshot, as an alternative to a mounted file. File takes precedence when both are set.
DEVOTEL_TCR_API_KEY
together with DEVOTEL_TCR_PARTNER_ID — the daily sync pulls the TCR
Universal Opt-Out registry directly from the partner API and upserts it
as source: "tcr". This gives the TCR scrub from the existing TCR
subscription without an out-of-band CSV.
The same snapshot the daily sync writes to the platform DNC list is
also loaded into memory by the API at boot, so the check endpoint can
answer a federal/state/TCR lookup without waiting for the next daily
write.
federal_feeds_synced: true on the response means that
in-memory feed is live.Read the check endpoint
GET /compliance/dnc/check reports whether one E.164 number is on any
DNC source the send path enforces. It is read-only — it performs no
send.
"on_dnc": false, "source": "none", and an
empty jurisdictions.
The fields that carry the posture:
source— which source produced the first hit, one offederal_dnc,state_dnc(a US state registry),tcr(the TCR Universal Opt-Out),intl_dnc(an international national registry),suppression(your own suppression layer), ornone(not on any list).jurisdictionslists every matching origin, so a number on both the federal registry and a state registry surfaces both.last_synced_at— the freshness timestamp of the matching source: when the federal/state/TCR snapshot (or the row it hit) was last synced. The daily sync stamps a heartbeat row every run, so this field always carries a “last synced” signal for the feed-backed sources rather than going silent when no row matches. Your own suppression/consent sources have no sync, so for a suppression-only hit the field reflects the opt-out event itself.federal_feeds_synced/intl_feeds_synced— whether the API has actually ingested a US federal/state/TCR snapshot and an international national-registry snapshot, respectively. Read these on every response: they distinguish “the number is clear” from “the number is clear and a federal scrub backed that answer.”
country (ISO alpha-2) to scope the
international registry lookup to one jurisdiction:
country=GB, only UK registers (TPS/CTPS) can produce an
international match — a UK-bound campaign is never flagged on an
unrelated country’s record.
Bulk. To scrub a whole list or campaign audience in one call, use
POST /compliance/dnc/scrub with a phones array (up to 500 numbers
per request; duplicates are removed). It runs the same chain per number
and returns per-number verdicts plus on_dnc / clear counts. The
same org gate applies.
How the send side consumes it
The check endpoint is a read of the same chain the send path enforces. You don’t wire the scrub into your sends — Orbit already does:- Messaging (SMS / MMS / WhatsApp / …). Before dispatch, the send path answers “is this recipient opted out?” against the same DNC sources — your contact DNC flag, your DNC list, the suppression list (the cross-channel STOP signal), the platform-wide DNC list (where the daily federal/state/TCR feed lands), and recorded consent opt-outs. A hit drops the send.
- Voice / dialer. The dialer runs the same compliance chain before originating a call — cross-channel STOP, contact DNC, platform DNC, and consent — so a number that opted out by SMS is not then voice-dialed. The send path fails closed: if the compliance check itself can’t complete, the call is deferred rather than dialed.
The fail-open caveat
The read endpoint is fail-open at the source layer: if one DNC source can’t be queried, the check continues to the others and returns the best answer it can. The concrete consequence you must understand:
While no federal feed is synced, a number that is only on the FTC
federal register reads back clear (on_dnc: false).
That is why the endpoint is gated until you opt in, and why
federal_feeds_synced travels on every response. Two operational rules
follow:
- Don’t treat a clear result as a federal safe-harbor unless
federal_feeds_synced: true. A clear verdict withfederal_feeds_synced: falseonly means your own lists, suppression, consent, and the platform list didn’t flag the number. - The strict gate is the send path. The read path is fail-open by design; the send path is not. A false negative from a pre-flight query never becomes a send — the send-time chain re-checks the same sources and blocks what it finds.
federal_feeds_synced: false as “no federal
scrub is backing this answer yet” and weigh that in whether you rely on
the pre-flight for a US campaign. Self-hosters close the gap by
configuring a feed (above).
Verify before a campaign
Pre-flight a campaign audience with the bulk scrub, then act on the verdicts:on_dnc: true numbers from the audience before sending.
Check federal_feeds_synced / intl_feeds_synced on the same response
to know which registries actually backed the verdicts, and check
last_synced_at per result to confirm the data is fresh. For a larger
list, page it in chunks of 500 numbers.
See also:
- Send Gates — the quiet-hours / DNC / RND / RMD send-time gates and emergency stop.
- Batch DNC Pre-Flight Scrubbing — the campaign workflow around the bulk scrub: gating, chunking, and routing flagged numbers.
- Opt-Out & Suppression Lists — how a recipient’s STOP lands on the suppression layer the DNC chain reads.
- Your Tenant Compliance Posture — the
toggle map, including this page’s
dnc_sync_enabledrow.