Skip to content

Campaign Service

The Campaign Service manages the full lifecycle of outreach campaigns — from creation through multi-step email, SMS, and voicemail execution to completion. It lives inside the apps/app monolith and delegates heavy async work to the worker service via BullMQ queues.

Campaign Lifecycle

StatusMeaning
DRAFTBeing configured; not yet running
ACTIVERunning — jobs are being enqueued and sent
PAUSEDTemporarily stopped; pending jobs are cancelled
COMPLETEDAll steps finished
ARCHIVEDHistorical record only

Data Models

ModelPurpose
CampaignsCampaign metadata, status, audience type, AI flag
CampaignStepsOrdered steps (EMAIL / SMS / VOICEMAIL / WAIT) grouped by day
CampaignLeadGroupsMany-to-many between campaigns and lead groups
CampaignLeadsPer-contact enrollment and engagement state
StepExecutionsPer-contact, per-step execution record (sent, opened, replied, etc.)

Campaign Launch Flow

This is the complete path from a user clicking "Launch" to an email arriving in a prospect's inbox.

Step Types

TypeDescription
EMAILSent via Gmail OAuth (sender account rotation)
SMSSent via Twilio
VOICEMAILDelivered via Twilio voicemail drop
WAITIntroduces a delay between groups (e.g., 3 days, 7 days)

Steps are organized into groups (day numbers). All steps in group 0 fire immediately after launch; group 1 fires after 1 day + any WAIT steps, etc.

Credit System

Before launch, the system calculates and reserves credits:

credit_cost = Σ (step_count_per_type × total_contacts)
  • 1 credit = $0.001 (1,000 credits = $1)
  • Plan tiers: Basic (1,000), Standard (10,000), Premium (100,000)
  • Credits are reserved atomically before status changes to ACTIVE. If insufficient, launch is rejected.

Sender Account Rotation

For EMAIL steps, the worker selects a Gmail sender account per contact:

  1. Consistency — reuses the same sender account previously used for this contact (improves deliverability).
  2. Quota check — verifies sendsToday < dailyLimit.
  3. Warmup-aware — accounts in warmup have progressively increasing daily limits; skips accounts at cap.
  4. Fallback — tries up to 3 accounts, sorted by highest remaining quota.
  5. Atomic incrementsendsToday is incremented before sending to prevent over-sending across concurrent workers.

Cron Jobs

JobSchedulePurpose
Email Warmup ResetDaily at midnight UTCResets sendsToday counter on all sender accounts
Follow-up ProcessorPeriodicRe-enqueues follow-up steps for contacts who haven't replied

API Endpoints

MethodPathDescription
POST/v1/campaign/Create campaign (name, audience, lead groups, optional template)
POST/v1/campaign/{id}/launchValidate and launch a DRAFT campaign
POST/v1/campaign/{id}/pausePause an ACTIVE campaign
POST/v1/campaign/{id}/resumeResume a PAUSED campaign
GET/v1/campaign/List campaigns for brand
GET/v1/campaign/{id}Get campaign details with steps and metrics

Full interactive reference: API Documentation