Campaigns
Campaigns
Create, schedule, and manage bulk messaging campaigns across SMS, Email, and WhatsApp channels.
Overview
Campaigns enable advanced messaging workflows beyond simple one-off sends:
- Scheduled Delivery: Send messages at a specific future date/time
- Multi-Channel: Combine SMS, Email, and WhatsApp in one campaign
- Targeted Recipients: Send to all contacts, selected contacts, or specific groups
- Analytics & Tracking: Monitor delivery rates, failures, and performance
- Draft Management: Save campaigns as drafts before launching
When to Use Campaigns vs Direct Messaging
| Feature | Direct Messaging (/notifications/send) | Campaigns |
|---------|----------------------------------------|-----------|
| Use Case | Quick, one-off messages | Planned bulk messaging |
| Scheduling | Immediate only | Immediate or future date/time |
| Multi-Channel | One channel per request | Multiple channels in one campaign |
| Recipients | Manual or "all" | All, selected contacts, groups, segments |
| Analytics | Per-send logging | Campaign-level metrics |
| State Management | Fire-and-forget | Draft → Scheduled → Active → Completed |
| Reusability | No | Yes (can duplicate/edit) |
Examples:
- ✅ Use Direct Messaging: Password reset, OTP codes, order confirmation
- ✅ Use Campaigns: Product launch, holiday promotions, weekly newsletters
Campaign Types
NotifyHub supports four campaign types:
1. Broadcast
Description: One-time message to a large audience Use Cases: Product launches, flash sales, announcements Example: "New feature release to all users"
2. Targeted
Description: Message to specific groups or selected contacts Use Cases: VIP customer offers, segment-specific updates Example: "Premium discount for VIP group only"
3. Automated
Description: Triggered by events or conditions (future feature) Use Cases: Welcome emails, abandoned cart reminders Example: "Send welcome email 1 hour after signup"
4. Recurring
Description: Repeating campaigns (future feature) Use Cases: Weekly newsletters, monthly reports Example: "Send newsletter every Monday at 9 AM"
Note: Currently, Broadcast and Targeted are fully supported. Automated and Recurring are planned features.
Create Campaign
Create a new campaign and save it as a draft.
Endpoint
POST https://api.notifyhub.com/campaigns
Request
Headers:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Body:
{
"name": "Winter Sale 2026",
"description": "Holiday promotion campaign",
"type": "targeted",
"channels": ["email", "sms"],
"recipients": {
"contacts": ["695f58f41fe77d18e56e232f"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"manual": []
},
"messages": {
"email": {
"subject": "Winter Sale - 50% Off!",
"content": "<h1>Winter Sale!</h1><p>Get 50% off all items this week.</p>"
},
"sms": {
"content": "Winter Sale! 50% off all items. Shop now: https://example.com/sale"
}
},
"scheduleDate": "2026-01-30T10:00:00.000Z"
}Field Descriptions
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Campaign name (internal reference) |
| description | string | No | Campaign description/purpose |
| type | string | Yes | Campaign type: "broadcast", "targeted", "automated", "recurring" |
| channels | array | Yes | Channels to use: ["email"], ["sms"], ["whatsapp"], or combinations |
| recipients | object | Yes | Recipient targeting configuration |
| recipients.contacts | array | No | Array of contact IDs |
| recipients.groups | array | No | Array of group IDs |
| recipients.manual | array | No | Manual phone/email list |
| messages | object | Yes | Per-channel message configuration |
| messages.email | object | No | Email configuration (if "email" in channels) |
| messages.email.subject | string | Yes* | Email subject (*required if email channel used) |
| messages.email.content | string | Yes | Email body (HTML or plain text) |
| messages.sms | object | No | SMS configuration (if "sms" in channels) |
| messages.sms.content | string | Yes | SMS message text |
| messages.whatsapp | object | No | WhatsApp configuration (if "whatsapp" in channels) |
| messages.whatsapp.content | string | Yes | WhatsApp message text |
| scheduleDate | string | No | ISO 8601 date/time (omit for immediate send) |
Recipients Configuration
Send to All Contacts:
{
"recipients": {
"contacts": [],
"groups": [],
"manual": []
}
}Empty arrays mean "all contacts" (backend default: recipientType: "all").
Send to Selected Contacts:
{
"recipients": {
"contacts": ["695f58f41fe77d18e56e232f", "695f58f41fe77d18e56e2330"],
"groups": [],
"manual": []
}
}Send to Group:
{
"recipients": {
"contacts": [],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"manual": []
}
}Send to Manual List (contacts not in database):
{
"recipients": {
"contacts": [],
"groups": [],
"manual": ["+254712345678", "user@example.com"]
}
}Combined (contacts + groups):
{
"recipients": {
"contacts": ["695f58f41fe77d18e56e232f"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"manual": []
}
}Response
Success (201 Created):
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"description": "Holiday promotion campaign",
"type": "targeted",
"channels": ["email", "sms"],
"recipientType": "selected",
"selectedContacts": ["695f58f41fe77d18e56e232f"],
"selectedGroup": "60d5f8e4c3f1a2b3c4d5e6f7",
"messages": {
"email": {
"subject": "Winter Sale - 50% Off!",
"content": "<h1>Winter Sale!</h1><p>Get 50% off all items this week.</p>"
},
"sms": {
"content": "Winter Sale! 50% off all items. Shop now: https://example.com/sale"
}
},
"scheduleDate": "2026-01-30T10:00:00.000Z",
"status": "draft",
"analytics": {
"sent": 0,
"delivered": 0,
"failed": 0,
"opened": 0,
"clicked": 0
},
"organization": "695cc3b0212740bd1dba40d2",
"createdBy": "695cc3b0212740bd1dba40d4",
"createdAt": "2026-01-26T07:06:34.119Z",
"updatedAt": "2026-01-26T07:06:34.119Z"
}Example
cURL:
curl -X POST https://api.notifyhub.com/campaigns \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Winter Sale 2026",
"description": "Holiday promotion",
"type": "broadcast",
"channels": ["email", "sms"],
"recipients": {
"contacts": [],
"groups": [],
"manual": []
},
"messages": {
"email": {
"subject": "Winter Sale!",
"content": "<h1>50% Off Everything!</h1>"
},
"sms": {
"content": "Winter Sale! 50% off. Shop: https://example.com"
}
},
"scheduleDate": "2026-01-30T10:00:00.000Z"
}'JavaScript:
const campaign = {
name: 'Winter Sale 2026',
description: 'Holiday promotion',
type: 'broadcast',
channels: ['email', 'sms'],
recipients: {
contacts: [],
groups: [],
manual: []
},
messages: {
email: {
subject: 'Winter Sale!',
content: '<h1>50% Off Everything!</h1>'
},
sms: {
content: 'Winter Sale! 50% off. Shop: https://example.com'
}
},
scheduleDate: '2026-01-30T10:00:00.000Z'
};
const response = await fetch('https://api.notifyhub.com/campaigns', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(campaign)
});
const created = await response.json();
console.log('Campaign created:', created._id);List Campaigns
Retrieve all campaigns in your organization.
Endpoint
GET https://api.notifyhub.com/campaigns
Response
Success (200 OK):
[
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"type": "broadcast",
"status": "completed",
"channels": ["email", "sms"],
"analytics": {
"sent": 1500,
"delivered": 1450,
"failed": 50,
"opened": 0,
"clicked": 0
},
"createdAt": "2026-01-26T07:06:34.119Z"
},
{
"_id": "6977127a40dbabc9cd8082aa",
"name": "Product Launch",
"type": "targeted",
"status": "scheduled",
"channels": ["email"],
"scheduleDate": "2026-02-01T09:00:00.000Z",
"analytics": {
"sent": 0,
"delivered": 0,
"failed": 0
},
"createdAt": "2026-01-27T14:20:00.000Z"
}
]Example
curl -X GET https://api.notifyhub.com/campaigns \
-H "Authorization: Bearer YOUR_TOKEN"Get Campaign Details
Retrieve full details of a specific campaign.
Endpoint
GET https://api.notifyhub.com/campaigns/:id
Response
Success (200 OK):
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"description": "Holiday promotion campaign",
"type": "broadcast",
"channels": ["email", "sms"],
"status": "completed",
"recipientType": "all",
"messages": {
"email": {
"subject": "Winter Sale!",
"content": "<h1>50% Off Everything!</h1>"
},
"sms": {
"content": "Winter Sale! 50% off. Shop: https://example.com"
}
},
"scheduleDate": "2026-01-30T10:00:00.000Z",
"analytics": {
"sent": 1500,
"delivered": 1450,
"failed": 50,
"opened": 0,
"clicked": 0
},
"createdAt": "2026-01-26T07:06:34.119Z",
"updatedAt": "2026-01-30T10:15:00.000Z"
}Update Campaign
Update campaign details (only allowed for campaigns in "draft" or "scheduled" status).
Endpoint
PUT https://api.notifyhub.com/campaigns/:id
Request
Body (partial update):
{
"name": "Winter Sale Updated",
"messages": {
"sms": {
"content": "NEW: Winter Sale! 60% off (was 50%). Shop: https://example.com"
}
},
"scheduleDate": "2026-01-31T10:00:00.000Z"
}Response
Success (200 OK):
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale Updated",
"messages": {
"email": {
"subject": "Winter Sale!",
"content": "<h1>50% Off Everything!</h1>"
},
"sms": {
"content": "NEW: Winter Sale! 60% off (was 50%). Shop: https://example.com"
}
},
"scheduleDate": "2026-01-31T10:00:00.000Z",
"updatedAt": "2026-01-27T09:30:00.000Z"
}Note: Cannot update campaigns with status "active" or "completed".
Launch Campaign
Execute a campaign immediately or schedule it for later (based on scheduleDate).
Endpoint
POST https://api.notifyhub.com/campaigns/:id/launch
Behavior
If scheduleDate is set:
- Campaign status changes to "scheduled"
- Will execute automatically at the scheduled time (checked every 5 minutes)
If scheduleDate is NOT set:
- Campaign executes immediately
- Status changes to "active" → "completed" when done
Response
Success (200 OK) - Immediate Launch:
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"status": "completed",
"analytics": {
"sent": 1500,
"delivered": 1450,
"failed": 50
},
"updatedAt": "2026-01-30T10:15:00.000Z"
}Success (200 OK) - Scheduled Launch:
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"status": "scheduled",
"scheduleDate": "2026-01-30T10:00:00.000Z",
"updatedAt": "2026-01-27T09:30:00.000Z"
}Example
curl -X POST https://api.notifyhub.com/campaigns/6977127a40dbabc9cd8082a9/launch \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch(
`https://api.notifyhub.com/campaigns/${campaignId}/launch`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }
}
);
const result = await response.json();
console.log('Campaign status:', result.status);Cancel Campaign
Cancel a scheduled campaign before it executes.
Endpoint
POST https://api.notifyhub.com/campaigns/:id/cancel
Response
Success (200 OK):
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"status": "canceled",
"updatedAt": "2026-01-29T15:00:00.000Z"
}Note: Only campaigns with status "scheduled" or "active" can be canceled. Cannot cancel "completed" campaigns.
Example
curl -X POST https://api.notifyhub.com/campaigns/6977127a40dbabc9cd8082a9/cancel \
-H "Authorization: Bearer YOUR_TOKEN"Campaign Status Lifecycle
draft → scheduled → active → completed
↓ ↓
canceled canceled
| Status | Description | Allowed Actions |
|--------|-------------|-----------------|
| draft | Campaign created but not launched | Update, Launch, Delete |
| scheduled | Campaign will execute at scheduleDate | Update, Cancel |
| active | Campaign is currently executing | Cancel (stops remaining sends) |
| completed | Campaign finished executing | View only |
| canceled | Campaign was canceled before completion | View only |
Campaign Analytics
Analytics are automatically updated after campaign execution.
Metrics
| Metric | Description |
|--------|-------------|
| sent | Total messages sent (all channels combined) |
| delivered | Messages successfully delivered |
| failed | Messages that failed to send |
| opened | Email opens (future feature) |
| clicked | Link clicks (future feature) |
Viewing Analytics
Get campaign details:
curl -X GET https://api.notifyhub.com/campaigns/CAMPAIGN_ID \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"_id": "6977127a40dbabc9cd8082a9",
"name": "Winter Sale 2026",
"status": "completed",
"analytics": {
"sent": 1500,
"delivered": 1450,
"failed": 50,
"opened": 0,
"clicked": 0
}
}Delivery Rate Calculation
function calculateDeliveryRate(analytics) {
if (analytics.sent === 0) return 0;
return (analytics.delivered / analytics.sent * 100).toFixed(2);
}
// Example
const rate = calculateDeliveryRate({ sent: 1500, delivered: 1450 });
console.log('Delivery rate:', rate + '%'); // 96.67%Complete Campaign Workflow Example
// 1. Create campaign as draft
const campaign = await fetch('https://api.notifyhub.com/campaigns', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Product Launch',
type: 'targeted',
channels: ['email', 'sms'],
recipients: {
groups: ['vip-customers-group-id']
},
messages: {
email: {
subject: 'New Product Launch!',
content: '<h1>Check out our new product!</h1>'
},
sms: {
content: 'New product just launched! Check it out: https://example.com'
}
},
scheduleDate: '2026-02-01T09:00:00.000Z'
})
}).then(r => r.json());
console.log('Campaign created:', campaign._id);
// 2. Review campaign
const review = await fetch(`https://api.notifyhub.com/campaigns/${campaign._id}`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
console.log('Campaign details:', review);
// 3. Make updates if needed
await fetch(`https://api.notifyhub.com/campaigns/${campaign._id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: {
sms: {
content: 'UPDATED: New product launch! Limited stock: https://example.com'
}
}
})
});
// 4. Launch campaign
await fetch(`https://api.notifyhub.com/campaigns/${campaign._id}/launch`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }
});
console.log('Campaign scheduled for:', review.scheduleDate);
// 5. Check analytics after execution
setTimeout(async () => {
const analytics = await fetch(`https://api.notifyhub.com/campaigns/${campaign._id}`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
console.log('Campaign analytics:', analytics.analytics);
}, 3600000); // Check after 1 hourBest Practices
1. Test Before Launch
Always create a test campaign first:
// Create test campaign to yourself
const testCampaign = await createCampaign({
name: 'TEST - Product Launch',
type: 'targeted',
channels: ['email'],
recipients: {
manual: ['your-email@example.com']
},
messages: {
email: {
subject: 'TEST: New Product Launch',
content: '<h1>This is a test email</h1>'
}
}
});
// Launch immediately
await launchCampaign(testCampaign._id);
// Review email, then create production campaign2. Segment Your Audience
Use groups for targeted messaging:
// Good: Targeted campaigns per segment
await createCampaign({
name: 'VIP Sale',
recipients: { groups: ['vip-group-id'] },
messages: {
email: {
subject: 'Exclusive VIP Sale - 60% Off',
content: '<h1>Our VIP customers get 60% off!</h1>'
}
}
});
await createCampaign({
name: 'Regular Sale',
recipients: { groups: ['regular-group-id'] },
messages: {
email: {
subject: 'Sale - 40% Off',
content: '<h1>Get 40% off this week!</h1>'
}
}
});3. Schedule Strategically
Consider timezone and optimal send times:
// Bad: 3 AM send time
scheduleDate: '2026-02-01T03:00:00.000Z'
// Good: 9 AM send time
scheduleDate: '2026-02-01T09:00:00.000Z'
// Better: Convert from user's timezone
const userDate = new Date('2026-02-01 09:00:00'); // User's local 9 AM
const utcDate = new Date(userDate.toISOString());
scheduleDate: utcDate.toISOString();4. Monitor Delivery Rates
Track performance across campaigns:
async function getCampaignPerformance(token) {
const campaigns = await fetch('https://api.notifyhub.com/campaigns', {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
const completed = campaigns.filter(c => c.status === 'completed');
const performance = completed.map(c => ({
name: c.name,
sent: c.analytics.sent,
deliveryRate: (c.analytics.delivered / c.analytics.sent * 100).toFixed(2) + '%',
failureRate: (c.analytics.failed / c.analytics.sent * 100).toFixed(2) + '%'
}));
console.table(performance);
}Next Steps:
- Message Logs - Track individual message delivery
- Complete API Reference - All endpoints documented