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 hour

Best 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 campaign

2. 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: