Spec map
Home: All V2 Specs · Foundation: Data System (UVP) Mode(s): Relationship Mode, Campaign Mode Related specs: CTAs, Contacts, Data System (UVP), Forms, Polling Engine, Surveys, Tribes
🎯 Goals
Cross-Mode Architecture
- Provide one texting system serving two recipient sources while applying the correct mode-specific compliance ruleset at send time. Dashboard
- Give the user an at-a-glance overview of all campaigns, engagement stats, and active conversations with quick access to start new work. Compose
- Let the user build a compliant, merge-aware, cost-transparent SMS/MMS message with sender selection and mandatory STOP language. Recipients
- Resolve a precise, mode-compliant audience from Tribes, ad-hoc filters, or lists with a transparent eligibility audit before commit. Tech Check
- Serve as the pre-flight compliance and cost commit boundary that validates every aspect of the campaign before send. Status
- Provide real-time visibility and control over an in-progress send with health monitoring and pause/throttle controls. Conversations
- Turn inbound replies into a first-class phone-app-style conversation inbox with keyword handling and team assignment. Automations
- Run durable triggered, drip, opt-in, event, and recurring sends with built-in frequency, quiet-hours, and loop guardrails. Numbers Management
- Acquire, register, and monitor long codes, toll-free, and short codes with health monitoring and 10DLC compliance. Compliance
- Enforce TCPA, 10DLC/TCR, and state SMS rules structurally with opt-in provenance and suppression handling. UVP Provenance
- Write every messaging event to the recipient’s UVP engagement history as a defensible record. Permissions
- Gate send, automate, and number-management capabilities to appropriate roles while allowing safety pausing broadly. Performance & Scale
- Ensure the queue, webhook, and conversation architecture scales while respecting throughput limits.
Mode: Cross-Mode (Relationship + Campaign)
Status: Conceptual Spec — V1 Scope Definition (extends current production system)
Companion specs: vrm-data-system (UVP, contact methods, opt-in status), vrm-tribes (audience), vrm-contacts (Relationship recipient pool), vrm-polling-engine (Campaign recipient pool indirectly), vrm-forms / vrm-surveys / vrm-cta (consent capture inputs), politogy-vrm-brand
1. What This Product Is
A2P Texting (Application-to-Person SMS/MMS) is the messaging engine of Politogy VRM. It is how campaigns deliver SMS messages — outbound broadcasts, conversational replies, automated drips, opt-in confirmations, event reminders, GOTV pushes — to contacts in Relationship Mode and voters in Campaign Mode. One system, two recipient sources, identical UI.
The current production system handles SMS/MMS, message composition, recipient selection, conversations, phone-number purchasing, and 10DLC registration via Telnyx. This spec extends it with:
- Automations (opt-ins, auto-responders, drip campaigns, trigger-based sends)
- Short code purchasing and management
- Campaign Mode recipient support (voters, not just contacts)
- Auto-append of compliance language (STOP=end, etc.)
- Improved Tribes integration (audience selection from Tribes, not just contact lists)
Product thesis: Texting is the highest-engagement channel in political outreach. Open rates above 95%, response rates 5-10×email, near-instant delivery. A campaign that can’t text effectively is a campaign that can’t reach its voters. VRM provides texting that is compliant, automated, conversational, and Tribe-aware — so a precise audience built in Tribes flows into a precise message campaign with one click, complete with automated handling of opt-outs, replies, and follow-up sequences.
2. Cross-Mode Architecture
Texting is a horizontal capability, not mode-specific. One A2P system; two recipient sources.
| Mode | Recipient Pool | Compliance Posture |
|---|---|---|
| Relationship Mode | Account-claimed contacts with SMS opt-in | Marketing/relationship SMS — express written consent required (TCPA) |
| Campaign Mode | Voter-file voters within authorized geography | Political SMS — prior express consent for ringless/auto-dialed messages; manual ATDS-free messages permit broader reach (varies by state) |
The mode determines the audience pool and the compliance ruleset applied. Everything else — composer, conversations, automations, number management, send pipeline — is identical.
2.1 Mode-Aware Send Logic
At send time, the system evaluates each recipient against the active mode’s compliance rules:
- Relationship Mode: every recipient must have a confirmed SMS opt-in record on file with provenance (which Form / Survey / CTA / manual entry captured it, when, with what consent language). Recipients without confirmed opt-in are auto-excluded with a count notice (“Excluded 217 contacts: no SMS opt-in”).
- Campaign Mode: SMS to voters without prior consent is permissible under TCPA only for manually-sent messages or via short codes with proper carrier registration; the system enforces send-method gating (manual-trigger pacing for unconsented recipients; short-code/long-code with consent for automated bulk). State-level political SMS laws apply.
The system enforces these rules at send time, not user discretion. A user cannot send to a non-opted-in recipient via automation in Relationship Mode, period.
2.2 Audience Integration with Tribes
The Recipients tab is fundamentally a Tribe picker. The user selects:
- An existing Tribe (recommended path)
- Or an ad-hoc filter using the same criteria expression language as Tribes
- Or an explicit list (manual upload or paste — capped at 10,000 for the manual path; beyond that, use a Tribe)
When a Tribe is the audience, the system shows live member count + opt-in eligibility (“Tribe ‘PDX Metro Election Security’ contains 487 members; 412 are SMS-eligible”) and applies mode compliance filtering automatically at finalize time.
3. The Defining Distinction — A2P Texting vs. Other Outreach Channels
Texting is one of several outreach channels VRM supports. Honor the distinction:
| Texting (this spec) | Phone Banking | Field Canvassing | ||
|---|---|---|---|---|
| Channel | SMS/MMS | Voice call (live human) | In-person door knock | |
| Throughput per hour | 1,000-10,000+ (depends on number type) | Unlimited | ~30 calls/canvasser | ~25 doors/canvasser |
| Engagement rate | Very high (95%+ open) | Moderate (15-25% open) | Variable (15-40% connect) | High (when home: 30%+ conversation) |
| Compliance | TCPA (strict) | CAN-SPAM (lighter) | TCPA + state DNC | State election laws |
| Conversational | Yes (replies route to inbox) | Yes (replies to inbox) | Yes (real-time) | Yes (in-person) |
| Cost per recipient | $0.005-0.05 | $0.0001-0.001 | $0.05-0.30 | $1.00-5.00 (labor) |
Texting is the engagement workhorse: high reach, moderate cost, conversational. Email is for longer-form content. Phone Banking is for high-touch persuasion. Canvassing is for highest-touch hand-to-hand.
4. The Core Architectural Idea — Campaign as the Atomic Unit
A texting Campaign is the atomic unit of work. A Campaign carries:
| Property | Description |
|---|---|
campaign_id | System unique ID |
account_id, mode | Owning account, mode (relationship / campaign) |
name, description, tags | Organization |
message_content | The SMS/MMS payload (text, media, merge fields) |
sender_pool | Phone numbers / short codes to send from |
recipient_source | Tribe ID, ad-hoc filter, or manual list |
send_mode | immediate, scheduled, trigger_based |
schedule_time / trigger_definition | If scheduled or trigger-based |
automation_config | Drip sequence, auto-responder rules, keyword handlers |
compliance_config | STOP keyword behavior, quiet hours, opt-in audit, regional restrictions |
status | draft, tech_check, scheduled, sending, paused, completed, failed, archived |
metrics | Real-time counts (queued, sent, delivered, failed, opted-out, replied) |
| Provenance | created_by, created_at, last_modified, send_started, send_completed |
A campaign is the durable record. Conversations spawned by a campaign reference back to it for context.
5. The Six-Tab UI
Honors Ben’s specification: Dashboard, Compose, Recipients, Tech Check, Status, Conversations.
| # | Tab | Purpose |
|---|---|---|
| 1 | Dashboard | Start new campaign; see all campaigns; engagement stats; access conversations per campaign |
| 2 | Compose | Build the message; select sender numbers; auto-append compliance language |
| 3 | Recipients | Pick audience from Tribes (mode-aware) or ad-hoc filter |
| 4 | Tech Check | Pre-flight review + commit (send now / schedule / automate) |
| 5 | Status | Real-time send progress |
| 6 | Conversations | Inbound reply inbox + threaded conversation surface |
Each tab is detailed below.
6. Tab 1 — Dashboard
The campaign list and account-level texting overview.
6.1 Headline Strip
- Total Campaigns sent (all-time) + count this month
- Total Recipients Reached (delivered count) + this month
- Reply Rate average across campaigns (last 30 days)
- Opt-Out Rate (last 30 days, with trend indicator — opt-outs are a quality signal)
- Account Credit / Balance (with low-balance warning)
- Active Conversations (unread replies needing attention)
6.2 Campaign List
A sortable, filterable table of all campaigns. Default sort: most recent. Columns:
- Status pill (Draft / Scheduled / Sending / Paused / Completed / Failed / Archived)
- Name
- Mode badge (Relationship / Campaign)
- Send type (Immediate / Scheduled / Automated)
- Sent / Delivered / Failed counts
- Reply count
- Opt-Out count
- Created by
- Last activity
- Actions menu (Open, Duplicate, Pause/Resume, Archive)
Click any row → opens the campaign’s detail view (defaulting to Status tab if Live, Tech Check if Draft, etc.).
6.3 Conversations Quick-Access
A panel showing the most recent inbound replies across all campaigns, with click-through to the Conversations tab. This is the “is anyone talking back to us?” surface that surfaces engagement without requiring the user to dig.
6.4 New Campaign Button
Prominent ”+ New Campaign” CTA at top-right. Opens to Tab 2 (Compose) with a fresh draft. The user can also “Duplicate” an existing campaign as a starting point.
6.5 Engagement Insights Panel
Aggregate analytics:
- Best-Performing Campaigns (by reply rate / delivery rate / conversion rate if linked to a Form/CTA conversion)
- Send Volume Over Time (chart)
- Opt-Out Trend (line chart — flag if trending up)
- Top Reply Keywords (top words/phrases recipients are texting back — V1.5 with light NLP)
7. Tab 2 — Compose
Where the user builds the message.
7.1 Campaign Setup
- Campaign Name (internal label)
- Description / Notes (optional, for team context)
- Tags (organizational)
- Mode Indicator — auto-detected from active mode; user can switch modes here, which resets recipient selection
7.2 Sender Selection
The user picks the phone number(s) and/or short code(s) to send from. The system shows the account’s number pool:
- Long codes (regular 10-digit numbers)
- Toll-free numbers (V1.5+)
- Short codes (shared or dedicated)
Each number/code shows:
- The number
- Type badge (Long / Toll-Free / Short)
- 10DLC registration status (Registered / Pending / Unregistered)
- State of origin (for local-presence routing)
- Throughput tier (msg/sec)
- Health indicators (delivery rate, complaint rate, recent opt-out spike)
Number Cycling for High Throughput: For campaigns where send volume exceeds single-number throughput, the user can select multiple numbers and the system distributes the send across them. Sticky conversation assignment ensures that any given recipient consistently sees messages from the same number — replies route correctly. The assignment is computed by hash of recipient phone + campaign ID.
The system can recommend numbers based on campaign characteristics:
- “For 47,000 recipients, consider using your short code (estimated send time: 8 minutes) or distributing across all 12 long codes (estimated: 23 minutes).“
7.3 The Message Composer
A text editor with SMS-aware features:
- Character counter — shows segment count and breakdown (SMS = 160 chars per segment; concatenated SMS reduces to 153 chars per segment; emoji and special chars can shift to UCS-2 encoding at 70 chars/segment). Cost preview updates in real time.
- Merge fields —
{first_name},{last_name},{custom_field_name},{preferred_name},{address}— substituted at send time per recipient. - Link shortening — paste a long link; system shortens to a Politogy-branded short link (e.g.,
pvrm.co/abc123) and tracks clicks per recipient. - Media attachment — for MMS: drag/drop or upload image (PNG/JPG/GIF), video (MP4 up to ~5MB), audio (MP3), or vCard. Auto-optimized for cellular delivery (compression, resizing).
- Preview panel — shows the message as a recipient will see it on phone-style mockup, with merge fields rendered against a sample recipient.
7.4 Auto-Append of Compliance Language
Critical V1 feature. The system automatically appends a configurable compliance line at the end of every message:
Default: Reply STOP to opt out.
User configurable per-campaign or per-account default:
Reply STOP=end to unsubscribeTxt STOP to end. HELP for help.Msg&data rates may apply. Reply STOP to opt out.
The user can override the default per campaign but cannot disable the append. STOP language is mandatory for TCPA compliance.
7.5 Templates
A library of saved message templates per account. The user can:
- Save current draft as a template
- Insert a template into the composer
- Manage templates (rename, edit, delete, share with account)
- Politogy-curated starter templates for common political workflows: GOTV reminder, event RSVP, petition push, donor ask, volunteer recruitment, opt-in confirmation, etc.
7.6 AI Message Assist (V1.5)
A “Suggest a message” button surfaces AI-drafted message variants based on:
- Campaign intent (the user describes the goal in 1-2 sentences)
- Audience characteristics (pulled from the selected Tribe’s defining attributes)
- Tone preference (urgent / friendly / formal)
The user reviews, picks one, edits. Same AI-as-accelerator pattern as Tribe Builder.
8. Tab 3 — Recipients
Audience selection. Mode-aware.
8.1 Recipient Source Selection
Three options, presented as cards:
Option A — Select a Tribe (recommended):
- Tribe picker with search/filter (same UI as Tribes Library)
- Active mode determines which Tribes are eligible (Relationship Mode shows Relationship + cross-mode-eligible Tribes; Campaign Mode shows Campaign Tribes + cross-mode-eligible)
- On select: show member count + SMS-eligible count
Option B — Build an Ad-Hoc Filter:
- The Tribe Builder UI embedded inline (or the manual filter builder)
- Result becomes a one-time audience for this campaign
- Option to “Save this as a Tribe” for future reuse
Option C — Upload or Paste List:
- CSV upload with phone column
- Paste a list of phone numbers (one per line)
- Max 10,000 for manual paste; CSV up to 50,000 (chunked async)
- System runs identity matching against the UVP — matched recipients become full UVPs in this campaign’s context; unmatched are stored as “phone-only” records (still messageable, but no UVP profile)
8.2 Eligibility Audit (always displayed)
Once a source is selected, the system shows a live eligibility breakdown:
Tribe: "PDX Metro Election Security"
Total members: 487
SMS-eligible (opted in): 412
Excluded — no SMS opt-in: 52
Excluded — opted out (STOP): 18
Excluded — invalid phone: 5
Final audience: 412
The user sees exactly how the audience resolves before committing. No surprises at send time.
8.3 Mode-Specific Compliance Filters
Relationship Mode: strict opt-in required; excluded recipients listed clearly.
Campaign Mode: ATDS rules apply per state; system enforces:
- Manual-mode-only flag for unconsented Campaign recipients (no automation, no scheduled-bulk; user must trigger each send manually if recipient hasn’t opted in)
- State-specific political-SMS restrictions (e.g., quiet hours by recipient time zone)
- Automatic short-code routing for high-volume Campaign sends to bypass long-code throughput limits
8.4 Exclusion Lists
Cross-campaign exclusions:
- Account-level Do Not Contact (DNC) — recipients globally excluded
- Campaign-specific exclusions — “exclude anyone who replied to last week’s campaign”
- Recency suppression — “don’t message anyone messaged in the last 24 hours”
- Suppression by Tribe — “exclude Tribe ‘Already Voted’ from GOTV campaigns”
9. Tab 4 — Tech Check
The pre-flight review and commit boundary.
9.1 The Review Checklist
A structured review surface showing every aspect of the campaign before commit:
Message Review:
- Rendered message preview (multi-device mockup: iOS, Android)
- Segment count + per-recipient cost estimate
- Total estimated cost
- STOP language confirmation (auto-appended; show what will be appended)
- Merge field sample rendering (against 3 sample recipients)
- Media attachment preview
Audience Review:
- Source (Tribe name / ad-hoc filter / list)
- Eligible recipient count
- Mode + compliance posture summary
- Excluded counts with reasons
Sender Review:
- Numbers/short codes selected
- 10DLC registration status confirmation
- Estimated send duration based on selected throughput
- Number cycling assignment (if multiple senders)
Compliance Review:
- Opt-in audit confirmation
- STOP / HELP keyword handlers configured (default: STOP → opt out, HELP → return help text)
- Quiet hours configuration (default: no sends 9pm-8am recipient local time)
- Regional restrictions (any state-specific blocks)
Cost Confirmation:
- Per-segment cost × estimated segments
- Account balance vs. estimated cost
- Low-balance warning if insufficient
9.2 Send Mode Selection
The user chooses one of three commit modes:
Send Now (Immediate):
- Confirms the campaign and queues for immediate dispatch
- Sends begin within seconds
- Status tab is auto-opened
Schedule:
- Pick a date/time
- Time zone — by default UTC, with quick-toggle to “recipient local time” (each recipient receives the message at their local timezone-equivalent of the scheduled time, computed from their address)
- Quiet-hours guardrail: scheduled sends that would land in quiet hours are auto-shifted to the next allowable window with a warning
Automate (Trigger-Based):
- Choose a trigger event (see Section 11 — Automations)
- Configure trigger conditions (specific event, frequency cap, time-of-day window)
- This campaign now becomes a triggered automation; fires whenever the trigger condition is met (until paused or limit reached)
9.3 Compliance Final Check
Before commit, the system runs a final compliance scan:
- Re-validates opt-in status (in case recipients opted out between Recipients tab and now)
- Checks the message text for forbidden content per Telnyx / TCR rules (V1.5 — light pattern check for high-risk terms)
- Re-confirms quiet-hours math against scheduled time
- Verifies sender numbers are still in good 10DLC standing
If any check fails, commit is blocked with a clear error and remediation path.
9.4 Commit
Once the user clicks Commit, the campaign transitions to its next state (Scheduled / Sending / Automation Active). The user is auto-routed to Tab 5 (Status) for Immediate or Scheduled sends, or to the campaign Dashboard for Automation campaigns.
10. Tab 5 — Status
Real-time visibility into the send.
10.1 The Live Counter
A persistent top strip showing:
SENDING — Campaign: "GOTV Reminder #3"
Selected: 4,829 | Queued: 2,217 | Sent: 2,612
Delivered: 2,531 | Failed: 81 | Opted-Out: 14
Progress: 54% complete | Est. completion: 13:42 PT (~21 min)
WebSocket / SSE-driven; updates in real time as the send proceeds.
10.2 Per-Recipient Status Table
A virtualized table of every recipient in the campaign:
- Recipient name + phone
- Status (Queued / Sent / Delivered / Failed / Opted-Out / Replied)
- Sender number used
- Sent timestamp
- Delivery timestamp
- Failure reason if applicable
Filterable by status. Searchable by name/phone. Exportable for audit.
10.3 Live Engagement Panel
As replies start arriving:
- Reply count (climbing)
- “Open Conversations” button → routes to Tab 6 with this campaign’s conversations pre-filtered
- Recent inbound previews (most recent 5 replies, with quick-action buttons)
10.4 Controls
Campaign-level controls available during send:
- Pause — stops queue processing; in-flight messages complete; queued messages hold
- Resume — restarts the queue
- Cancel — pauses + abandons remaining queue; sent messages cannot be recalled (SMS doesn’t support recall)
- Throttle — slow down the send rate (useful if opt-outs spike or carrier flags)
A “Health” indicator on the side warns if delivery rate drops below threshold or opt-outs spike — possible signs of carrier filtering or audience-message mismatch.
10.5 Completion State
Once the campaign completes:
- Final tally shown
- Aggregate metrics computed (delivery rate, reply rate, opt-out rate, cost)
- Link to engagement analytics + conversations
- Option to “Send to non-responders” (creates a follow-up campaign with the same content + recipients who didn’t reply, or with a modified message)
11. Tab 6 — Conversations
The inbound reply surface. Where SMS becomes conversational.
11.1 The Inbox
A list of all conversations (one per recipient who has replied to any campaign in this account). Default sort: most recent reply.
Each conversation row shows:
- Recipient name + avatar
- Phone number
- Last message preview (truncated)
- Last message timestamp
- Unread indicator
- Campaign label (which campaign initiated the conversation)
- Assigned-to (which team member, if assigned)
- Status (Open / Resolved / Snoozed)
Filterable by:
- Unread only
- Assigned to me
- Campaign
- Date range
- Tribe membership
- Keyword (search message content)
11.2 The Thread View
Click a conversation → opens a thread that looks and feels exactly like a phone messaging app:
- Bubbles for inbound (recipient) and outbound (account) messages
- Timestamps
- Media inline (images/video shown directly)
- Delivery status indicators
- Typing indicator (V1.5)
- Read receipts (V2 if/where supported by carriers)
Above the thread:
- Recipient header with name, phone, Tribe memberships, UVP click-through to Contact Card
- “Assign to…” dropdown for team handoff
- “Mark Resolved” / “Snooze” status controls
- Conversation tags
Below the thread:
- Compose field with same composer features as Tab 2 (merge fields, link shortening, attachments)
- Send sends a one-off message from the same sender number that initiated the conversation (sticky)
11.3 Auto-Responders & Keyword Handlers
Standard auto-handlers (always-on by default):
| Keyword | Action |
|---|---|
STOP, END, QUIT, UNSUBSCRIBE, CANCEL | Opt-out: mark UVP as SMS opted-out, send confirmation (“You’ve been unsubscribed. Reply START to opt back in.”), exclude from all future sends |
START, SUBSCRIBE, YES (in opt-in flow context) | Re-opt-in if previously stopped; otherwise context-dependent |
HELP, INFO | Send help text (configurable per account: name of campaign, contact info, opt-out instructions) |
Custom keyword handlers (per campaign or account-default):
DONATE→ reply with donation linkEVENT→ reply with event detailsVOLUNTEER→ reply with sign-up link + add to “Volunteers” Tribe- Custom keywords for any campaign-specific automation
11.4 AI-Suggested Replies (V1.5)
For inbound messages, an AI suggests 2-3 reply variants based on:
- The inbound message content
- The campaign context (what was the original message?)
- The recipient’s UVP attributes (their Tribes, custom fields)
- Account’s tone preferences
User reviews, picks one, edits. Always opt-in to the AI suggestion; never auto-sends.
11.5 Team Assignment
Multi-user accounts: conversations can be assigned to specific team members. Assignee sees the conversation in their “Assigned to Me” view. Assignment history audit-logged. Useful for distributing reply load across volunteers.
11.6 Conversation Resolution
Each conversation has a lifecycle state:
- Open — awaiting reply / response
- Resolved — no further action needed (marked by user)
- Snoozed — temporarily archived with a wake-up date (e.g., “remind me in 3 days”)
- Spam — flagged as spam reply; suppresses recipient from future sends
Resolved/Snoozed conversations are out of the default inbox but searchable.
11.7 Bulk Reply / Macro Responses
For high-volume reply scenarios (a viral campaign), saved macro responses allow one-click sending of pre-written replies to multiple selected conversations. Used carefully — too generic kills the conversational benefit of SMS.
12. Automations — The Engine Behind Triggered Sends
Beyond one-shot campaigns, A2P Texting V1 supports five automation patterns.
12.1 Opt-In Confirmation Flows
When a recipient newly opts in (via Form, CTA, keyword JOIN, etc.), an automated welcome message fires. Configurable per account / per campaign:
- Single opt-in: message sent immediately on capture
- Double opt-in: PIN-style confirmation flow (“Reply YES to confirm” → on YES, mark opted in)
- Welcome sequence: 1-3 messages over 24-72 hours introducing the campaign / candidate / issue
12.2 Auto-Responders (Inbound-Triggered)
When a recipient sends an inbound message matching configured criteria:
- Keyword match (STOP, HELP, custom keywords) → preconfigured response
- AI-classified intent (V1.5): “thank you” / “question” / “complaint” / “opt-out request” → routed action
- No-match: route to inbox for human reply
12.3 Drip Campaigns (Sequential Sends)
A sequence of messages delivered over time to a recipient (or new opt-ins). Configurable:
- Number of steps (up to 10 in V1)
- Delay between steps (hours / days)
- Conditional branches (if recipient replied → branch A; if no reply → branch B)
- Stop conditions (recipient opted out, recipient replied with specific keyword, recipient reached an action goal like donating)
Used for: volunteer onboarding sequence, GOTV countdown (10-day, 5-day, 1-day, election-day messages), donor cultivation, event-attendee follow-up.
12.4 Event-Triggered Campaigns
Campaigns that fire on platform events:
- New Tribe member — recipient added to a specified Tribe → automated welcome
- New Form submission — Form completion triggers a SMS confirmation
- Petition signature — signing a petition triggers a thank-you with next-action
- CTA conversion — converting via a CTA triggers SMS welcome
- Date-based — birthday, voter registration anniversary, election proximity
Each event-triggered campaign has:
- Trigger event definition
- Frequency cap (don’t fire more than once per recipient per N days)
- Quiet hours respect
- Maximum daily send budget (prevents runaway loops)
12.5 Scheduled Recurring Campaigns
For repeated outreach:
- “Every Tuesday at 10am, send our weekly digest to the ‘Engaged Donors’ Tribe”
- “On the 1st of each month, send the monthly newsletter SMS to all opted-in contacts”
Configurable cadence with skip-holiday and skip-quiet-hours guardrails.
12.6 Automation Dashboard
A subview of the main Dashboard showing all active automations:
- Each automation as a row: name, type, trigger, send count (last 30d), opt-out impact, status (Active/Paused)
- Bulk pause/resume
- Performance metrics per automation
- Edit / Duplicate / Archive controls
Automations are durable. They run continuously until paused or until their stop conditions are met.
13. Phone Numbers, Short Codes, and 10DLC Management
A dedicated “Numbers” management surface (accessible from Account Settings or from a sub-tab of the Dashboard).
13.1 Number Acquisition
Long Codes (10DLC):
- Purchase via Telnyx integration
- Search by area code / state / locality
- Auto-register with The Campaign Registry (TCR) via Telnyx API once purchased
- 10DLC use-case selection (Political, Political Tax-Exempt 501(c), Charity, Marketing, etc.)
- Brand + Campaign registration in TCR (some onboarding workflow required; system streamlines this with a guided form)
- Throughput tier negotiation based on use case and TCR vetting score
Toll-Free Numbers (V1.5):
- Purchase via Telnyx
- Toll-free verification process (less stringent than 10DLC)
- Suited for transactional / opt-in confirmation use cases
Short Codes:
- 5-6 digit codes (dedicated to the account or shared)
- Dedicated short code: $1,000+/month plus setup; 6-12 week provisioning; carrier-approved campaign-by-campaign
- Shared short code: lower cost, per-keyword licensing on a Politogy-managed pool, faster provisioning, less brand control
- Politogy facilitates the short code application and ongoing carrier compliance
13.2 Number Pool Management UI
A table view of all the account’s numbers/codes:
| Column | Detail |
|---|---|
| Number / Code | The actual digits |
| Type | Long / Toll-Free / Short |
| Status | Active / Pending / Suspended / Failed |
| Registration | 10DLC TCR status, brand, campaign |
| State of Origin | For local presence |
| Throughput | Max msg/sec |
| Daily Send Volume | Last 24h |
| Health | Delivery rate / complaint rate / opt-out rate (last 30d) |
| Cost | Monthly fee + per-message charges |
| Actions | Configure / Suspend / Release |
13.3 Local Presence Routing
When sending to recipients across multiple states, the system can pick a sender number that matches the recipient’s area code or state — known as local presence. Recipients are more likely to engage with local numbers. Requires the account to own numbers in the relevant states.
V1 implements simple state-match routing. V1.5 adds area-code-level matching where feasible.
13.4 Number Health Monitoring
System continuously monitors per-number performance:
- Delivery rate dropping → flag for review
- Opt-out rate spike → automatic throttle + alert
- Carrier filtering detected (high “delivery_unknown” rate) → flag, suggest 10DLC re-verification or switching numbers
A “Health” panel surfaces problem numbers proactively.
13.5 10DLC Registration Workflow
Streamlined onboarding:
- User chooses to register a long code as 10DLC
- System presents the TCR Brand registration form (pre-filled with account info where possible)
- User submits, system handles Telnyx API call
- User registers a Campaign within the Brand (campaign use case, sample message, opt-in flow disclosure)
- System tracks approval status; once approved, the number is fully ready for A2P sending
- If rejected, system surfaces the rejection reason and helps the user revise
Status tracking: Brand Pending → Brand Approved → Campaign Pending → Campaign Approved → Active.
14. Compliance — Structural, Not Optional
A2P Texting compliance is the difference between a working campaign and a $1,500/violation TCPA settlement. The system enforces compliance at the structural level.
14.1 TCPA Compliance (US)
- Prior express written consent required for marketing/political SMS to consumers under TCPA (Relationship Mode = strict)
- Auto-dialer / ATDS rules for Campaign Mode sends without consent — system enforces manual-trigger pacing or short-code routing
- STOP keyword honored automatically — system processes STOP within 5 seconds, sends confirmation, marks UVP opted-out, blocks all future sends across all campaigns
- HELP keyword honored — system returns configurable help text
- Quiet hours — no sends 9pm-8am recipient local time (configurable, but defaults strictly enforced)
- Frequency limits — max 3 marketing messages per recipient per week unless explicit opt-in to more
14.2 10DLC / TCR Compliance
- Brand + Campaign registration required for long-code A2P
- Use-case must accurately match actual content
- Sample message in registration must match operational messages (no bait-and-switch)
- TCR vetting score affects throughput
14.3 State-Level Political SMS Rules
Several states have additional political-SMS rules (consent thresholds, disclosure requirements, blackout periods near elections). The system carries a per-state ruleset and applies it at send time based on recipient state. Updates as laws change.
14.4 Opt-In Provenance
Every recipient’s SMS opt-in state on the UVP carries:
- Source (which Form / Survey / CTA / manual / import)
- Timestamp
- Consent language presented at capture
- IP address / device fingerprint at capture
- Confirmation status (single vs. double opt-in)
This is the legal record. If a TCPA complaint arrives, the system can produce a defensible audit trail per recipient.
14.5 Suppression Lists
- Global STOP list — anyone who has ever sent STOP is blocked from all sends across all campaigns until they explicitly re-opt-in
- Account-level DNC — recipients added by the account to a permanent do-not-contact list
- Cross-account STOP awareness — V2 consideration; in V1, STOP is per-account (a recipient who STOPs in Account A is not auto-blocked in Account B, but this is a contentious area)
14.6 Carrier Complaint Handling
When a recipient marks a message as spam to their carrier:
- The complaint is reported back to Telnyx, then to VRM
- The recipient is auto-added to the account’s DNC
- If complaint rate exceeds threshold (typically 0.1% of sends), the sender number is throttled or suspended pending review
- Alert raised to account admin
15. UVP Provenance & Message History
Every send and every reply writes to the recipient’s UVP engagement_history substructure:
- Outbound:
{ type: 'sms_sent', campaign_id, message_text, sender_number, sent_at, delivered_at, status } - Inbound:
{ type: 'sms_received', campaign_id (if reply to a campaign), message_text, received_at } - Opt-out:
{ type: 'sms_opt_out', triggered_by: 'STOP_keyword', timestamp, source_campaign_id } - Opt-in:
{ type: 'sms_opt_in', source, consent_language, timestamp }
Visible on the Contact Card’s Engagement tab. Feeds the Tribes Builder (“contacts who replied to last week’s campaign”) and the Polling Engine’s engagement signals.
16. Permissions
Standard role matrix applied to A2P Texting:
| Role | Compose | Send | Schedule / Automate | Conversations | Numbers Mgmt | View Stats |
|---|---|---|---|---|---|---|
| Account Admin | Yes | Yes | Yes | All | Yes | All |
| Account Manager | Yes | Yes (within scope) | Yes (within scope) | Assigned + shared | View only | In scope |
| Field User | No | No | No | Assigned only | No | Limited |
| Viewer | No | No | No | Read-only | No | Read-only |
Send authority and number management are gated to Admin/Manager. Live campaigns can be paused by any user with conversation access (safety — anyone watching can stop a runaway send).
17. Mobile
V1 mobile experience is monitor + reply, not full builder:
- Dashboard (view campaigns)
- Status tab (monitor live sends)
- Conversations tab (full reply functionality — texting on mobile is the natural mobile workflow)
- Campaign creation = desktop V1
V1.5: full mobile parity except for Numbers Management (desktop-only due to 10DLC workflow complexity).
18. V1 / V1.5 / V2 Scope
V1 — Ship (extending current production)
- Six-tab UI (Dashboard, Compose, Recipients, Tech Check, Status, Conversations)
- Cross-mode operation (Relationship + Campaign with mode-appropriate compliance)
- Tribes integration as primary audience source
- Ad-hoc filter audience selection
- Manual list upload (CSV up to 50k async, paste up to 10k)
- Message composer with merge fields, link shortening, MMS attachment, character/segment counter, preview
- Auto-append of STOP language (configurable, mandatory enforcement)
- Sender selection with multi-number cycling and sticky conversation assignment
- Long code support with Telnyx 10DLC registration streamlining
- Short code purchasing and management (dedicated + shared)
- Eligibility audit with mode-specific compliance filtering
- Tech Check pre-flight with cost confirmation, compliance final check, commit gating
- Send modes: Immediate, Scheduled (with timezone awareness), Automated (trigger-based)
- Real-time Status tab with WebSocket-driven counts, per-recipient table, pause/resume/cancel/throttle controls
- Conversations inbox with thread view (phone-app feel), team assignment, resolution states
- Automations: opt-in confirmation flows (single + double opt-in), keyword handlers (STOP/HELP/JOIN/custom), drip campaigns (up to 10 steps), event-triggered campaigns, scheduled recurring
- Quiet hours enforcement, frequency caps, suppression lists
- Number pool management with health monitoring
- Local presence routing (state-level)
- Templates library (Politogy-curated starters + account-saved)
- UVP engagement history writes
- Standard permissions
V1.5 — Near-term Additions
- AI message assist in composer
- AI-suggested replies in conversations
- AI-classified intent for inbound routing
- Light NLP on inbound for top-keyword analytics
- Typing indicators
- Toll-free number support
- Area-code-level local presence
- Rage-spike opt-out detection with auto-throttle
- Mobile parity (campaign creation on mobile)
- “Send to non-responders” follow-up workflow
- Macro responses for bulk reply scenarios
V2 — Defer
- Cross-account STOP awareness (contested area, defer until industry consensus)
- Read receipts (carrier-dependent)
- Conditional message variants (different messages based on recipient attributes — multi-version A/B at send time)
- Predictive send-time optimization (AI picks best send time per recipient based on engagement history)
- Voice + SMS integrated outreach (combine with Phone Banking)
- Conversational AI auto-reply (full LLM-driven responses, with human-handoff escalation)
V3+ — Aspirational
- Cross-channel handoff (SMS conversation continues in email or vice versa)
- Sentiment analysis on inbound replies → automatic UVP signal writes
- Multi-language send with auto-translation per recipient
- RCS support as carriers roll it out
19. Performance & Scale Considerations
19.1 Throughput Math
For a campaign of 100,000 recipients:
- Single registered 10DLC long code at standard throughput (10 msg/sec): ~2.8 hours to send
- 10 long codes in cycling pool at standard throughput: ~17 minutes
- Dedicated short code (100+ msg/sec): ~17 minutes
- Premium 10DLC tier (200+ msg/sec): ~8 minutes per code
The Tech Check tab shows estimated completion time so users can plan accordingly.
19.2 Queue Architecture
V1 architecture:
- Campaign committed → message records inserted into a sends queue table with status=queued
- Workers consume the queue, respecting throughput limits per sender number
- On send: status=sent, sender_number recorded, Telnyx API call dispatched
- Delivery webhook from Telnyx → status updated to delivered/failed
- Inbound webhook → message inserted into inbound table, conversation thread created/updated
19.3 Webhook Handling
Telnyx webhooks for delivery status and inbound messages. The system must:
- Acknowledge webhooks within Telnyx’s timeout (10s)
- Process asynchronously to avoid backpressure
- Handle webhook signature verification
- Retry on transient failures
19.4 Conversation Scaling
For high-volume accounts, the conversation inbox could carry 50k+ open threads. UI uses virtualization + indexed querying. Search across messages uses a dedicated full-text index.
20. Summary Mental Model
A2P Texting is the engagement workhorse of VRM. One system, two modes (Relationship + Campaign), six tabs (Dashboard / Compose / Recipients / Tech Check / Status / Conversations), three sender types (long codes / toll-free / short codes), five automation patterns (opt-in / auto-reply / drip / event-triggered / scheduled-recurring).
The architectural rules:
- Tribes feeds audience — pick a precise segment, not a raw list
- STOP language is mandatory — auto-appended, never disable-able
- Compliance is structural — opt-in audit at send time, quiet hours enforced, frequency caps default-on
- Conversations are first-class — replies route to an inbox that feels like a phone, not a CRM
- Number management is operational — health monitoring, sticky conversation assignment, cycling for throughput
- Cross-mode is one system — Relationship and Campaign modes share UI; mode determines audience pool and compliance ruleset
- Automations are durable — opt-in confirmations, drips, event triggers run continuously without manual operation
The strategic payoff: texting is the highest-engagement channel in modern political outreach, and most campaigns butcher it. They blast generic messages to unconsented numbers, accumulate TCPA risk, and burn relationships through opt-out spikes. VRM texting is the opposite: precise audiences from Tribes, compliant by default, conversational by design, automated where it should be, human where it must be.
North Star: The user picks a Tribe, writes a message, reviews the Tech Check, hits Send. Twenty minutes later they have 412 delivered messages, 23 replies in their inbox, zero compliance risk, and a fully audited UVP record of the engagement. Everything in this spec serves that promise.
Developer Open Questions
These are V1 architectural decisions that need a recommendation before engineering can scope.
-
Provider abstraction layer. Should the messaging layer be hard-coded to Telnyx or abstracted to support Twilio/Bandwidth/etc. later? Recommend abstraction with Telnyx as the V1 implementation — defensive against provider risk and pricing changes.
-
Conversation database scaling. SMS conversations can grow into millions of rows per account. Recommend partitioning by account_id and creating a separate hot/cold storage tier (active threads in hot, resolved-and-snoozed beyond 90 days in cold).
-
Sticky conversation assignment hash. Hash function for assigning a recipient to a sender number in a multi-number campaign? Recommend SHA-256 of (recipient_phone + campaign_id) mod sender_count — deterministic, stable across recomputes.
-
Send rate calibration. Throughput limits per sender number are real but somewhat dynamic. Recommend adaptive send pacing: start at the registered tier, monitor delivery rate, throttle down on degradation, throttle up when stable.
-
MMS storage and delivery. Where do media attachments live? Recommend S3 with signed URLs for Telnyx fetch, retention 90 days (after which Telnyx-side reference goes 404 — recipients have already received the media, retention is for re-send and audit).
-
Quiet hours timezone calculation. Recipient timezone derived from their address. What if the address is missing or ambiguous? Recommend defaulting to the account’s default timezone with a warning at Tech Check.
-
Frequency cap implementation. Per-recipient cap on messages received per day/week. Recommend a Redis-backed counter that increments on send and decrements on cycle expiry; check at send time before each individual recipient.
-
Inbound message routing when recipient is unknown. Someone texts the account’s number who isn’t in any UVP — what happens? Recommend: create a phone-only UVP record, start a conversation thread, surface in inbox with “Unknown sender” label until matched.
-
Number cycling and reply attribution. Recipient receives from number A in a campaign, replies hours later — does the reply route correctly? Recommend sticky assignment is stored on the conversation, not just computed on the fly. Inbound message to number A from recipient X looks up existing thread by phone match first.
-
Short code keyword conflicts. On a shared short code with multiple accounts, what if two accounts both want the keyword “JOIN”? Recommend Politogy-managed keyword allocation; first-come-first-served with periodic review; dedicated short codes bypass this.
-
Trigger-based campaign loop prevention. A trigger campaign fires SMS, the recipient replies, the reply triggers another campaign that sends SMS — infinite loop risk. Recommend a per-recipient daily budget across all automations (default 5 messages/day) with override for true emergencies.
-
Cost tracking and per-campaign accounting. Each campaign accrues cost. Should account balance deduct in real-time or batch nightly? Recommend real-time with optimistic-locking — gives the user immediate cost feedback and supports low-balance halt-send.
-
Carrier-specific delivery quirks. Verizon, AT&T, T-Mobile each have slightly different filtering and throughput. Recommend per-carrier monitoring on the Number Health panel and per-carrier delivery rate stats in campaign analytics.
-
The default STOP language. What is the platform default? Recommend: “Reply STOP to opt out.” (short, clear, TCPA-defensible) with account-level override.
-
Conversation pagination. Long threads (months of back-and-forth) — load fully or paginate? Recommend lazy-load with infinite scroll, most recent 50 messages first.
-
Inbound message classification AI training data. V1.5 AI-classified intent on inbound — where does the training data come from? Recommend: customer-tier labels (user marks “this was a complaint” / “this was a yes / this was an opt-out request”) feed a Politogy-tier classification model over time.
-
Tech Check skip option for power users. Should users with track record of clean sends be able to skip Tech Check and send straight from Compose? Recommend no for V1 — Tech Check is the compliance commit boundary, not optional, regardless of user track record.
-
Time zone resolution failure handling. If a recipient’s timezone can’t be derived (missing address, ambiguous), fall back to account default? Or block from send? Recommend fall back with a Tech Check warning (“23 recipients have unknown timezone; will use account default 9pm-8am quiet hours”).
-
Per-message delivery cost transparency. Telnyx pricing varies by carrier and number type. Show the user exact cost or an estimate? Recommend show estimate with a “may vary up to X%” disclaimer.
-
Re-opt-in friction. A recipient who STOPs in Campaign A — do they need to re-opt-in explicitly to receive Campaign B in the same account? Recommend yes, STOP is account-level not campaign-level (this is the safer TCPA reading); re-opt-in via explicit START keyword or via a new Form/CTA opt-in.
-
Automation editor UX. Configuring a drip campaign with 10 steps and conditional branches is a real workflow design problem. Recommend a visual flow builder (similar to Zapier / n8n) with node-based step composition.
-
Engagement history retention. Per-recipient message history can grow large. Recommend full granularity for 24 months, then summarize older history into aggregate metrics on the UVP (counts, last-sent, last-replied).
-
Toll-free vs. long code routing decision. When the user has both, which should the system recommend by default? Recommend: toll-free for transactional/opt-in confirmation; long code for relational/campaign-style sends. Configurable.
-
Reply-to-non-campaign-number handling. A recipient replies to a number that isn’t currently assigned to any active campaign — what happens? Recommend: create/open conversation thread tagged “unattached,” surface in inbox with notice “Reply to a number not currently assigned to an active campaign.”
End of Spec
This document is the V1 conceptual specification for VRM A2P Texting, extending the existing production system with automations, short codes, cross-mode support, and tighter Tribes integration.
The North Star: precise audiences from Tribes, compliant by default, conversational by design, automated where appropriate, human where required.