Create campaign
Create a new campaign in draft status. Mailboxes can be assigned using any combination of:
mailboxesormailboxIds- direct mailbox IDsmailboxEmails- resolve mailboxes by email addressmailboxTags- all mailboxes matching any of these tagsmailboxProvider- all mailboxes with this provider (e.g. "gmail", "outlook")
curl -X POST "https://api.sendkit.ai/v1/campaigns" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "Q2 Outbound - Decision Makers",
"sequence": [
{
"type": "email",
"order": 0,
"subject": "Quick question about {{companyName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{companyName}} is scaling fast. Would love to share how we helped similar teams cut outbound costs by 40%.</p>"
},
{
"type": "wait",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"order": 2,
"subject": "Re: Quick question about {{companyName}}",
"body": "<p>Hey {{firstName}}, just bumping this up. Happy to send over a case study if that helps.</p>"
}
],
"schedule": {
"timezone": "America/Chicago",
"startTime": "08:30",
"endTime": "16:00",
"workingDays": [
1,
2,
3,
4,
5
],
"skipNationalHolidays": true
},
"settings": {
"trackOpens": true,
"trackClicks": true,
"includeUnsubscribeLink": false,
"cc": [
"sales-log@yourcompany.com"
],
"bcc": [
"crm-sync@yourcompany.com"
],
"stopOnReply": true,
"stopOnAutoReply": true,
"stopOnCompanyReply": true,
"skipDNC": true,
"dailySendLimit": 50,
"emailIntervalMinutes": 12,
"espMatchingMode": "auto",
"segCheckMode": "skip_providers",
"segSkipProviders": [
"proofpoint",
"mimecast"
],
"cnameTracking": {
"enabled": true,
"domain": "track.yourcompany.com"
},
"slackChannelId": "C04ABCDEF12",
"positiveRepliesOnlySlack": true,
"webhook": {
"enabled": true,
"url": "https://yourcompany.com/webhooks/sendkit",
"secret": "whsec_abc123xyz",
"events": [
"lead.replied",
"email.sent",
"lead.bounced"
]
},
"copyFatigueProtection": {
"enabled": true,
"autoRegenerate": true,
"autoResume": true
},
"variantOptimization": {
"enabled": true,
"minimumSendsPerVariant": 50,
"minimumDays": 5,
"optimizationMetric": "replyRate",
"keepMinimumVariants": 2
}
},
"mailboxTags": [
"outreach"
]
}'
import requests
import json
url = "https://api.sendkit.ai/v1/campaigns"
headers = {
"Content-Type": "application/json",
"X-Api-Key": "YOUR_API_KEY"
}
data = {
"name": "Q2 Outbound - Decision Makers",
"sequence": [
{
"type": "email",
"order": 0,
"subject": "Quick question about {{companyName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{companyName}} is scaling fast. Would love to share how we helped similar teams cut outbound costs by 40%.</p>"
},
{
"type": "wait",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"order": 2,
"subject": "Re: Quick question about {{companyName}}",
"body": "<p>Hey {{firstName}}, just bumping this up. Happy to send over a case study if that helps.</p>"
}
],
"schedule": {
"timezone": "America/Chicago",
"startTime": "08:30",
"endTime": "16:00",
"workingDays": [
1,
2,
3,
4,
5
],
"skipNationalHolidays": true
},
"settings": {
"trackOpens": true,
"trackClicks": true,
"includeUnsubscribeLink": false,
"cc": [
"sales-log@yourcompany.com"
],
"bcc": [
"crm-sync@yourcompany.com"
],
"stopOnReply": true,
"stopOnAutoReply": true,
"stopOnCompanyReply": true,
"skipDNC": true,
"dailySendLimit": 50,
"emailIntervalMinutes": 12,
"espMatchingMode": "auto",
"segCheckMode": "skip_providers",
"segSkipProviders": [
"proofpoint",
"mimecast"
],
"cnameTracking": {
"enabled": true,
"domain": "track.yourcompany.com"
},
"slackChannelId": "C04ABCDEF12",
"positiveRepliesOnlySlack": true,
"webhook": {
"enabled": true,
"url": "https://yourcompany.com/webhooks/sendkit",
"secret": "whsec_abc123xyz",
"events": [
"lead.replied",
"email.sent",
"lead.bounced"
]
},
"copyFatigueProtection": {
"enabled": true,
"autoRegenerate": true,
"autoResume": true
},
"variantOptimization": {
"enabled": true,
"minimumSendsPerVariant": 50,
"minimumDays": 5,
"optimizationMetric": "replyRate",
"keepMinimumVariants": 2
}
},
"mailboxTags": [
"outreach"
]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://api.sendkit.ai/v1/campaigns", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": "YOUR_API_KEY"
},
body: JSON.stringify({
"name": "Q2 Outbound - Decision Makers",
"sequence": [
{
"type": "email",
"order": 0,
"subject": "Quick question about {{companyName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{companyName}} is scaling fast. Would love to share how we helped similar teams cut outbound costs by 40%.</p>"
},
{
"type": "wait",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"order": 2,
"subject": "Re: Quick question about {{companyName}}",
"body": "<p>Hey {{firstName}}, just bumping this up. Happy to send over a case study if that helps.</p>"
}
],
"schedule": {
"timezone": "America/Chicago",
"startTime": "08:30",
"endTime": "16:00",
"workingDays": [
1,
2,
3,
4,
5
],
"skipNationalHolidays": true
},
"settings": {
"trackOpens": true,
"trackClicks": true,
"includeUnsubscribeLink": false,
"cc": [
"sales-log@yourcompany.com"
],
"bcc": [
"crm-sync@yourcompany.com"
],
"stopOnReply": true,
"stopOnAutoReply": true,
"stopOnCompanyReply": true,
"skipDNC": true,
"dailySendLimit": 50,
"emailIntervalMinutes": 12,
"espMatchingMode": "auto",
"segCheckMode": "skip_providers",
"segSkipProviders": [
"proofpoint",
"mimecast"
],
"cnameTracking": {
"enabled": true,
"domain": "track.yourcompany.com"
},
"slackChannelId": "C04ABCDEF12",
"positiveRepliesOnlySlack": true,
"webhook": {
"enabled": true,
"url": "https://yourcompany.com/webhooks/sendkit",
"secret": "whsec_abc123xyz",
"events": [
"lead.replied",
"email.sent",
"lead.bounced"
]
},
"copyFatigueProtection": {
"enabled": true,
"autoRegenerate": true,
"autoResume": true
},
"variantOptimization": {
"enabled": true,
"minimumSendsPerVariant": 50,
"minimumDays": 5,
"optimizationMetric": "replyRate",
"keepMinimumVariants": 2
}
},
"mailboxTags": [
"outreach"
]
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"name": "Q2 Outbound - Decision Makers",
"sequence": [
{
"type": "email",
"order": 0,
"subject": "Quick question about {{companyName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{companyName}} is scaling fast. Would love to share how we helped similar teams cut outbound costs by 40%.</p>"
},
{
"type": "wait",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"order": 2,
"subject": "Re: Quick question about {{companyName}}",
"body": "<p>Hey {{firstName}}, just bumping this up. Happy to send over a case study if that helps.</p>"
}
],
"schedule": {
"timezone": "America/Chicago",
"startTime": "08:30",
"endTime": "16:00",
"workingDays": [
1,
2,
3,
4,
5
],
"skipNationalHolidays": true
},
"settings": {
"trackOpens": true,
"trackClicks": true,
"includeUnsubscribeLink": false,
"cc": [
"sales-log@yourcompany.com"
],
"bcc": [
"crm-sync@yourcompany.com"
],
"stopOnReply": true,
"stopOnAutoReply": true,
"stopOnCompanyReply": true,
"skipDNC": true,
"dailySendLimit": 50,
"emailIntervalMinutes": 12,
"espMatchingMode": "auto",
"segCheckMode": "skip_providers",
"segSkipProviders": [
"proofpoint",
"mimecast"
],
"cnameTracking": {
"enabled": true,
"domain": "track.yourcompany.com"
},
"slackChannelId": "C04ABCDEF12",
"positiveRepliesOnlySlack": true,
"webhook": {
"enabled": true,
"url": "https://yourcompany.com/webhooks/sendkit",
"secret": "whsec_abc123xyz",
"events": [
"lead.replied",
"email.sent",
"lead.bounced"
]
},
"copyFatigueProtection": {
"enabled": true,
"autoRegenerate": true,
"autoResume": true
},
"variantOptimization": {
"enabled": true,
"minimumSendsPerVariant": 50,
"minimumDays": 5,
"optimizationMetric": "replyRate",
"keepMinimumVariants": 2
}
},
"mailboxTags": [
"outreach"
]
}`)
req, err := http.NewRequest("POST", "https://api.sendkit.ai/v1/campaigns", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", "YOUR_API_KEY")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://api.sendkit.ai/v1/campaigns')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-Api-Key'] = 'YOUR_API_KEY'
request.body = '{
"name": "Q2 Outbound - Decision Makers",
"sequence": [
{
"type": "email",
"order": 0,
"subject": "Quick question about {{companyName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{companyName}} is scaling fast. Would love to share how we helped similar teams cut outbound costs by 40%.</p>"
},
{
"type": "wait",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"order": 2,
"subject": "Re: Quick question about {{companyName}}",
"body": "<p>Hey {{firstName}}, just bumping this up. Happy to send over a case study if that helps.</p>"
}
],
"schedule": {
"timezone": "America/Chicago",
"startTime": "08:30",
"endTime": "16:00",
"workingDays": [
1,
2,
3,
4,
5
],
"skipNationalHolidays": true
},
"settings": {
"trackOpens": true,
"trackClicks": true,
"includeUnsubscribeLink": false,
"cc": [
"sales-log@yourcompany.com"
],
"bcc": [
"crm-sync@yourcompany.com"
],
"stopOnReply": true,
"stopOnAutoReply": true,
"stopOnCompanyReply": true,
"skipDNC": true,
"dailySendLimit": 50,
"emailIntervalMinutes": 12,
"espMatchingMode": "auto",
"segCheckMode": "skip_providers",
"segSkipProviders": [
"proofpoint",
"mimecast"
],
"cnameTracking": {
"enabled": true,
"domain": "track.yourcompany.com"
},
"slackChannelId": "C04ABCDEF12",
"positiveRepliesOnlySlack": true,
"webhook": {
"enabled": true,
"url": "https://yourcompany.com/webhooks/sendkit",
"secret": "whsec_abc123xyz",
"events": [
"lead.replied",
"email.sent",
"lead.bounced"
]
},
"copyFatigueProtection": {
"enabled": true,
"autoRegenerate": true,
"autoResume": true
},
"variantOptimization": {
"enabled": true,
"minimumSendsPerVariant": 50,
"minimumDays": 5,
"optimizationMetric": "replyRate",
"keepMinimumVariants": 2
}
},
"mailboxTags": [
"outreach"
]
}'
response = http.request(request)
puts response.body
{
"success": true,
"data": {
"_id": "665a1b2c3d4e5f6a7b8c9d0e",
"name": "Q1 Outreach Campaign",
"userId": "664f0a1b2c3d4e5f6a7b8c9d",
"workspaceId": "664f0a1b2c3d4e5f6a7b8c9e",
"status": "draft",
"mailboxes": [
"665b1c2d3e4f5a6b7c8d9e0f"
],
"sequence": [
{
"type": "email",
"name": "Initial Email",
"order": 0,
"subject": "Quick question, {{firstName}}",
"body": "<p>Hi {{firstName}},</p><p>I noticed {{company}} is growing fast...</p>"
},
{
"type": "wait",
"name": "Wait 3 days",
"order": 1,
"waitDays": 3
},
{
"type": "email",
"name": "Follow-up",
"order": 2,
"subject": "Re: Quick question",
"body": "<p>Just following up on my last email...</p>"
}
],
"sendingSchedule": {
"timezone": "America/New_York",
"startTime": "09:00",
"endTime": "17:00",
"workingDays": [
1,
2,
3,
4,
5
]
},
"trackOpens": true,
"trackClicks": true,
"stopOnReply": true,
"stats": {
"sent": 0,
"delivered": 0,
"opened": 0,
"clicked": 0,
"replied": 0,
"bounced": 0,
"unsubscribed": 0
},
"createdAt": "2025-06-10T10:30:00.000Z",
"updatedAt": "2025-06-10T10:30:00.000Z"
}
}
/v1/campaigns
Platform API key (sk_user_...) or Workspace API key (sk_...)
The media type of the request body
Campaign name
Email sequence steps
Optional list of subsequences (nested follow-up flows). Each subsequence
fires when a lead's AI tag matches (trigger.type='ai_tag') or when the
lead first replies (trigger.type='reply').
Validation rules (mirrors the dashboard sequence builder): max 15 active
(non-archived) subsequences per campaign; at most one active subsequence
may have trigger.type='reply'; active ai_tag-trigger values must be
unique across subsequences (case-insensitive); the inner sequence
follows the same email/wait rules as the main campaign sequence, except
the first step MAY be a wait (subsequence emails can be sent as
in-thread replies after a delay); trigger is immutable once a subsequence
has sent any emails (addedCount > 0 or stats.sent > 0) — archive and
recreate to change.
Sending schedule configuration
Campaign tracking, sending, and deliverability settings
Mailbox IDs (legacy field)
Mailbox IDs to use for sending
Resolve mailboxes by email address
Use all mailboxes matching any of these tags
Use all mailboxes with this provider
Request Preview
Response
Response will appear here after sending the request
Authentication
API Key for authentication. Platform API key (sk_user_...) or Workspace API key (sk_...)
Body
Campaign name
Email sequence steps
Step display name (auto-assigned if omitted)
Step position (zero-based)
Email subject (for email steps)
Email body HTML (for email steps)
Days to wait (for wait steps)
Hours to wait (for wait steps)
Whether conditional variables are used in this step
Conditional variable definitions
has_valueno_valueequalsnot_equalscontainsnot_containsA/B test variants. If omitted on an email/follow-up step, a default variant "A" is auto-seeded from the step's subject/body so the sender always has something to send.
Single uppercase letter A-Z. Unique within the step; need not be sequential or start at A.
Optional list of subsequences (nested follow-up flows). Each subsequence
fires when a lead's AI tag matches (trigger.type='ai_tag') or when the
lead first replies (trigger.type='reply').
Validation rules (mirrors the dashboard sequence builder): max 15 active
(non-archived) subsequences per campaign; at most one active subsequence
may have trigger.type='reply'; active ai_tag-trigger values must be
unique across subsequences (case-insensitive); the inner sequence
follows the same email/wait rules as the main campaign sequence, except
the first step MAY be a wait (subsequence emails can be sent as
in-thread replies after a delay); trigger is immutable once a subsequence
has sent any emails (addedCount \\> 0 or stats.sent \\> 0) — archive and
recreate to change.
Subsequence ID (the _id of the subdocument)
What causes a lead to enter this subsequence. With type='ai_tag', the
subsequence fires when the lead's AI tag (set by reply classification or
manual tagging) matches value (case-insensitive); manual tag changes via
the campaign-lead PATCH endpoint and the MCP tag_conversation tool also
enroll into matching subsequences. With type='reply', the subsequence
fires the first time the lead replies and value is ignored.
ai_tagreplyRequired when type is ai_tag. The AI tag value to match.
emailwaitAuto-assigned by the server (e.g., "Initial Email", "Follow-up 1", "Wait 3 days")
Plain text or HTML; auto-converted to TipTap-compatible HTML
A/B variants. If omitted on an email/follow-up step, a default variant "A" is auto-seeded from the step's subject/body.
Single uppercase letter A-Z. Unique within the step; need not be sequential or start at A.
Total leads that have ever entered this subsequence
Sending schedule configuration
IANA timezone (default "America/New_York")
Daily start time in HH:MM format (default "09:00")
Daily end time in HH:MM format (default "17:00")
Days of week to send (0=Sun, 6=Sat). Default [1,2,3,4,5]
Skip sending on national holidays (default true)
Campaign tracking, sending, and deliverability settings
Track email opens (default true)
Track link clicks (default true)
Add unsubscribe link to email footer and headers (default false)
CC recipients added to every email
BCC recipients added to every email
Stop sequence when lead replies (default true)
Stop on out-of-office and auto-replies (default false)
Stop if anyone from the same company replies (default false)
Skip leads in your Do Not Contact list (default true)
Maximum emails to send per day
Minutes between each email send (default 15)
ESP matching strategy for mailbox-to-recipient provider matching. disabled uses standard mailbox rotation; auto matches sender to recipient provider.
disabledautoHow to handle SEG (Secure Email Gateway) protected leads. disabled sends to all leads; skip_all skips every SEG protected lead; skip_providers skips only leads on SEG providers listed in segSkipProviders. use_specific_mailboxes is legacy and is normalized to disabled on write.
disabledskip_allskip_providersuse_specific_mailboxesSEG provider names to skip when segCheckMode is skip_providers.
Custom tracking domain configuration
Enable custom CNAME tracking domain
Custom tracking domain (e.g. "track.yourdomain.com")
Slack channel ID for reply notifications
Only send Slack notifications for AI-tagged positive replies (default false)
Email addresses to notify when a reply is detected. Maximum 5 entries; each must be a valid email.
Send email notifications only for positive AI-tagged replies (default true)
AI reply agent ObjectId. Must belong to this workspace — 400 AGENT_NOT_FOUND is returned otherwise. Pair with aiAgentEnabled: true to actually use it.
Toggle the AI reply agent for this campaign (default false)
Webhook configuration for campaign events
Enable webhook notifications
Webhook endpoint URL
Secret key for webhook signature verification
Events that trigger the webhook
Automatically detect and repair flagged content to maintain deliverability
Enable copy fatigue protection
Automatically regenerate flagged content
Automatically resume campaign after regeneration
A/B variant smart optimization settings
Enable automatic variant optimization
Minimum sends per variant before optimizing (default 25)
Minimum days before optimizing (default 3)
Metric used to determine winning variant (default "replyRate")
replyRateopenRateclickRateMinimum number of variants to keep active (default 1)
Mailbox IDs (legacy field)
Mailbox IDs to use for sending
Resolve mailboxes by email address
Use all mailboxes matching any of these tags
Use all mailboxes with this provider
Responses
draftactivepausedcompletedarchivedemailwaitcustom is a legacy value kept for read-back compatibility; new writes only accept disabled or auto.
disabledautocustomLegacy custom ESP matching rules. Read-only; new writes are ignored.
use_specific_mailboxes is a legacy value kept for read-back compatibility; on write it is normalized to disabled.
disabledskip_allskip_providersuse_specific_mailboxesSEG provider names to skip when segCheckMode is skip_providers.
proofpointmimecastbarracudaciscoforcepointsophostrendmicrosymantecmcafeemicrosoft_atpgoogle_postiniLegacy field. Read-only; new writes are ignored.
allby_providerindividualLegacy field. Read-only; new writes are ignored.
Legacy field. Read-only; new writes are ignored.
Last updated 4 days ago
Built with Documentation.AI