Campaigns API
Campaign lifecycle management, scheduling, and statistics.
List Campaigns
GET /campaigns
Query Parameters
| Parameter | Type | Description |
|---|---|---|
tenantId | string | Required |
clubId | string | Filter by club |
status | string | DRAFT, SCHEDULED, ACTIVE, PAUSED, COMPLETED, CANCELLED |
type | string | ONE_TIME, RECURRING, TRIGGERED, JOURNEY |
Response: 200 OK
{
"data": [{
"id": "campaign_123",
"name": "Summer Tournament Promo",
"type": "ONE_TIME",
"status": "SCHEDULED",
"channels": ["EMAIL", "SMS"],
"segmentId": "segment_456",
"scheduledAt": "2025-12-20T09:00:00Z",
"targetCount": 500,
"sentCount": 0,
"openRate": null,
"createdAt": "2025-12-14T10:00:00Z"
}]
}
Get Campaign
GET /campaigns/:id
Response: 200 OK
{
"id": "campaign_123",
"tenantId": "tenant_123",
"clubId": "club_456",
"name": "Summer Tournament Promo",
"description": "Promotion for upcoming summer tournament",
"type": "ONE_TIME",
"status": "SCHEDULED",
"channels": ["EMAIL", "SMS"],
"segmentId": "segment_456",
"segmentName": "Active Golfers",
"emailTemplateId": "template_email_123",
"smsTemplateId": "template_sms_456",
"scheduledAt": "2025-12-20T09:00:00Z",
"timezone": "Africa/Johannesburg",
"targetCount": 500,
"sentCount": 0,
"deliveredCount": 0,
"openedCount": 0,
"clickedCount": 0,
"createdBy": "user_123",
"createdAt": "2025-12-14T10:00:00Z",
"updatedAt": "2025-12-14T10:00:00Z"
}
Create Campaign
POST /campaigns
Request Body
{
"tenantId": "tenant_123",
"clubId": "club_456",
"name": "December Newsletter",
"description": "Monthly member newsletter",
"type": "ONE_TIME",
"segmentId": "segment_123",
"channels": ["EMAIL", "SMS"],
"emailTemplateId": "template_email_123",
"smsTemplateId": "template_sms_456",
"timezone": "Africa/Johannesburg"
}
Response: 201 Created
Update Campaign
PATCH /campaigns/:id
Request Body
{
"name": "Updated Campaign Name",
"description": "Updated description",
"segmentId": "segment_789"
}
Response: 200 OK
Note: Only DRAFT campaigns can have their segment or templates changed.
Schedule Campaign
POST /campaigns/:id/schedule
Request Body
{
"scheduledAt": "2025-12-20T09:00:00Z"
}
Response: 200 OK
{
"id": "campaign_123",
"status": "SCHEDULED",
"scheduledAt": "2025-12-20T09:00:00Z",
"targetCount": 500
}
Execute Campaign Immediately
POST /campaigns/:id/execute
Response: 200 OK
{
"id": "campaign_123",
"status": "ACTIVE",
"startedAt": "2025-12-14T10:00:00Z",
"targetCount": 500
}
Pause Campaign
Pauses an active campaign.
POST /campaigns/:id/pause
Response: 200 OK
{
"id": "campaign_123",
"status": "PAUSED",
"pausedAt": "2025-12-14T10:30:00Z",
"sentCount": 250
}
Resume Campaign
Resumes a paused campaign.
POST /campaigns/:id/resume
Response: 200 OK
{
"id": "campaign_123",
"status": "ACTIVE",
"resumedAt": "2025-12-14T11:00:00Z"
}
Cancel Campaign
Cancels a scheduled or active campaign.
POST /campaigns/:id/cancel
Response: 200 OK
{
"id": "campaign_123",
"status": "CANCELLED",
"cancelledAt": "2025-12-14T10:00:00Z",
"sentCount": 0
}
Get Campaign Stats
GET /campaigns/:id/stats
Response: 200 OK
{
"campaignId": "campaign_123",
"targetCount": 500,
"sentCount": 485,
"deliveredCount": 478,
"openedCount": 215,
"clickedCount": 89,
"convertedCount": 12,
"unsubscribedCount": 3,
"bouncedCount": 7,
"deliveryRate": 0.9856,
"openRate": 0.4498,
"clickRate": 0.4140,
"conversionRate": 0.1348,
"byChannel": {
"EMAIL": {
"sent": 485,
"delivered": 478,
"opened": 215,
"clicked": 89,
"bounced": 7
},
"SMS": {
"sent": 380,
"delivered": 375,
"failed": 5
}
},
"timeline": [
{ "hour": "2025-12-14T09:00:00Z", "sent": 100, "opened": 45 },
{ "hour": "2025-12-14T10:00:00Z", "sent": 385, "opened": 120 }
]
}
Get Campaign Interactions
GET /campaigns/:id/interactions
Query Parameters
| Parameter | Type | Description |
|---|---|---|
type | string | SENT, DELIVERED, OPENED, CLICKED, CONVERTED, UNSUBSCRIBED, BOUNCED |
skip | number | Offset |
take | number | Limit |
Response: 200 OK
{
"data": [{
"id": "interaction_123",
"customerId": "customer_456",
"customerEmail": "john@example.com",
"customerName": "John Smith",
"type": "CLICKED",
"channel": "EMAIL",
"occurredAt": "2025-12-14T09:15:30Z",
"metadata": {
"linkId": "link_123",
"linkUrl": "https://example.com/offer"
}
}],
"meta": { "total": 89, "skip": 0, "take": 25 }
}
Campaign Types
ONE_TIME
Single send to a segment at a specific time.
{
"type": "ONE_TIME",
"segmentId": "segment_123",
"scheduledAt": "2025-12-20T09:00:00Z"
}
RECURRING
Repeating campaign on a schedule.
{
"type": "RECURRING",
"segmentId": "segment_123",
"schedule": {
"frequency": "weekly",
"dayOfWeek": 1,
"time": "09:00",
"timezone": "Africa/Johannesburg"
}
}
TRIGGERED
Sent in response to an event.
{
"type": "TRIGGERED",
"triggerEvent": "scl.member.tier.changed",
"triggerConditions": {
"reason": "upgrade"
}
}
JOURNEY
Part of a multi-step journey (managed via Journeys API).
Status Transitions
DRAFT → SCHEDULED → ACTIVE → COMPLETED
↘ PAUSED ↗
↘ CANCELLED
| From | To | Action |
|---|---|---|
| DRAFT | SCHEDULED | POST /campaigns/:id/schedule |
| DRAFT | ACTIVE | POST /campaigns/:id/execute |
| SCHEDULED | ACTIVE | Automatic at scheduled time |
| SCHEDULED | CANCELLED | POST /campaigns/:id/cancel |
| ACTIVE | PAUSED | POST /campaigns/:id/pause |
| ACTIVE | COMPLETED | Automatic when all messages sent |
| PAUSED | ACTIVE | POST /campaigns/:id/resume |
| PAUSED | CANCELLED | POST /campaigns/:id/cancel |