Deliverability Lab
Carrier filtering and regulatory compliance are two different problems. The policy scanner gates on legal rules — TCPA, SHAFT-content, GDPR, India DLT — and it can pass a campaign that carriers still silently filter for looking like spam. The Deliverability Lab fills that gap: it scores the draft campaign body for filtering risk and projects delivery rates per destination carrier from your own history, so “was this filtered?” is a measurement you take before launch, not an inference you make after the fact. The lab runs onPOST /api/v1/campaigns/deliverability-lab. It is read-only: no campaign row is required, nothing sends, no provider is called, and the wallet is untouched. Pass the draft body in the request; re-score on every edit while you compose.
1. The two signals in one report
Each call returns both signals plus a warning roll-up the composer renders directly. Signal one — content filtering-risk lint (content_risk). The body is scanned twice:
- Spam-trigger vocabulary. The shared spam-keyword classifier (
@devotel/compliance’s scanning package — the same engine behind the composer’s live underlines) matches promotional, urgency, and financial vocabulary against the channel’s filtering profile. Email campaigns pass the subject line too. - URL and link heuristics. Layers on top of the keyword scan, because carriers also filter on link shape: public URL shorteners (bit.ly, t.co, goo.gl, and friends), bare IP-address links, plain
http://links, and link-stuffing (three or more links in one message).
score, a bucketed risk_level (low / medium / high / critical), and a verdict of pass, warn, or block. Each finding carries a severity, the matched fragments, and a remediation suggestion.
Signal two — predicted per-carrier delivery (predicted_delivery). The controller aggregates your tenant’s own terminal-status sends per destination operator (per MCCMNC for SMS/MMS, joined to the shared operator catalogue; a single account-level bucket for other channels) over a 7-, 30-, or 90-day window. Each carrier’s observed delivery rate is discounted by a content-risk penalty that scales with the lint score, up to 35 percentage points at a content-risk score of 100. Rates are sample-weighted, so a low-volume carrier cannot swing the headline number; samples under 30 sends are flagged low confidence. When you have no history yet, the lab says so instead of inventing a number.
The roll-up. blocking_warnings lists anything you should fix before launch (a block verdict, or a predicted overall delivery rate at or below 50%); advisories lists non-blocking nudges (a warn verdict, a predicted rate at or below 75%, or carriers projected under the block floor with medium/high confidence). ready_to_send is true when the blocking list is empty. campaigns:read scope is sufficient.
2. Not the policy scanner
The regulatory policy scanner answers “is this send legal?” — TCPA consent, SHAFT-content categories, GDPR lawful basis, India DLT template rules. The Deliverability Lab answers “will carriers let this through?” — vocabulary and link shape vs. your observed per-carrier history. A pre-flight gate firing in the composer can be either one; the report tells you which lens flagged it, so a clean legal posture doesn’t settle the filtering question and a filtering flag isn’t a legal verdict. And the lab’s counterpart for measured (not predicted) truth is the seed lab: register your own test handsets onPOST /api/v1/campaigns/deliverability-seed-lab and score actual terminal deliveries to them. Predict from history with this endpoint; measure with the seed roster; gate legality with the policy scanner.
3. Where it lives
The campaigns create wizard’s Review step runs the lab as part of pre-flight, and the composer re-scores on edit — the same shape as the dry-run (which checks audience, cost, and quiet hours) and audience preview, but scoped to content and carrier risk. Every read in the flow below acceptscampaigns:read; only launch needs campaigns:write.
4. Call it from the API
5. Example: before and after a shortened link
Running the body above returns a blocking result driven by the shared shortener and the urgency/discount vocabulary:https://, and pull the countdown vocabulary:
pass, blocking_warnings empties, ready_to_send returns true, and the predicted per-carrier rates climb back toward their historical baselines. That round-trip — flag, fix, re-score — is the operating loop the lab is built for.
Penalty cheatsheet:
6. Related pre-flight surfaces
- Send a campaign end-to-end — the full lifecycle including the dry-run report.
- Send-gating model and the pre-flight checklist — the admission chain every send walks.
- Policy scanner — the regulatory gate this page deliberately does not replace.
- Contact deliverability health — per-recipient address hygiene, a different axis from campaign-content risk.