How DropDialer's BYOC + Drop Cowboy outbound delivery flow actually works
TL;DR — Critical Architecture Fact
The phone numbers we assign to customers are NOT just inbound callback routing. Under our BYOC (Bring Your Own Carrier) setup via Twilio, those numbers serve as the actual outbound caller ID shown on the prospect's phone when they receive a voicemail. Drop Cowboy orchestrates the drop, but the call physically originates through our Twilio SIP trunk, and Twilio enforces that the caller ID is a number on our master account. The pool must scale with paid signups, and every number in PricingConfig.package_allocations is a real, hard deliverable backed by real Twilio inventory.
createCampaign,sendOneOffDrop, or processScheduledDrops).PhoneNumber entity, filtered by assigned_to_email and excluding source: 'byon' (BYON numbers are customer-owned and not on our master Twilio account — using them as caller ID causes Twilio Error 32204).rotationIndex % senderNumbers.length. Each prospect gets a different caller ID for warm-up + reputation distribution./v1/rvm with payload including forwarding_number set to the rotated Twilio number (in E.164 format).forwarding_number is what appears as caller ID on the prospect's phone.twilioVoiceWebhook, and is forwarded to the customer's personal phone via the number's forwarding_number field on the PhoneNumber record.Drop Cowboy's forwarding_number parameter sounds like it's only for inbound forwarding. But under BYOC, the same number serves two purposes:
This is why a customer's plan tier must come with a real, dedicated set of Twilio numbers. The "dedicated sender numbers included" marketing claim on the Checkout page is literal infrastructure, not just an inbound feature.
Counts toward pool
source: 'twilio'provisionInboundNumbersDoes NOT count
source: 'byon') — customer-owned, can't be caller IDpaused or burned health statusSource of truth: PricingConfig.package_allocations[plan].phone_numbers. Defaults (as of May 2026):
| Plan | Numbers per Signup | Drops/mo | Notes |
|---|---|---|---|
| Free Trial | 1 | 100 | Low warm-up; single number |
| Starter | 2 | 750 | Light rotation |
| Growth | 4 | 1,500 | Multi-number reputation balancing |
| Pro | 6 | 3,000 | High volume requires distribution |
| Elite | 15 | 9,000 | "Massive sender pool for warm-up & rotation" |
functions/createCampaign — rotates assigned numbers as caller ID per prospect (lines 687-710, 755-763)functions/sendOneOffDrop — same rotation logic for one-off dropsfunctions/processScheduledDrops — same rotation logic for scheduled batchesfunctions/claimPoolNumbers — assigns available pool numbers to a customer at signup, respecting PricingConfig allocationfunctions/changeStripePlan — provisions additional numbers when a customer upgradesfunctions/provisionInboundNumbers — admin tool to purchase new Twilio numbers into the available poolfunctions/checkSenderPoolHealth — daily automation that alerts admin when available pool runs lowfunctions/senderHealthCheck — daily automation that scores number reputation and auto-pauses burned numbersTwilio Error 32204
Caller ID rejected — happens if a BYON number is passed as forwarding_number. Filter source: 'byon' at every drop site.
Pool depletion at signup
An Elite signup needs 15 free numbers. If pool has fewer, claimPoolNumbers assigns what's available — customer is underprovisioned. checkSenderPoolHealth alerts on low inventory.
Burned number reputation
If a number's 7-day success rate drops below threshold, senderHealthCheck sets health_status: 'burned' and paused_at. That customer is now sending from a smaller effective pool until replacement.
Document history: Written May 22, 2026 after architectural deep-dive during the PricingConfig single-source-of-truth refactor. Resolves prior confusion where the forwarding_number field in DC's API was misinterpreted as inbound-only. The double-duty (caller ID + callback target) was confirmed by code review of createCampaign.js lines 686-710 and the BYON exclusion comment referencing Twilio Error 32204.