Campaign API
Interfaces to manage campaigns
A campaign is the configuration for sending out messages. Campaigns need senders, messages, and contacts in order to work properly.
V2 API Recommended
Response Format
V2 endpoints and app-compat V1 endpoints return a standardized response with success, data (or message), and request_id. Legacy V1 endpoints may return different shapes. Errors return:
{
"error": {
"type": "invalid_request_error",
"code": "missing_campaign_id",
"message": "CampaignId is required",
"param": "CampaignId",
"doc_url": "https://docs.supersend.io/docs/errors#missing_campaign_id"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}Create Campaign
Create a new campaign.
V2 API (Recommended)
curl -X POST 'https://api.supersend.io/v2/campaigns' \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 Outreach Campaign",
"TeamId": "team-uuid"
}'# Optional: include nodes, edges, category_id, track, bcc, schedule, opt-outs, failureConfiguration
# -d 700 dark:text-green-400">'{"name": "Q4 Outreach", "TeamId": "team-uuid", "category_id": "category-uuid", "track": true, "nodes": [...], "edges": [...]}'
# Response (201 Created)
{
"success": true,
"data": {
"id": "campaign-uuid",
"name": "Q4 Outreach Campaign",
"status": 2,
"track_domain": null,
"is_draft": true,
"legacy_sequence": false,
"nodes": [],
"edges": [],
"contact_count": 0,
"createdAt": "2025-11-27T10:00:00Z",
"updatedAt": "2025-11-27T10:00:00Z"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
V2 Create Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Campaign name |
TeamId | string (UUID) | Yes | Team identifier |
track_domain | string | No | Tracking domain (team default used if omitted) |
track | boolean | No | Enable open and click tracking. Default: false. |
category_id | string (UUID) or null | No | Campaign category (folder) ID |
nodes | array | No | Initial sequence nodes |
edges | array | No | Initial sequence edges |
is_draft | boolean | No | Draft status (default: true) |
custom_variables | array | No | Custom variable definitions for contacts |
templateId | string (UUID) | No | Template used to create this campaign |
send_to_risk_levels | array or null | No | List Health levels to send to. Default on create: SAFE/LOW/MEDIUM/HIGH (Invalid off). null = all. |
bcc | array of emails or null | No | BCC email addresses |
bcc_replies_only | boolean | No | When true, BCC only applies to reply emails |
timezone | string | No | Campaign schedule timezone |
days | object | No | Days of week to send |
hours | array | No | Sending hours windows |
start | string (ISO 8601) or null | No | Campaign start date |
end | string (ISO 8601) or null | No | Campaign end date |
unsubscribe | boolean | No | Enable opt-out link in emails |
unsubscribe_message | string or null | No | Keyword to detect opt-out in replies |
blacklistIfUnsubscribe | boolean | No | Add contact to blacklist when they opt out |
blacklistIfBounced | boolean | No | Add contact to blacklist when email bounces |
blacklistDomainOnReply | boolean | No | Blacklist contact domain when reply received |
list_unsubscribe_header | boolean | No | Add List-Unsubscribe header to emails |
failureConfiguration | object | No | Sequence step failure handling |
V1 API
curl -X POST 'https://api.supersend.io/v1/campaign' \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 Outreach Campaign",
"TeamId": "team-uuid"
}'# Response (201 Created)
{
"success": true,
"data": {
"campaign": {
"id": "campaign-uuid",
"name": "Q4 Outreach Campaign",
...
}
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
List Campaigns
Get campaigns for a team.
V2 API (Recommended)
curl -X GET 'https://api.supersend.io/v2/campaigns?TeamId=xxx&limit=20' \
-H "Authorization: Bearer YOUR_API_KEY"# Response (200 OK)
{
"success": true,
"data": [
{
"id": "campaign-uuid",
"name": "Q4 Outreach Campaign",
"status": 1,
"track_domain": null,
"is_draft": false,
"legacy_sequence": false,
"nodes": [...],
"contact_count": 150,
"contact_metrics": {
"total": 150,
"not_started": 50,
"in_progress": 75,
"finished": 20,
"paused": 5
},
"user_id": "user-uuid",
"createdAt": "2025-11-01T10:00:00Z",
"updatedAt": "2025-11-27T15:30:00Z"
}
],
"pagination": {
"total": 10,
"limit": 20,
"offset": 0,
"has_more": false
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
V2 Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
TeamId | string | Yes | Team identifier |
search | string | No | Search in campaign name or track_domain |
status | number | No | Filter by status (1=active, 2=inactive) |
archived | string | No | Include archived campaigns ("true" or "false", default: "false") |
sortBy | string | No | Sort field: newest (default), oldest, last_modified, name |
limit | number | No | Results per page (default: 50) |
offset | number | No | Pagination offset |
Contact Metrics:
The contact_metrics object provides lifecycle breakdown of contacts in the campaign:
| Field | Description |
|---|---|
total | Total non-archived contacts |
not_started | Contacts waiting in queue (haven't started the sequence yet) |
in_progress | Contacts currently progressing through the sequence |
finished | Contacts that completed the sequence |
paused | Contacts currently paused |
Auto-Refill Integration
not_started to determine how many contacts are queued and ready. This is useful for auto-refill integrations that need to maintain a minimum queue size.V1 API (with metrics)
The V1 overview endpoint includes performance metrics:
curl -X GET 'https://api.supersend.io/v1/campaigns/overview?TeamId=xxx&limit=50&includeMetrics=true' \
-H "Authorization: Bearer YOUR_API_KEY"# Response
{
"success": true,
"campaigns": [
{
"id": "campaign-uuid",
"name": "Q4 Outreach Campaign",
"contactedCount": 150,
"openCount": 75,
"replyCount": 12,
"emailSentCount": 200,
"linkedInSentCount": 50,
"bounces": 5,
"invalidRecipientBounces": 2,
"policyBlockBounces": 2,
"softBounces": 1,
"opt_outs": 2,
"contactCount": 300,
"verifiedContactCount": 280,
...
}
],
"total": 1
}
V1 Additional Parameters:
search - Search in campaign nameorder_by - Sort field (name, status, createdAt, etc.)order - Sort direction (ASC, DESC)status - Filter by status (1=active, 2=inactive)archived - Include archived campaignsincludeMetrics - Include performance metricsGet Campaign
Get a single campaign by ID.
V2 API (Recommended)
curl -X GET 'https://api.supersend.io/v2/campaigns/campaign-uuid' \
-H "Authorization: Bearer YOUR_API_KEY"# Response (200 OK)
{
"success": true,
"data": {
"id": "campaign-uuid",
"name": "Q4 Outreach Campaign",
"status": 1,
"track_domain": null,
"is_draft": false,
"legacy_sequence": false,
"nodes": [...],
"edges": [...],
"timezone": "America/New_York",
"days": [1, 2, 3, 4, 5],
"max_per_day": 50,
"contact_count": 150,
"contact_metrics": {
"total": 150,
"not_started": 50,
"in_progress": 75,
"finished": 20,
"paused": 5
},
"created_by": {
"id": "user-uuid",
"name": "John Doe",
"email": "john@example.com"
},
"team_id": "team-uuid",
"reply_link_clicks": 12,
"createdAt": "2025-11-01T10:00:00Z",
"updatedAt": "2025-11-27T15:30:00Z"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
reply_link_clicks: Deduplicated count of inbox reply link clicks attributed to this campaign — at most one per (contact, link, UTC calendar day). Separate from sequence-step clicks on campaign emails. See List Campaign Inbox Reply Link Clicks.
V1 API
curl -X GET 'https://api.supersend.io/v1/campaign/campaign-uuid' \
-H "Authorization: Bearer YOUR_API_KEY"# Response
{
"success": true,
"campaign": {...}
}
Update Campaign
Update campaign settings.
V2 API (Recommended)
curl -X PATCH 'https://api.supersend.io/v2/campaigns/campaign-uuid' \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Campaign Name",
"track_domain": "track.example.com",
"status": 2,
"is_draft": false,
"nodes": [...],
"edges": [...]
}'# Response (200 OK)
{
"success": true,
"data": {
"id": "campaign-uuid",
"name": "Updated Campaign Name",
"status": 2,
"track_domain": "track.example.com",
"is_draft": false,
"legacy_sequence": false,
"nodes": [...],
"edges": [...],
"createdAt": "2025-11-01T10:00:00Z",
"updatedAt": "2025-11-27T15:30:00Z"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
V2 Update Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | Campaign name |
track_domain | string | No | Tracking domain |
track | boolean | No | Enable open and click tracking. When false, no pixels or link rewrites; replies/bounces still tracked. |
category_id | string (UUID) or null | No | Campaign category (folder) ID. Set to null to uncategorize. See Campaign Categories. |
nodes | array | No | Campaign sequence nodes |
edges | array | No | Campaign sequence edges (connections between nodes) |
status | number | No | Status (1=ACTIVE, 2=INACTIVE) |
is_draft | boolean | No | Draft status |
max_per_day | number or null | No | Max emails per day from all senders (1–100000). null = no campaign limit. |
send_to_risk_levels | array or null | No | List Health levels to send to (SAFE, LOW, MEDIUM, HIGH, INVALID). On create, omitted defaults to SAFE/LOW/MEDIUM/HIGH (Invalid excluded). null = send to all. |
bcc | array of emails or null | No | BCC email addresses |
bcc_replies_only | boolean | No | When true, BCC only applies to reply emails |
timezone | string | No | Campaign schedule timezone (e.g. America/Los_Angeles) |
days | object | No | Days of week to send: { monday: true, tuesday: true, ... } |
hours | array | No | Sending hours: [{ start: "09:00", end: "17:00" }] |
start | string (ISO 8601) or null | No | Campaign start date |
end | string (ISO 8601) or null | No | Campaign end date |
unsubscribe | boolean | No | Enable opt-out link in emails |
unsubscribe_message | string or null | No | Keyword to detect opt-out in replies |
blacklistIfUnsubscribe | boolean | No | Add contact to blacklist when they opt out |
blacklistIfBounced | boolean | No | Add contact to blacklist when email bounces |
blacklistDomainOnReply | boolean | No | Blacklist contact domain when reply received |
list_unsubscribe_header | boolean | No | Add List-Unsubscribe header to emails |
failureConfiguration | object | No | Sequence step failure handling: { strategy, retryAfterDays, notification }. Strategy: skip, retry, pause_contact, pause_campaign. |
Note: Cannot modify nodes or legacy_sequence while campaign is active (status=1).
V1 API
V1 supports additional configuration options:
curl -X PUT 'https://api.supersend.io/v1/campaign/campaign-uuid' \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Campaign Name",
"status": 1,
"warm": false,
"unsubscribe": true,
"max_per_day": 25,
"unsubscribe_message": "Click here to unsubscribe",
"hours": [
{ "start": "09:00", "end": "12:00" },
{ "start": "14:00", "end": "17:00" }
],
"days": {
"monday": true,
"tuesday": true,
"wednesday": true,
"thursday": true,
"friday": true,
"saturday": false,
"sunday": false
},
"LinkedinId": "linkedin-account-id",
"SenderIds": ["sender-id-1", "sender-id-2"],
"TeamId": "team-uuid",
"CampaignId": "campaign-uuid"
}'# Response
{
"success": true,
"message": "Campaign updated successfully"
}
Subsequences {#subsequences}
Subsequences are linked child campaigns that continue the conversation with parent-campaign contacts who match their entry conditions (subsequence_entry_conditions, for example status Interested).
Rules:
GET /v2/campaigns excludes subsequences by default; pass include_subsequences=true to include themparentCampaignId sets the parent link; the child inherits normal campaign behaviordays, hours, timezone) follows the parent too, until you edit the subsequence's schedule: that sets subsequence_settings.schedule to custom. PATCH with {"subsequence_settings": {"schedule": "parent"}} switches back and copies the parent's scheduleList subsequences
curl -X GET 'https://api.supersend.io/v2/campaigns/{parentCampaignId}/subsequences' \
-H "Authorization: Bearer YOUR_API_KEY"Each subsequence includes its counts (contact_count, contacted_count, replies), active_count (contacts still going through it), entry_delay (the wait before its first step, e.g. {"wait": 3, "unit": "days"}, or null), subsequence_entry_conditions and subsequence_settings.
Get parent campaign
curl -X GET 'https://api.supersend.io/v2/campaigns/{campaignId}/parent' \
-H "Authorization: Bearer YOUR_API_KEY"Response includes isSubsequence and parentCampaign when applicable.
Create subsequence
Pass parentCampaignId on POST /v2/campaigns (same body as create campaign). See Create Campaign.
Move behavior: When a contact is moved to a subsequence target, interest is preserved on the new copy, the parent contact is finished, and source campaign metadata is stored on the contact for journey tracking. The copy keeps the parent contact's sender (inbox) and sender profile. Bulk transfers (action: transfer) from a parent campaign into its subsequence work the same way.
Continuing the conversation: A subsequence's first email step with send_as_reply: true replies in the contact's thread from the parent campaign, from the same inbox, to the newest message in that thread (including replies sent from Super Inbox). When that inbox has no thread with the contact, it starts a new thread with the parent campaign's first email subject. A reply, out-of-office or unsubscribe in that thread after the move applies to the subsequence.
Inbox Reply Link Tracking {#inbox-reply-link-tracking}
SuperSend can wrap http:// and https:// URLs in Super Inbox outbound email replies with trackable redirect links. When a recipient clicks, SuperSend records the click and can append UTM parameters to the destination URL at redirect time.
This is separate from sequence-step link tracking (track: true on campaign emails). Inbox reply link tracking is configured in the app at org and team (Super Inbox settings) levels.
Rollup: When a click is attributed to a campaign (CampaignId on the link), reply_link_clicks on the campaign increments (deduplicated per contact, link, and UTC day). The contact's reply_link_clicked flag is set and a reply_link_click webhook may fire.
For end-user setup (toggles, UTM templates, tokens), see Inbox Reply Link Tracking in the SuperSend help center.
List Campaign Inbox Reply Link Clicks {#inbox-link-clicks}
Returns paginated inbox reply link clicks attributed to a campaign.
V2 API
curl -X GET 'https://api.supersend.io/v2/campaigns/campaign-uuid/inbox-link-clicks?limit=25&page=1' \
-H "Authorization: Bearer YOUR_API_KEY"# Response (200 OK)
{
"success": true,
"data": {
"campaign_id": "campaign-uuid",
"clicks": [
{
"id": "click-uuid",
"link_id": "link-uuid",
"original_url": "https://your-site.com/pricing",
"final_url": "https://your-site.com/pricing?utm_source=supersend&utm_medium=inbox_reply&utm_campaign=q3-outreach",
"clicked_at": "2026-06-08T14:32:15.123Z",
"is_first_today": true,
"ip": "203.0.113.10",
"contact": {
"id": "contact-uuid",
"email": "john@example.com",
"name": "John Doe"
},
"sender_email": "sales@company.com",
"sequence_step": 2
}
],
"pagination": {
"page": 1,
"limit": 25,
"total": 42,
"total_pages": 2
}
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}
V2 Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Results per page (default: 25, max: 100) |
contact_id | string (UUID) | Filter to a specific contact |
date_from | string (ISO 8601) | Earliest click timestamp |
date_to | string (ISO 8601) | Latest click timestamp |
first_only | boolean | When true, return only the first click per (contact, link, UTC day) |
Notes:
final_url includes UTM parameters when UTM attribution is enabled; otherwise it may be null.reply_link_clicks on GET /v2/campaigns/:id is the deduplicated rollup counter.Clone Campaign (V1 Only)
Create a copy of an existing campaign with all its messages and settings.
curl -X POST 'https://api.supersend.io/v1/campaign/campaign-uuid/clone' \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"TeamId": "team-uuid"
}'# Response
{
"success": true,
"campaign": {
"id": "new-campaign-uuid",
"name": "Copy of Original Campaign",
...
}
}
Delete Campaign
Archive (soft delete) a campaign and its contacts. Draft campaigns are permanently removed.
curl -X DELETE 'https://api.supersend.io/v2/campaigns/campaign-uuid' \
-H "Authorization: Bearer YOUR_API_KEY"# Response (archived campaign)
{
"success": true,
"message": "Campaign archived successfully",
"data": {
"id": "campaign-uuid"
},
"request_id": "req_..."
}
# Response (draft campaign — permanently deleted)
{
"success": true,
"message": "Campaign deleted successfully",
"request_id": "req_..."
}
V1 equivalent: DELETE /v1/campaign/:id
Campaign Status Values
| Status | Description |
|---|---|
| 1 | Active - Campaign is running |
| 2 | Inactive - Campaign is paused |
V1 vs V2 Endpoint Mapping
| Action | V1 Endpoint | V2 Endpoint |
|---|---|---|
| Create | POST /v1/campaign | POST /v2/campaigns |
| List | GET /v1/campaigns/overview | GET /v2/campaigns |
| Get | GET /v1/campaign/:id | GET /v2/campaigns/:id |
| Update | PUT /v1/campaign/:id | PATCH /v2/campaigns/:id |
| Delete | DELETE /v1/campaign/:id | DELETE /v2/campaigns/:id |
| Clone | POST /v1/campaign/:id/clone | Not available in V2 |