SkyLight Chat
API Reference

Campaigns

Create and manage multi-day outreach campaigns across your connected messaging channels.

Overview

Outreach Campaigns let you send a sequence of messages to a list of contacts over multiple days, with built-in daily rate limiting that prevents your sending number from being flagged or blocked. Each campaign draws contacts from explicit IDs, contact lists, segments, or a combination.

Campaigns consume your outreach campaign quota. Check your remaining quota with GET /account/subscription.

Campaign lifecycle

draft → running → paused → running → completed
                          ↘ cancelled

A campaign must be explicitly started after creation. It can be paused and resumed at any time. Once all contacts have been messaged, the status moves to completed automatically.


The Campaign object

{
  "id": 12,
  "name": "Spring Promo 2026",
  "status": "running",
  "total_contacts": 250,
  "success_count": 87,
  "failed_count": 3,
  "campaign_day": 4,
  "messages_sent_today": 65,
  "is_new_number": false,
  "started_at": "2026-03-05T08:00:00.000000Z",
  "completed_at": null,
  "progress_percentage": 36,
  "daily_limit": 65,
  "remaining_today": 0,
  "client_setting": { "id": 5, "name": "Business WhatsApp", "type": "whatsapp" },
  "campaign_contacts_count": 250,
  "sent_contacts_count": 87,
  "failed_contacts_count": 3,
  "pending_contacts_count": 160,
  "created_at": "2026-03-04T10:00:00.000000Z"
}
FieldTypeDescription
statusstringdraft, running, paused, completed, cancelled
campaign_dayintegerHow many days the campaign has been running
progress_percentageinteger0–100, based on contacted vs total
daily_limitintegerMax messages the system will send today
remaining_todayintegerRemaining sends for today
is_new_numberbooleanConservative warm-up mode for new phone numbers

List campaigns

GET /api/v1/campaigns
ParameterTypeDescription
statusstringdraft, running, paused, completed, cancelled
per_pageintegerMax 100 (default 25)

Create a campaign

POST /api/v1/campaigns

Request body

FieldTypeRequiredNotes
namestring
channel_idintegerClientSetting ID — get from GET /account/channels
messagesarraySequence of message objects
messages[].typestringtext, image, document, video, audio
messages[].contentstringMessage text or media URL
is_new_numberbooleanNoUse conservative warm-up daily limits (default: false)
contact_idsarrayNo*Explicit contact IDs to target
list_idsarrayNo*Pull contacts from these contact lists
segment_idsarrayNo*Pull contacts from these segments

*At least one of contact_ids, list_ids, or segment_ids is required.

curl -X POST https://dashboard.skylightchat.com/api/v1/campaigns \
  -H "X-Api-Key: ••••••••••••" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Promo 2026",
    "channel_id": 5,
    "messages": [
      { "type": "text", "content": "Hi! We have a special offer just for you 🎉" },
      { "type": "text", "content": "Reply YES to learn more, or STOP to unsubscribe." }
    ],
    "list_ids": [3, 7],
    "is_new_number": false
  }'

Returns 201 Created. The campaign starts in draft status — call /start to begin sending.

Daily limits

Daily message limits scale automatically based on campaign_day and is_new_number to protect your sending reputation:

DayNormal numberNew number
1up to 35up to 20
3up to 65up to 40
5up to 65up to 60
7+up to 120up to 90
14+up to 200up to 200

For small campaigns, the limit is capped at ⌈total_contacts / 3⌉ to finish in ~3 days.


Get a campaign

GET /api/v1/campaigns/{id}

Update a campaign

PUT /api/v1/campaigns/{id}

Only draft campaigns can be updated. You can change name, messages, and is_new_number.


Start a campaign

POST /api/v1/campaigns/{id}/start

Transitions the campaign from draft to running. Sending begins on the next background job cycle.


Pause a campaign

POST /api/v1/campaigns/{id}/pause

Stops sending immediately. The campaign can be resumed at any time without losing progress.


Resume a campaign

POST /api/v1/campaigns/{id}/resume

Transitions from paused back to running.


Cancel a campaign

POST /api/v1/campaigns/{id}/cancel

Permanently stops the campaign. Cancelled campaigns cannot be restarted. Returns the updated campaign object.


Delete a campaign

DELETE /api/v1/campaigns/{id}

Only draft or cancelled campaigns can be deleted. Returns 204 No Content.


List campaign contacts

GET /api/v1/campaigns/{id}/contacts

Returns the enrolled contacts and their delivery status.

ParameterTypeDescription
statusstringpending, sent, failed
per_pageintegerMax 100
{
  "success": true,
  "data": [
    {
      "id": 1,
      "status": "sent",
      "phone": "+966501234567",
      "sent_at": "2026-03-05T09:14:00.000000Z",
      "error": null,
      "contact": { "id": 42, "name": "Noura Al-Otaibi", "type": "whatsapp" }
    }
  ]
}