Creating Campaigns
Campaigns are multi-step cold email sequences that automatically send to your leads based on schedules, conditions, and sender rotation rules. This guide walks you through creating your first campaign.
Prerequisites
- At least one verified sending domain
- At least one active sender/mailbox
- At least one lead list with contacts
Creating a Campaign (Dashboard)
Navigate to Campaigns
From the dashboard sidebar, click Campaigns → New Campaign.
Configure campaign settings
Set the following:
- Name — Internal name for your reference
- Status — Start as "Draft" to configure before launching
- Check Reply — Stop sequence if lead replies (recommended: ON)
- Track Opens — Insert invisible pixel for open tracking
- Track Clicks — Wrap links for click tracking
Attach lead lists
Select one or more lead lists to target. Only leads that are not unsubscribed and have valid emails will receive messages.
Assign senders
Select the sender accounts (mailboxes) to use. Cleanmails automatically rotates between them using reputation-weighted selection.
Build your sequence steps
Add one or more email steps. Each step has:
- Subjects — One or more subject lines (for A/B testing)
- Body — HTML email content with personalization tags
- Wait Days/Hours — Delay before sending this step (after previous step)
- Trigger Condition — When to send: always, on_open, on_click, not_opened
Set schedule (optional)
Configure sending windows to only send during business hours:
{
"days": [1, 2, 3, 4, 5],
"start": "09:00",
"end": "17:00",
"timezone": "America/New_York"
}Days are 0-6 (Sunday=0, Monday=1, etc.). Overnight schedules like 22:00 to 06:00 are supported.
Launch
Set status to "running" and optionally set a Launch At date for delayed start. The campaign will begin processing leads immediately (or at the scheduled time).
Creating via API
curl -X POST http://YOUR_SERVER/v1/outreach/campaigns \
-H "Content-Type: application/json" \
-H "Cookie: auth_token=YOUR_SESSION" \
-d '{
"name": "Q2 Outreach",
"status": "running",
"check_reply": true,
"track_opens": true,
"track_clicks": true,
"schedule_config": "{\"days\":[1,2,3,4,5],\"start\":\"09:00\",\"end\":\"17:00\",\"timezone\":\"UTC\"}",
"lists": [{"id": 1}],
"senders": [{"id": 1}, {"id": 2}],
"steps": [
{
"position": 0,
"subjects": "[\"Hey {{FIRST_NAME}}, quick question\", \"{{FIRST_NAME}} — saw your work at {{COMPANY}}\"]",
"body": "<p>Hi {{FIRST_NAME}},</p><p>{I noticed|I saw} your work at {{COMPANY}}...</p>",
"wait_days": 0,
"trigger_condition": "always"
},
{
"position": 1,
"subjects": "[\"Following up\"]",
"body": "<p>Hey {{FIRST_NAME}}, just bumping this to the top...</p>",
"wait_days": 3,
"trigger_condition": "not_opened"
}
]
}'Campaign Lifecycle
| Status | Behavior |
|---|---|
draft | Not processing — safe to edit |
running | Actively sending to leads per schedule |
paused | Stopped — can be resumed |
completed | All leads processed through all steps |
Campaigns automatically move to "completed" when all leads have been processed through the final step and no retries are pending.
If hard bounce rate exceeds 5%, the campaign is automatically paused to protect sender reputation. Fix your list quality before resuming.
How Sending Works
The outreach worker runs every 5 seconds and:
- Finds all campaigns with status "running" that are within their schedule window
- For each campaign, checks which leads need the next step
- Assigns senders using reputation-weighted rotation (healthier senders get more sends)
- Respects daily limits per sender and per-domain rate limits (e.g., 2/sec for Gmail)
- Processes spintax, personalization, and AI tags
- Signs with DKIM, wraps tracking links, adds unsubscribe footer
- Sends via the sender's SMTP credentials
- Logs the delivery and emits events for webhooks/CRM sync