Fail closed
When a compliance check cannot complete, the call does not happen. Only an affirmative pass authorizes a dial, and a stage that cannot answer yields an unknown that resolves to a suppression.
Product · The compliance engine
Every dial passes one gate, and every dial leaves a file: what ran, what your signature covered, what the agent said, and why the call was placed or refused, all of it reconstructible years later from the record alone.
Four controls are enforced in code on every plan, for every tenant, through every entry point. No API field, plan tier, feature flag or support tool reaches them, because they are not settings: a compliance mode can only name checks drawn from a waivable set, and these four are not members of it. Waiving the disclosure opener is not a state anyone can construct, express in JSON, or store.
Why this exists
What happened on this call, on this date, to this number. Most calling stacks answer it by hand, months later, out of logs that were never designed to be read by anyone outside the company. This engine was designed backwards from that letter.
Three tenets govern every mechanism below, and they are worth reading before the mechanisms, because each one is the reason a mechanism has the shape it has.
When a compliance check cannot complete, the call does not happen. Only an affirmative pass authorizes a dial, and a stage that cannot answer yields an unknown that resolves to a suppression.
A model may detect opt-out intent or sensitive content. Only deterministic code may enforce: block a dial, write a suppression row, play a disclosure. The line between those two verbs is the whole architecture.
Every decision must be reconstructible years later from the audit store alone, without access to the live system. A control nobody can prove ran is a control you cannot use in an answer.
Enforced in code · every plan · every entry point
In every mode, for every tenant, on every plan, through every entry point: campaign dials, ad-hoc API calls, and agent test calls alike.
Compiled by the policy engine rather than generated by the model: who is calling, on whose behalf, that the voice is an AI, and the recording announcement where it is required. You supply the values that fill it: company name, agent name, and an optional extra line that can lengthen the opener and never shorten it or replace a required element. The AI sentence is unconditional and cannot be prompt-injected away.
It is played before the model produces its first token, and the ordering is an interlock rather than a convention: the model adapters are held behind a gate the call driver holds no reference to, so reaching the model early raises instead of dialing. If the opener cannot be played, the call ends.
Writes: The opener’s exact text, and playback confirmation by media-stream offset.
A deterministic phrase list and a keypress detector run on every final transcript, with a model classifier for the phrasings the list misses. Either one firing hands control to scripted code, and the model does not get to argue. The phrase list and the closing line it speaks are module constants, not configuration.
The suppression is written and confirmed before the call closes, a fixed graceful close is spoken, the attempt is disposed opt_out, and the suppression cascades across every campaign in your workspace with pending dials cancelled.
Writes: The internal do-not-call entry, the optout.recorded event, and the write itself recorded as written, failed, or not applicable.
Your own suppression list is applied when the list is prepared, and read live again at dial time, never from cache. An opt-out taken during one call suppresses the next dial. If the store behind that read is unavailable, dialing halts rather than proceeding on a stale answer.
The dial-time re-check is a separate read from the batch one on purpose. A list prepared this morning is a photograph; the gate needs the present tense.
Writes: The stage result on the run, and the refusal reason internal_dnc on the attempt.
Validation to E.164, short-code rejection, and dedupe, run as a stage of the pipeline rather than as a pre-step, so it leaves a result like every other stage.
It is the one stage whose own suppression stops the ladder, and for a structural reason rather than a policy one: there is then no number left for the suppression list to be asked about.
Writes: The normalized number and the stage result.
They are precisely the acts a regulator attributes to whoever originated the artificial voice, and that is Vocapable, even when the call leaves your own carrier account, under your own registrations, billed to your own carrier. We compile the disclosure, we synthesize the speech, we decide whether the next dial happens. That is not a duty a contract can hand back, so it is not a setting either. It runs on every plan and is never a paid add-on; the rate card is a separate question from the floor. The difference between a control with no off switch and a setting that has one is worth seeing side by side.
Quiet-hours windows and frequency caps are enforced on every dial too, and they are deliberately not floor controls. They are values, evaluated against a record, against a clock, against a counter, and a value is a different kind of thing from a control with no off state. Counting them in would make this list longer and less true, which is the easiest mistake on this page to make.
The gate
Campaign dials, ad-hoc API calls and agent test calls all evaluate through one dialability evaluator. There is no second implementation and there is no side door: the verified-own-number exemption a test call relies on is an input to that function, not a way around it. The evaluator is pure: it takes an already-gathered picture of the world and returns a verdict plus the evidence for it, which is what makes every branch testable, including the ones that only occur at 8:59pm in an ambiguous area code.
One says this number may not be called at all. The other says the number is fine but this moment, this cadence or this consent basis is not. Collapsing them would leave an evidence export unable to answer the first question a reviewer asks: was this number callable at all, or just not right now?
internal_dnc · consent_insufficient · consent_scope_mismatch · blocked_state · quiet_hours · sunday_ban · no_lawful_window · frequency_cap · platform_test_only
Every stage yields a pass, a suppression, or an unknown, and an unknown resolves to a suppression. A check that cannot complete blocks the call. Uncertainty never resolves in favor of dialing, and a stage that did not run is never recorded as a stage that found nothing.
The worker locks the contact, then a transaction-scoped suppression subject for that exact number, samples its clock only once both locks are held, and reads the gate facts with that fresh time. A revocation that wins the race commits first; the dial worker then observes it, disposes the attempt, and never asks the carrier to originate. Carrier traffic begins only after the seize has committed.
Consent
Consent is a typed entity on the record, not a checkbox column somebody set to true during an import. It has a class, a scope, a source, a proof, and an expiry.
Append-only, and it holds the contact, the class, its scope (purposes, campaign categories, channels), its source, its proof with a content hash, the disclosure text shown where the class demands one, when it was captured, when it expires, and its status. Written consent expires on a schedule you may tighten and never loosen, and expired consent downgrades dialability rather than silently passing.
Consent to appointment reminders does not authorize a sales campaign: a campaign whose purpose falls outside a contact’s scope is suppressed with consent_scope_mismatch. The classes are ranked against the standard in force for the call’s purpose, and a purpose nobody listed takes the strictest standard on file rather than the most convenient one.
One more reason the consent record earns this much machinery: it is the part of the file that speaks directly to whether this person agreed to hear from you. Nothing else in the record does that job, which is why it is typed, scoped, hashed, and read again at dial time instead of trusted from an import.
Revocation
A revocation is one fact about a person, not a per-channel preference. Somebody who says stop calling me has not asked to keep hearing from you somewhere else.
A mid-call opt-out, a keypress, an inbound stop request and your own API call all converge on the same transaction: the internal suppression entry, the optout.recorded event, the withdrawal of the consent standing behind the number, and the dial-time fast path. Not four writes that have to agree afterwards. One write, whose statement order carries the guarantee.
The suppression table has no channel column, so both readers ask it the same question and there is no second lookup to fall out of step. A revocation whose covered set cannot be resolved covers everything: it over-suppresses rather than under-suppresses, which is the only direction this is permitted to err in.
The endpoint refuses one rather than honoring it. Two of those writes are irreversible: the consent ledger is append-only and the dial-time flag is never re-derived, so a time-limited revocation would destroy the consent evidence permanently and then hand the number back as dialable.
47 C.F.R. § 64.1200(a)(10) requires a revocation received through any medium to be honored across every channel the caller uses. The cross-channel portion becomes mandatory on 2027-01-31, after two delays. Vocapable propagates today rather than on that date, and the date itself is recorded as evidence and deliberately not branched on, because gating the behavior on it would mean shipping the non-propagating version first.
That rule allows ten business days to honor a revocation. Ours lands in the same transaction that records it. Those are two different numbers, and neither one is ever quoted as the other: the statutory bar is what a record gets measured against, never a schedule anything is allowed to drift toward.
The attestation
Keep the screening arrangement you already run and the pricing you negotiated for it. Your posture is never locked to a data vendor we picked, and you never pay twice for a lookup you already buy.
Before your first production dial you sign one attestation naming that arrangement. It does not sit in a folder afterwards. Its reference and its signer are written onto your compliance profile and ride into every attempt from then on, so each stage your own arrangement covers arrives in the file as a named election with the document and the person behind it. Six months later, when somebody asks who screened this number, the answer is on the call rather than in an email thread.
The platform will not let that election be half-written. A waiver carrying a reference and no signer is rejected the moment the object is built, so it cannot exist in memory, let alone reach a dial. The database holds the other end of it: a profile carrying waived stages with no attestation reference is a row it will not accept. And an account with nothing signed does not screen clear either. Its contacts screen undialable, with the missing document named, because a missing check with no election is a bug rather than a waiver, and the gate treats it as one.
So your file hands a reviewer three things they can act on: a name, a document, and a date. Follow any of them and you land on a person who signed.
The record
Every attempt, connected or not, placed or refused, produces exactly one policy snapshot. A call with no attempt behind it carries its snapshot on the call instead. One home per call, never both, never neither.
policy_snapshot atmp_01J9…K4T
Product UI · synthetic data
Synthetic tenant, real shape. The amber row is the point of the panel: a stage your own arrangement covers arrives as a signature, never as a silence.
Both are load-bearing, and breaking either one is treated as a defect of the highest severity rather than a cosmetic issue. A check that did not run must never read as a check that found nothing. And a value we applied must never read as a value we vouched for.
So the file names the window, the caps, the consent standard and the recording-consent class that bound the call, and dates the rule pack each one came from. What the file settles is which values bound this dial. What they mean for your program is yours to determine with your own advisors.
The stage results and, for each stage you run upstream, the election with its attestation reference and signer. The consent record relied upon, with its content hash, or the exemption class instead. The quiet-hour and attempt-cap evaluations with the computed contact-local time. If the call connected: disclosure playback confirmed by media-stream offset, recording-consent status, the opt-out and transfer events, the disposition, and the suppression write recorded as written, failed, or not applicable, and that last one is an election rather than a softer failure, because a leg with no called party has no number to suppress.
Compliance evidence is retained at least five years, the four-year statute of limitations plus margin. It is not tenant-configurable and it is excluded from tenant-initiated deletion, because it is the platform’s defense record as much as yours. No database role holds UPDATE or DELETE on the audit log, so the application tier could not rewrite history even by bug; a correction is a new row referencing the one it corrects.
A phone number and a date range is the shape a demand letter arrives in, and it is also the shape of an export filter. Submit a job for the attempt rows and their snapshots, and another for a run’s screening results. A completed job provides a signed CSV download that expires with the artifact it points at. Every row carries the values that bound the call, the consent record it stood on, and the attestation covering each stage your own arrangement runs, with its signer and its date. The export itself lands in the audit log.
Record production is a filter and a job, not a week of somebody’s life.
Before the first dial
Before a campaign can launch you see the run report: the funnel from uploaded records to dialable ones, per-stage suppression counts, the reason on every suppressed row, and the policy versions that bound the evaluation. The records the platform will not call come back as a downloadable export, with the reason beside each one.
The floor stages plus whatever you elected upstream. A suppression short-circuits the stages that would have cost money to perform; the floor stages still run to the end, so every run’s evidence carries an internal do-not-call result. Suppression is not what stops the ladder. Cost is.
Launch is refused until an authorized user acknowledges the report, and that acknowledgment records who, when, and the totals exactly as they were seen. Nobody gets to say later that the numbers were different when they clicked.
Results expire. A campaign paused past the staleness window re-runs incrementally before it resumes, rather than dialing on an answer that was true last month.
Every stage you elected to run upstream appears in this report as waived, with its attestation reference and its signer, and never as a stage that found nothing. That is the same rendering rule the evidence file follows, applied at the point where you can still do something about it.
The division
Quiet-hours windows, frequency caps, consent-basis standards and the recording-consent class are applied at the gate on every attempt, and the values the gate evaluated go into the file. What the law requires of your program where you dial is yours to determine with your own advisors. Applying the values in force on every attempt, and proving afterwards which ones bound the call, is ours.
Every plausible jurisdiction for a number is resolved and applied stricter-only, rather than one being picked: candidates come from the area code, the carrier locale and the address you supplied, and all of them bind, because a 305 number can live in Seattle. The layering can only narrow what is permitted. It never invents a window.
Every production dial goes out on the Twilio account you own: your numbers, your registrations, your negotiated rates, and the caller-ID reputation attached to them. Lists you purchased, rented, or had appended are yours to call, under the Cold Outreach & Data Provenance Waiver you execute, which records that the data is yours under your own supplier agreement and that the consent basis, the jurisdictions and the responsibility for that program stay on your side. Scraped and unauthorized-extraction contacts are refused however they arrive. The four controls above are unchanged by that waiver, and an applicant who declines the AI-disclosure opener is refused, terminally.
Every attempt either clears the gate or lands on the record as a refusal with the reason that produced it. A signature, on the attestation or on the waiver, records who carries which half of the work, so nothing in the division rests on an assumption.
The security posture, the scope of service, and the whole published legal set live on the Trust Center.
The trust close
Here is what we will put in writing. Every call, placed or refused, is reconstructible from the record years later. The calls the platform can detect as ones you should not place do not go out. Both of those still hold on the day somebody asks you to prove them, which is the only day a compliance claim is worth anything.
It is also why the difference between checked, clear, and nobody looked is a design rule here rather than a detail. A record that cannot tell those three apart is not evidence. It is a log.
No, and not because a policy forbids it. A tenant’s compliance mode can only name checks drawn from a waivable set, and these four are not members of it; the unwaivable stages are derived by set difference rather than listed, so they cannot be omitted by an edit. Waiving the disclosure opener is not a state anyone can construct, express in JSON, or store.
On every call. You sign one attestation naming the arrangement you already run, and its reference and its signer go onto your compliance profile and into every attempt from then on. Each stage that attestation covers arrives in the file as a named election carrying the document and the officer who signed it, so the record answers who screened this number and on what date. A waiver missing either half is rejected the moment it is built, a profile carrying waived stages with no attestation reference is a row the database will not accept, and an account with nothing signed screens undialable rather than clear.
The call does not happen. Every stage yields a pass, a suppression, or an unknown, and an unknown resolves to a suppression, and only an affirmative pass authorizes a dial. A check that cannot complete blocks the call, and uncertainty never resolves in favor of dialing. An account carrying no attestation for the stages it runs upstream does not screen clear: its contacts screen undialable, with the missing document named.
In the same transaction that records it. A mid-call opt-out, a keypress, an inbound stop request and your own API call converge on one write path, which lands the internal suppression entry, the event, the withdrawal of the consent standing behind that number and the dial-time fast path together, or lands none of them. An opt-out taken during one call suppresses the next dial.
Every channel it covers. There is one suppression row and it carries no channel column, so both readers ask it the same question and there is no second lookup to fall out of step. A revocation whose covered set cannot be resolved covers everything: it over-suppresses rather than under-suppresses, which is the only direction it is allowed to err in. It also cannot be given an expiry: the endpoint refuses one, because two of those writes are irreversible and a time-limited revocation would destroy the consent evidence permanently and then hand the number back as dialable.
47 C.F.R. § 64.1200(a)(10) requires a revocation received through any medium to be honored across every channel the caller uses, and the cross-channel portion becomes mandatory on 2027-01-31, after two delays. Vocapable propagates today rather than on that date. The date is recorded as evidence and is deliberately not branched on, because gating the behavior on a date would mean shipping the non-propagating version first.
The platform applies them for you. Quiet-hours windows, frequency caps, consent-basis standards and the recording-consent class are enforced at the gate on every attempt, in the contact’s local time, and the values evaluated go into the file. Calling-policy configuration is not available in the portal or API, so nobody on either side loosens a window by accident. What those values mean for your program where you dial is yours to determine with your own advisors; applying them on every attempt and proving it afterwards is ours.
No, on any plan or class. The two local floor stages are excluded from the metered lookups by construction rather than by a billing rule someone remembers to apply, so there is no configuration in which the floor is charged for, or switched off to save money.
You do, with your own advisors. Our half is enforcement and evidence: the gate runs on every attempt, the calls the platform can detect as ones that should not go out are stopped before the carrier is asked to originate anything, and every attempt leaves a file. A signature, on an attestation or on the cold-outreach waiver, records who carries which half, so nothing in the division rests on an assumption.
Open a sandbox account and read a policy snapshot from a call you ran yourself. The floor runs there exactly as it runs in production.