Skip to main content

Create campaign

Create an email campaign with a sequence of personalized follow-up messages and customizable delivery settings. Configure campaign-wide settings like timezone and daily limits, define email content with support for A/B testing, scheduled delivery windows, and time delays between steps.

Request

Endpoint

POST https://api.woodpecker.co/rest/v2/campaigns

Headers

x-api-key: {YOUR_API_KEY}
Content-type: application/json

For details on how to authenticate your requests, please see the authentication guide.

Body

The campaign payload includes several objects, which are described in detail below. In addition to the general campaign configuration, a campaign is made up of steps that define its structure and actions for each prospect. Every campaign must begin with a START step, followed by 1 to 16 EMAIL steps. Subsequent steps are linked using nested follow-up properties, forming a sequence of steps. Each step includes its own configuration and points to the next step, or null if it is the final step

{
"email_account_ids": [
112233
],
"settings": {
"timezone": "Europe/Warsaw",
"daily_enroll": 40
},
"steps": {
"type": "START",
"followup": {
"type": "EMAIL",
"delivery_time": {
"MONDAY": [
{
"from": "08:00",
"to": "17:00"
}
]
},
"body": {
"versions": [
{
"subject": "Hi {{FIRST_NAME | \"there\"}}. {{SPINTAX | \"Hi\" | \"Hello\" | \"Good morning\"}}",
"message": "<div>Hi {{FIRST_NAME | \"there\"}},</div><div><br /></div><div>This is an example cold email message.&nbsp;</div><div><br /></div><div>Best wishes,&nbsp;</div><div><a href=\"https://woodpecker.co\">Woodpecker</a> team</div><div><a href=\"{{UNSUBSCRIBE}}\">unsubscribe</a></div>",
"track_opens": true
}
]
}
}
}
}

Body schema

This section provides the body schema for each object in the campaign payloads. For a more detailed overview, please refer to the campaign schema.

Campaign configuration object

The root level of the campaign payload. It provides general information about the campaign and campaign-wide settings.

FieldTypeDefaultRequiredDescription
namestring“My campaign #0”NOName of the campaign
email_account_idsarray[integer]-YESList of email account SMTP IDs used in this campaign. Use /mailboxes endpoint to review them. Chosen mailboxes must be connected to Woodpecker without issues
settingsobject-YESCampaign-level settings like timezone, sending limit, unsubscribe settings, etc
└─timezonestring-YESThe default timezone of a campaign. It will be used when setting.prospect_timezone is disabled or when it is enabled but the prospect's timezone is not specified. List of accepted timezones
└─prospect_timezonebooleanfalseNOWhether to adjust sending times to prospect's timezone instead of the campaign timezone
└─daily_enrollinteger-YESMaximum number of opening emails that can be sent per day. The limit is shared between all mailboxes. The default maximum value is 500
└─gdpr_unsubscribebooleanfalseNOWhether the unsubscribe link should provide prospects with an option for GDPR-compliant data removal. This option will work only if the {{UNSUBSCRIBE}} snippet is included in your email or account signature
└─list_unsubscribebooleanfalseNOWhether to include List-Unsubscribe header. This option will work only if the {{UNSUBSCRIBE}} snippet is included in your email or account signature
└─open_disabled_listarray[string]/null[]NOList of email service providers (recipient's ESP) for which open tracking is disabled. Available options: google.com, outlook.com, OTHER_PROVIDER
└─auto_pause_prospect_from_domainboolean/nullfalseNOWhether to automatically pause sending to prospects after a response from the same domain (free providers excluded)
└─catch_all_verification_modestringBALANCEDNOCatch-all email verification mode - how to approach contacting prospects using catch-all emails.
  • NONE - contact all catch-all emails, including undeliverable
  • BALANCED - contact deliverable and risky catch-all emails
  • MAXIMUM - contact only deliverable catch-all emails
  • ONLY_VERIFY - do not contact catch-all emails
stepsobject-YESCampaign steps, including all emails and their delivery times, content, etc
"catch_all_verification_mode": "MAXIMUM",
Steps objects

This object defines a step of a campaign, including its content, versions, delivery times, and follow-ups. A START step contains only of type and followup properties.

FieldTypeDefaultRequiredDescription
typestring-YESSTART is always the first step of a campaign; the remaining steps are EMAIL
delivery_timeobject-YESTime intervals during which emails can be sent
bodyobject-YESEmail content configuration including A/B test versions
followup_afterobject1 DAYNOObject that specifies the time delay before processing a prospect in the next step; if delivery_time allows it
└─rangestringDAYNOTime unit - DAY, HOUR, MINUTE
└─valueinteger1NOValue of the time unit
followupobject/nullnull (meaning no followup)NONext step in the sequence. Consists of an EMAIL step object. Null indicates end of sequence. Followup object is required in the START step
Delivery time object

The delivery_time object defines the time intervals during which email messages can be sent. The timezone will follow the settings of the timezone and prospect_timezone of the campaign configuration.

FieldTypeDefaultRequiredDescription
MONDAY...SUNDAYarray[object]-YESArray of time windows for each day. Maximum 2 windows per day, at least one day must be present. The valid keys are the days of the week: MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
└─[].fromstring-YESStart time in "HH:mm" format (24-hour)
└─[].tostring-YESEnd time in "HH:mm" format (24-hour)
Body object

The body and versions objects define the email content, A/B test versions, open tracking, and signature settings. Each of these can be configured individually for each version, and at least one version must be present.

FieldTypeDefaultRequiredDescription
body.versionsarray[object]-YESArray of email version objects and their definitions. At least one version is required. A/B versions will be assigned based on the order of the array
└─[].subjectstring/null-YES, for the first EMAIL stepEmail subject line. This field is required if the version is part of the first EMAIL step in the sequence. It must be included in all step versions if multiple versions exist. If the step is not the first EMAIL step and the subject field is null, the message will be sent as a follow-up in the same thread. Supports snippets like {{FIRST_NAME}} and spintax
└─[].messagestring-YESEmail body content in HTML format. Supports snippets like {{FIRST_NAME}} and spintax
└─[].signaturestringNO_SIGNATURENOWhether to use the sender's email account signature. The available options are: SENDER or NO_SIGNATURE
└─[].track_opensboolean-YESWhether to track email opens for this email version

Request sample

Create campaign

curl --request POST \
--url "https://api.woodpecker.co/rest/v2/campaigns" \
--header "x-api-key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--data '{
"email_account_ids": [112233],
"settings": {
"timezone": "Europe/Warsaw",
"daily_enroll": 40
},
"steps": {
"type": "START",
"followup": {
"type": "EMAIL",
"delivery_time": {
"MONDAY": [
{
"from": "08:00",
"to": "17:00"
}
]
},
"body": {
"versions": [
{
"subject": "Hi {{FIRST_NAME | \"there\"}}. {{SPINTAX | \"Hi\" | \"Hello\" | \"Good morning\"}}",
"message": "<div>Hi {{FIRST_NAME | \"there\"}},</div><div><br /></div><div>This is an example cold email message.&nbsp;</div><div><br /></div><div>Best wishes,&nbsp;</div><div><a href=\"https://woodpecker.co\">Woodpecker</a> team</div><div><a href=\"{{UNSUBSCRIBE}}\">unsubscribe</a></div>",
"track_opens": true
}
]
}
}
}
}'

Response

Response examples

Campaign created. The returned body will be a full campaign payload, which consists of any optional fields that were not included in the POST request, along with the following information:

  • id - unique identifiers for the campaign, each step, and version
  • status - status of the campaign, always DRAFT after creation
  • version - version identifiers for each email, ranging from A to E

You can review the full campaign payload here.