Back to API Reference

Email Campaign API

Base URL: /api/email-campaigns

Overview

The Email Campaign API enables creating, managing, and sending personalized email campaigns using Microsoft Graph integration. Campaigns combine data files, email templates, and Word document attachments for sophisticated email automation.

Authentication

All endpoints require JWT authentication:

Authorization: Bearer 

Key Features

---

Endpoints

POST /api/email-campaigns

Create a new email campaign configuration.

Request:

{

"campaignName": "Q1 Welcome Campaign",

"campaignMode": "broadcast",

"dataFileId": "uuid-of-data-file",

"dataFileName": "customers.csv",

"recipientListId": null,

"emailBodyTemplateId": "uuid-of-html-template",

"emailBodyTemplateName": "Welcome Template",

"attachmentTemplateId": "uuid-of-word-template",

"attachmentTemplateName": "Welcome Packet.docx",

"emailField": "Email",

"subjectField": "SubjectLine",

"defaultSubject": "Welcome to Data Publisher!",

"dataFlow": "single",

"ccField": null,

"bccField": null,

"replyToField": null,

"fromNameField": null,

"graphicLibraryId": "uuid-of-image-library",

"generateAttachments": true,

"attachmentFormat": "pdf",

"trackOpens": true,

"trackClicks": true,

"trackReplies": false,

"testMode": false,

"recordCount": 150,

"staticAttachments": [],

"wizardProgress": 100

}

Required Fields:

Optional Fields:

Success Response (201):

{

"success": true,

"campaign": {

"Id": "uuid-of-campaign",

"UserId": "user-uuid",

"CampaignName": "Q1 Welcome Campaign",

"Status": "draft",

"RecordCount": 150,

"CreatedAt": "2026-02-12T10:30:00Z"

},

"message": "Email campaign created successfully"

}

Validation Errors (400):

{

"success": false,

"error": "Missing required fields: campaignName, emailField"

}

{

"success": false,

"error": "Invalid attachment format. Must be 'docx' or 'pdf'"

}

---

GET /api/email-campaigns

Get all email campaigns for the authenticated user.

Query Parameters:

Example:

GET /api/email-campaigns?status=draft&limit=20

Success Response (200):

{

"success": true,

"campaigns": [

{

"Id": "uuid-1",

"CampaignName": "Q1 Welcome Campaign",

"Status": "draft",

"RecordCount": 150,

"CreatedAt": "2026-02-12T10:30:00Z",

"UpdatedAt": "2026-02-12T10:30:00Z"

},

{

"Id": "uuid-2",

"CampaignName": "Product Announcement",

"Status": "completed",

"RecordCount": 500,

"SentCount": 498,

"FailedCount": 2,

"CreatedAt": "2026-02-10T09:00:00Z",

"CompletedAt": "2026-02-10T11:45:00Z"

}

],

"total": 2,

"limit": 50,

"offset": 0

}

---

GET /api/email-campaigns/:id

Get detailed information about a specific campaign.

URL Parameters:

Success Response (200):

{

"success": true,

"campaign": {

"Id": "uuid-1",

"UserId": "user-uuid",

"CampaignName": "Q1 Welcome Campaign",

"CampaignMode": "broadcast",

"Status": "draft",

"DataFileId": "data-uuid",

"DataFileName": "customers.csv",

"EmailBodyTemplateId": "template-uuid",

"EmailBodyTemplateName": "Welcome Template",

"AttachmentTemplateId": "word-template-uuid",

"AttachmentTemplateName": "Welcome Packet.docx",

"EmailField": "Email",

"SubjectField": "SubjectLine",

"DefaultSubject": "Welcome to Data Publisher!",

"DataFlow": "single",

"GenerateAttachments": true,

"AttachmentFormat": "pdf",

"TrackOpens": true,

"TrackClicks": true,

"RecordCount": 150,

"SentCount": 0,

"FailedCount": 0,

"CreatedAt": "2026-02-12T10:30:00Z",

"UpdatedAt": "2026-02-12T10:30:00Z"

}

}

Error Response (404):

{

"success": false,

"error": "Campaign not found"

}

---

PUT /api/email-campaigns/:id

Update an existing campaign (must be in "draft" status).

URL Parameters:

Request: Same structure as POST, all fields optional

{

"campaignName": "Q1 Welcome Campaign - Updated",

"trackOpens": false,

"testMode": true

}

Success Response (200):

{

"success": true,

"campaign": {

"Id": "uuid-1",

"CampaignName": "Q1 Welcome Campaign - Updated",

"UpdatedAt": "2026-02-12T11:00:00Z"

},

"message": "Campaign updated successfully"

}

Error Responses:

400 - Cannot Edit:

{

"success": false,

"error": "Cannot edit campaign in 'sending' or 'completed' status"

}

---

DELETE /api/email-campaigns/:id

Delete a campaign (cannot delete campaigns that are currently sending).

URL Parameters:

Success Response (200):

{

"success": true,

"message": "Campaign deleted successfully"

}

Error Response (400):

{

"success": false,

"error": "Cannot delete campaign while sending"

}

---

POST /api/email-campaigns/:id/send

Send the email campaign.

URL Parameters:

Request (optional):

{

"testMode": true,

"testRecipients": ["test@example.com"],

"limitRecords": 10

}

Success Response (200):

{

"success": true,

"jobId": "send-job-uuid",

"message": "Campaign sending started",

"estimatedDuration": "15 minutes",

"recipientCount": 150

}

Note: Sending is asynchronous. Use /api/email-campaigns/:id/status to check progress.

---

GET /api/email-campaigns/:id/status

Check campaign sending status and progress.

URL Parameters:

Success Response (200):

{

"success": true,

"status": {

"campaignStatus": "sending",

"progress": 45.5,

"sentCount": 68,

"failedCount": 2,

"remainingCount": 80,

"totalCount": 150,

"startedAt": "2026-02-12T10:45:00Z",

"estimatedCompletion": "2026-02-12T11:00:00Z",

"errors": [

{

"recipient": "invalid@email",

"error": "Invalid email address"

}

]

}

}

---

POST /api/email-campaigns/:id/pause

Pause a sending campaign.

Success Response (200):

{

"success": true,

"message": "Campaign paused",

"sentCount": 75,

"remainingCount": 75

}

---

POST /api/email-campaigns/:id/resume

Resume a paused campaign.

Success Response (200):

{

"success": true,

"message": "Campaign resumed",

"remainingCount": 75

}

---

POST /api/email-campaigns/:id/cancel

Cancel a sending campaign.

Success Response (200):

{

"success": true,

"message": "Campaign cancelled",

"sentCount": 75,

"cancelledCount": 75

}

---

Campaign Modes

Broadcast Mode

Send same email to all recipients with personalized fields.

{

"campaignMode": "broadcast",

"dataFlow": "single"

}

Individual Mode (Future)

One email per record with all data.

---

Attachment Generation

PDF Attachments

{

"generateAttachments": true,

"attachmentFormat": "pdf",

"attachmentTemplateId": "word-template-uuid"

}

Process:

  • Word template populated with data
  • Converted to PDF
  • Attached to email
  • DOCX Attachments

    {
    

    "attachmentFormat": "docx"

    }

    Static Attachments

    {
    

    "staticAttachments": [

    {

    "fileName": "brochure.pdf",

    "fileContent": "base64-encoded-content"

    }

    ]

    }

    ---

    Email Tracking

    Track Opens

    {
    

    "trackOpens": true

    }

    Embeds invisible tracking pixel in emails.

    Track Clicks

    {
    

    "trackClicks": true

    }

    Rewrites links to track click-through.

    Analytics Endpoint:

    GET /api/email-campaigns/:id/analytics

    Response:

    {
    

    "success": true,

    "analytics": {

    "sentCount": 150,

    "openCount": 98,

    "openRate": 65.3,

    "clickCount": 45,

    "clickRate": 30.0,

    "bounceCount": 2,

    "bounceRate": 1.3

    }

    }

    ---

    Test Mode

    Before sending to all recipients, test with a small group:

    {
    

    "testMode": true,

    "testRecipients": ["test1@example.com", "test2@example.com"],

    "limitRecords": 5

    }

    Benefits:

    ---

    Data Field Placeholders

    In email templates and subjects, use {{FieldName}} syntax:

    Subject:

    "Welcome {{FirstName}} to {{CompanyName}}!"

    Email Body HTML:

    Dear {{FirstName}} {{LastName}},

    We're excited to have {{CompanyName}} as a customer!

    Supported Fields:

    ---

    Best Practices

  • Test First: Always use test mode before full send
  • Validate Data: Check email column for valid addresses
  • Monitor Status: Poll /status endpoint during sending
  • Handle Failures: Review error log after campaign
  • Track Performance: Enable opens/clicks for insights
  • Attachment Size: Keep PDFs under 5MB
  • Subject Lines: Keep under 50 characters for best open rates
  • Unsubscribe: Include unsubscribe links (compliance)
  • ---

    Rate Limits

    ---

    Example: Complete Campaign

    const token = 'your-jwt-token';
    
    

    // 1. Create campaign

    const campaign = await fetch('http://localhost:3001/api/email-campaigns', {

    method: 'POST',

    headers: {

    'Authorization': Bearer ${token},

    'Content-Type': 'application/json'

    },

    body: JSON.stringify({

    campaignName: 'Welcome Campaign',

    dataFileId: 'data-uuid',

    dataFileName: 'customers.csv',

    emailBodyTemplateId: 'template-uuid',

    emailBodyTemplateName: 'Welcome Email',

    emailField: 'Email',

    defaultSubject: 'Welcome {{FirstName}}!',

    trackOpens: true,

    trackClicks: true,

    testMode: true

    })

    }).then(r => r.json());

    // 2. Test send

    await fetch(http://localhost:3001/api/email-campaigns/${campaign.campaign.Id}/send, {

    method: 'POST',

    headers: {

    'Authorization': Bearer ${token},

    'Content-Type': 'application/json'

    },

    body: JSON.stringify({

    testMode: true,

    testRecipients: ['test@example.com'],

    limitRecords: 5

    })

    });

    // 3. Check status

    const status = await fetch(http://localhost:3001/api/email-campaigns/${campaign.campaign.Id}/status, {

    headers: { 'Authorization': Bearer ${token} }

    }).then(r => r.json());

    console.log('Progress:', status.status.progress + '%');

    // 4. Full send

    await fetch(http://localhost:3001/api/email-campaigns/${campaign.campaign.Id}/send, {

    method: 'POST',

    headers: {

    'Authorization': Bearer ${token},

    'Content-Type': 'application/json'

    },

    body: JSON.stringify({

    testMode: false

    })

    });

    // 5. Get analytics later

    const analytics = await fetch(http://localhost:3001/api/email-campaigns/${campaign.campaign.Id}/analytics, {

    headers: { 'Authorization': Bearer ${token} }

    }).then(r => r.json());

    console.log('Open rate:', analytics.analytics.openRate + '%');

    ---

    Related APIs