Skip to main content

Add campaign step

This endpoint allows you to add a new step at the end of a campaign, as long as the parent step has not yet processed any prospects.

Only campaigns with a status of DRAFT or EDITED can be updated. To change the campaign status to EDITED use the /make_editable endpoint.

Request

Endpoint

POST https://api.woodpecker.co/rest/v2/campaigns/{campaign_id}/steps

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 order to fetch the parent_id you can use the GET /campaigns structure endpoint

{
"parent_id": "9e8e8ebb-c6e1-4b8f-be37-a5542513dbge",
"step": {
"type": "EMAIL",
"delivery_time": {
"TUESDAY": [{ "from": "09:00", "to": "18:00" }],
"WEDNESDAY": [{ "from": "09:00", "to": "18:00" }],
"THURSDAY": [{ "from": "09:00", "to": "18:00" }]
},
"body": {
"versions": [
{
"subject": null,
"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>",
"signature": "SENDER",
"track_opens": true
},
{
"subject": "Example subject line - version B",
"message": "<div>{{SPINTAX | \"Hi\" | \"Hello\" | \"Good morning\"}} {{FIRST_NAME}},</div><div><br /></div><div>Yet another example of a cold email message.&nbsp;</div><div><br /></div><div>All the best,&nbsp;</div><div><a href=\"https://woodpecker.co\">Woodpecker</a> team</div><div><a href=\"{{UNSUBSCRIBE}}\">unsubscribe</a></div>",
"signature": "NO_SIGNATURE",
"track_opens": false
}
]
}
}
}

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.

This type defines an email step of a campaign, including its content, versions and delivery times.

FieldTypeDefaultRequiredDescription
typestring-YesUse EMAIL to indicate it is an email step
delivery_timeobject-YesTime intervals during which emails can be sent. Described in more detail below
bodyobject-YesEmail content configuration including A/B test versions. Described in more detail below
followup_afterobject1 DAYNoObject that specifies the time delay before processing a prospect in the next step; if delivery_time allows it. If not provided, a default delay of 1 DAY will be applied
└─rangestringDAYNoTime unit: DAY, HOUR, MINUTE
└─valueinteger1NoValue of the time unit (range: 1 - 9999)

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.

Each step must define at least one delivery interval. You can assign up to three intervals per day, but they must not overlap. If a day is omitted from the object, no emails will be sent on that day.

To specify a whole day interval, you can use either "from": "00:00", "to": "00:00" or "from": "00:00", "to": "24:00". The first format is set as the default.

FieldTypeDefaultRequiredDescription
MONDAY...SUNDAYarray[object]-YesArray of time windows for each day. Maximum 3 windows per day. 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 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
└─[].subjectstring/null-Yes, for the first EMAIL stepEmail subject line. Required for the first EMAIL step in a campaign. If multiple versions exist, all must include a subject.
For later EMAIL steps, a null subject sends the message as a follow-up in the same thread. Supports snippets like {{FIRST_NAME}}, snippet fallbacks and spintax
└─[].messagestring-YesEmail body content in HTML format. Supports snippets like {{FIRST_NAME}}, snippet fallbacks and spintax.
To track individual link clicks (not recommended), enclose the href attribute value in a {{CLICK}} snippet. Example: <a href=\"{{CLICK=https://google.com}}\">click here</a>
└─[].signaturestringNO_SIGNATURENoWhether to use the sender's email account signature. The available options are: SENDER or NO_SIGNATURE
└─[].track_opensbooleanfalseNoWhether to track email opens for this email version

Request samples

Add step

curl --request POST \
--url "https://api.woodpecker.co/rest/v2/campaigns/{campaign_id}/steps" \
--header "x-api-key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--data '{
"parent_id": "9e8e8ebb-c6e1-4b8f-be37-a5542513dbge",
"step": {
"type": "EMAIL",
"delivery_time": {
"TUESDAY": [
{
"from": "09:00",
"to": "18:00"
}
]
},
"body": {
"versions": [
{
"subject": null,
"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>",
"signature": "SENDER",
"track_opens": true
}
]
},
"followup_after": {
"range": "HOUR",
"value": 10
}
}
}'

Response

Response examples

The step has been added. A full campaign payload will be returned.