Weezly Outreach
|Developer Docs

Campaigns API

Create, manage, and monitor outreach campaigns. Launch campaigns, track execution progress, and retrieve performance stats.

Campaign statuses: DRAFT ACTIVE PAUSED STOPPED COMPLETED ARCHIVED

List Campaigns

GET/api/campaigns

List campaigns with cursor-based pagination. Supports filtering by status, folder, and search.

Query Parameters

ParameterTypeDescription
statusstringFilter by status (DRAFT, ACTIVE, etc.)
searchstringSearch by campaign name
folderIdstringFilter by folder ID
cursorstringCursor for next page (from previous response)
limitnumberResults per page (default: 20, max: 50)
Request — cURLcURL
curl --location --request GET 'http://outreach.weezly.com/api/campaigns' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "campaigns": [
    {
      "id": "cm3camp456",
      "name": "Q1 SaaS Founders Outreach",
      "status": "ACTIVE",
      "folderId": null,
      "totalLeads": 150,
      "leadsProcessed": 87,
      "leadsCompleted": 65,
      "leadsReplied": 12,
      "leadsFailed": 3,
      "leadList": {
        "id": "cm3list789",
        "name": "SaaS Founders — West Coast",
        "leadCount": 150
      },
      "senders": [
        { "id": "cs1", "account": { "id": "acc1", "linkedinName": "John Smith", "linkedinPhotoUrl": "https://..." } }
      ],
      "createdAt": "2026-05-20T08:00:00.000Z",
      "updatedAt": "2026-06-05T14:30:00.000Z"
    }
  ],
  "nextCursor": "cm3camp789"
}

Create Campaign

POST/api/campaigns

Create a new campaign in DRAFT status. You must add steps and senders before launching.

Request Body

ParameterTypeDescription
namerequiredstringCampaign name
leadListIdrequiredstringID of the lead list to use
excludeListIdsstring[]Lead list IDs to exclude
Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Q2 Enterprise Outreach",
  "leadListId": "cm3list789abc",
  "excludeListIds": [
    "cm3list_exclude1"
  ]
}'
Response — 201 CreatedJSON
{
  "campaign": {
    "id": "cm3camp_new789",
    "name": "Q2 Enterprise Outreach",
    "status": "DRAFT",
    "leadListId": "cm3list789abc",
    "leadList": { "id": "cm3list789abc", "name": "Enterprise CTOs", "leadCount": 89 },
    "totalLeads": 0,
    "createdAt": "2026-06-07T10:00:00.000Z"
  }
}

Response Codes

201Campaign created
400Name and leadListId required
404Lead list not found
401Unauthorized

Get Campaign

GET/api/campaigns/:id

Get full campaign details including stats, steps, and senders.

Request — cURLcURL
curl --location --request GET 'http://outreach.weezly.com/api/campaigns/:id' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "campaign": {
    "id": "cm3camp456",
    "name": "Q1 SaaS Founders Outreach",
    "status": "ACTIVE",
    "timezone": "America/Los_Angeles",
    "workingHoursStart": 540,
    "workingHoursEnd": 1020,
    "workingDays": [1, 2, 3, 4, 5],
    "leadList": { "id": "cm3list789", "name": "SaaS Founders", "leadCount": 150 },
    "steps": [
      { "id": "step1", "type": "CONNECTION_REQUEST", "order": 1, "delayDays": 0 },
      { "id": "step2", "type": "MESSAGE", "order": 2, "delayDays": 3 }
    ],
    "senders": [
      { "id": "cs1", "account": { "id": "acc1", "linkedinName": "John Smith" } }
    ],
    "totalLeads": 150,
    "totalExecutions": 150,
    "leadsProcessed": 87,
    "leadsCompleted": 65,
    "leadsReplied": 12,
    "leadsFailed": 3,
    "connectionsSent": 150,
    "connectionsAccepted": 45,
    "messagesSent": 45,
    "inmailsSent": 0,
    "createdAt": "2026-05-20T08:00:00.000Z"
  }
}

Update Campaign

PATCH/api/campaigns/:id

Update campaign settings. Only editable in DRAFT or PAUSED status (except folderId which can always be changed).

Request Body

ParameterTypeDescription
namestringCampaign name
folderIdstring|nullMove to folder (null to unfile)
timezonestringIANA timezone (e.g. "America/New_York")
workingHoursStartnumberStart time in minutes from midnight (e.g. 540 = 9:00 AM)
workingHoursEndnumberEnd time in minutes from midnight (e.g. 1020 = 5:00 PM)
workingDaysnumber[]Working days (1=Mon, 7=Sun)
Request — cURLcURL
curl --location --request PATCH 'http://outreach.weezly.com/api/campaigns/:id' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Updated Campaign Name",
  "folderId": null
}'

Response Codes

200Campaign updated
400Campaign is not editable in current status
404Campaign not found

Delete Campaign

DELETE/api/campaigns/:id

Delete a campaign. Only allowed for DRAFT, ARCHIVED, STOPPED, or COMPLETED campaigns.

Request — cURLcURL
curl --location --request DELETE 'http://outreach.weezly.com/api/campaigns/:id' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{ "success": true }

Response Codes

200Campaign deleted
400Cannot delete active campaigns — stop first
404Campaign not found

Launch Campaign

POST/api/campaigns/:id/launch

Launch a DRAFT campaign. Creates execution records and begins processing leads.

Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns/:id/launch' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "campaign": {
    "id": "cm3camp456",
    "status": "ACTIVE",
    "totalLeads": 150
  }
}

Response Codes

200Campaign launched
400Campaign must be in DRAFT status / missing steps or senders
503Background job service unavailable — campaign reverted to DRAFT

Stop Campaign

POST/api/campaigns/:id/stop

Stop an active campaign. All pending executions are cancelled.

Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns/:id/stop' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{ "campaign": { "id": "cm3camp456", "status": "STOPPED" } }

Pause Campaign

POST/api/campaigns/:id/pause

Pause an active campaign. Executions are suspended but not cancelled.

Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns/:id/pause' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{ "campaign": { "id": "cm3camp456", "status": "PAUSED" } }

Resume Campaign

POST/api/campaigns/:id/resume

Resume a paused campaign.

Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns/:id/resume' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{ "campaign": { "id": "cm3camp456", "status": "ACTIVE" } }

Duplicate Campaign

POST/api/campaigns/:id/duplicate

Duplicate a campaign as a new DRAFT. Copies all steps and settings with remapped IDs.

Request — cURLcURL
curl --location --request POST 'http://outreach.weezly.com/api/campaigns/:id/duplicate' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 201 CreatedJSON
{
  "campaign": {
    "id": "cm3camp_dup123",
    "name": "Q1 SaaS Founders Outreach (copy)",
    "status": "DRAFT"
  }
}

Campaign Leads

GET/api/campaigns/:id/leads

Get leads in a campaign with their execution status, current step, and next step.

Query Parameters

ParameterTypeDescription
statusstringFilter by execution status: PENDING, ACTIVE, WAITING, COMPLETED, FAILED, STOPPED_REPLY
searchstringSearch by lead name or company
pagenumberPage number (default: 1)
limitnumberResults per page (default: 25)
Request — cURLcURL
curl --location --request GET 'http://outreach.weezly.com/api/campaigns/:id/leads' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "executions": [
    {
      "id": "cm3exec789",
      "status": "WAITING",
      "currentStepOrder": 2,
      "nextRunAt": "2026-06-08T10:30:00.000Z",
      "lead": {
        "id": "cm3lead_001",
        "fullName": "Sarah Chen",
        "company": "TechStartup Inc.",
        "photoUrl": "https://..."
      },
      "assignedAccount": {
        "id": "acc1",
        "linkedinName": "John Smith"
      },
      "currentStepType": "MESSAGE",
      "nextStepType": "IF_CONNECTION"
    }
  ],
  "total": 150,
  "page": 1,
  "totalPages": 6
}

Campaign Stats

GET/api/campaigns/:id/stats

Get daily activity stats for a campaign.

Query Parameters

ParameterTypeDescription
daysnumberNumber of days of history (default: 7)
Request — cURLcURL
curl --location --request GET 'http://outreach.weezly.com/api/campaigns/:id/stats' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "daily": [
    { "date": "2026-06-01", "connections": 12, "messages": 5, "inmails": 0, "replies": 2 },
    { "date": "2026-06-02", "connections": 15, "messages": 8, "inmails": 0, "replies": 1 },
    { "date": "2026-06-03", "connections": 10, "messages": 12, "inmails": 2, "replies": 3 }
  ]
}

Campaign Steps

GET/api/campaigns/:id/steps

Get all campaign sequence steps with their configuration.

Request — cURLcURL
curl --location --request GET 'http://outreach.weezly.com/api/campaigns/:id/steps' \
  --header 'X-API-KEY: sk_live_YOUR_API_KEY'
Response — 200 OKJSON
{
  "steps": [
    {
      "id": "step1",
      "type": "CONNECTION_REQUEST",
      "order": 1,
      "branchId": null,
      "parentStepId": null,
      "delayDays": 0,
      "delayHours": 0,
      "inviteNote": "Hi {{firstName}}, I noticed we're both in the SaaS space...",
      "withdrawAfterDays": 25
    },
    {
      "id": "step2",
      "type": "IF_CONNECTION",
      "order": 2,
      "branchId": null,
      "parentStepId": "step1"
    },
    {
      "id": "step3",
      "type": "MESSAGE",
      "order": 3,
      "branchId": "step2_true",
      "parentStepId": "step2",
      "delayDays": 1,
      "messageText": "Great to connect, {{firstName}}! I wanted to share..."
    }
  ]
}

Campaign Step Types

TypeDescription
CONNECTION_REQUESTSend a LinkedIn connection request with optional note
MESSAGESend a direct message to a connected lead
VIDEO_MESSAGESend a video message (recorded or AI-generated)
VOICE_NOTESend a voice note message
INMAILSend a LinkedIn InMail
VIEW_PROFILEView the lead's LinkedIn profile
LIKE_POSTLike the lead's latest post
REACT_TO_POSTReact to the lead's latest post
COMMENT_ON_POSTAI-generated comment on the lead's latest post
FOLLOW_PROFILEFollow the lead's LinkedIn profile
IF_CONNECTIONBranch: check if connection was accepted
IF_OPEN_PROFILEBranch: check if profile is open
ENDEnd the sequence

Execution Statuses

StatusDescription
PENDINGNot yet started — waiting for scheduled time
ACTIVECurrently being processed
WAITINGWaiting for delay between steps
COMPLETEDAll steps finished successfully
FAILEDStep failed after retries
STOPPED_REPLYLead replied — execution stopped automatically