Campaigns

How to use API 2.0 to manage campaigns in your Woodpecker account

Weronika Wróblewska avatar
Written by Weronika Wróblewska
Updated over a week ago

Create campaign

To create a campaign in your Woodpecker account, use the following request:

POST https://api.woodpecker.co/rest/v2/campaigns
{
"name": "Example campaign created via APIv2",
"email_account_ids": [
123000,
123001
],
"settings": {
"timezone": "Europe/Berlin",
"prospect_timezone": false,
"daily_enroll": 50,
"gdpr_unsubscribe": true,
"list_unsubscribe": true
},
"steps": {
"type": "START",
"followup": {
"type": "EMAIL",
"delivery_time": {
"MONDAY": [{ "from": "08:00", "to": "18:00" }],
"TUESDAY": [{ "from": "08:00", "to": "18:00" }],
"WEDNESDAY": [{ "from": "08:00", "to": "18:00" }],
"THURSDAY": [{ "from": "08:00", "to": "18:00" }],
"FRIDAY": [{ "from": "08:00", "to": "18:00" }],
"SATURDAY": [
{ "from": "08:00", "to": "10:00" },
{ "from": "16:00", "to": "18:00" }
]
},
"body": {
"versions": [
{
"subject": "Example subject for A version",
"message": "<div><p>Hi {{FIRST_NAME | \"there\"}},</p><p>This is an example cold email message.</p><p>Best wishes,<br><a href=\"https://woodpecker.co\">Woodpecker</a> team</p></div>",
"signature": "NO_SIGNATURE",
"track_opens": true
},
{
"subject": "Example subject for B version",
"message": "<div><p>Hi {{FIRST_NAME}},</p><p>This is an example cold email message.</p><p>Sincerely,<br><a href=\"https://woodpecker.co\">Woodpecker team</a></p></div>",
"signature": "NO_SIGNATURE",
"track_opens": true
}
]
},
"followup_after": {
"range": "DAY",
"value": 3
},
"followup": {
"type": "EMAIL",
"delivery_time": {
"FRIDAY": [{ "from": "08:00", "to": "18:00" }]
},
"body": {
"versions": [
{
"subject": null,
"message": "<div><p>Hello {{FIRST_NAME}},</p><p>It's almost weekend - a great time to learn how the the Woodpecker campaign API works. Feel free to respond this email asking about details.</p>",
"signature": "SENDER",
"track_opens": true
}
]
}
}
}
}
}

Sample response:

{
"id": 777777,
"name": "Example campaign created via APIv2",
"status":"DRAFT",
"email_account_ids": [
123000,
123001
],
"settings": {
"timezone": "Europe/Berlin",
"prospect_timezone": false,
"daily_enroll": 50,
"gdpr_unsubscribe": true,
"list_unsubscribe": true
},
"steps": {
"id": "286f0242-00d6-4572-a4be-e4414ac589ed",
"type": "START",
"followup": {
"id": "4dbd7af6-682b-4348-9950-77098baa9522",
"type": "EMAIL",
"delivery_time": {
"MONDAY": [{ "from": "08:00", "to": "18:00" }],
"TUESDAY": [{ "from": "08:00", "to": "18:00" }],
"WEDNESDAY": [{ "from": "08:00", "to": "18:00" }],
"THURSDAY": [{ "from": "08:00", "to": "18:00" }],
"FRIDAY": [{ "from": "08:00", "to": "18:00" }],
"SATURDAY": [
{ "from": "08:00", "to": "10:00" },
{ "from": "16:00", "to": "18:00" }
]
},
"body": {
"versions": [
{
"id": "5a9a2de59267e55213480a7ffffe181905dedbe68b6895739ef2bf6b1e5129a1",
"version": "A",
"subject": "Example subject for A version",
"message": "<div><p>Hi {{FIRST_NAME}},</p><p>This is an example cold email message.</p><p>Best wishes,<br><a href=\"https://woodpecker.co\">Woodpecker</a> team</p></div>",
"signature": "NO_SIGNATURE",
"track_opens": true
},
{
"id": "289e9f659addc6a83901de175ca1e819f1261427c35759ea966c05457bb1a7db",
"version": "B",
"subject": "Example subject for B version",
"message": "<div><p>Hi {{FIRST_NAME}},</p><p>This is an example cold email message.</p><p>Sincerely,<br><a href=\"https://woodpecker.co\">Woodpecker team</a></p></div>",
"signature": "NO_SIGNATURE",
"track_opens": true
}
]
},
"followup_after": {
"range": "DAY",
"value": 3
},
"followup": {
"id": "d38f2fc0-7bed-461e-a2bb-a3d4aa786bcc",
"type": "EMAIL",
"delivery_time": {
"FRIDAY": [{ "from": "08:00", "to": "18:00" }],
},
"body": {
"versions": [
{
"id": "289e9f659addc6a83901de175ca1e819d394ded2c4e4df2835bc0e9d251e4eab",
"version": "A",
"subject": "",
"message": "<div><p>Hello {{FIRST_NAME}},</p><p>It's almost weekend - a great time to learn how the the Woodpecker campaign API works. Feel free to respond this email asking about details.</p>",
"signature": "SENDER",
"track_opens": true
}
]
}
}
}
}
}

Response type data:

name

data type

default

description

name

string

“My campaign #0”

The name of the campaign.

email_account_ids

array <number>

-

List of email account IDs used to send campaign emails. All provided email accounts have to be active and without issues. It is required to provide at least 1 email account ID.

settings.timezone

string

-

The 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.

The time zone must be specified as the regional ID and be one of the following:

Accepted timezones

Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Asmara
Africa/Bamako
Africa/Bangui
Africa/Banjul
Africa/Bissau
Africa/Blantyre
Africa/Brazzaville
Africa/Bujumbura
Africa/Cairo
Africa/Casablanca
Africa/Conakry
Africa/Dakar
Africa/Dar_es_Salaam
Africa/Djibouti
Africa/El_Aaiun
Africa/Freetown
Africa/Gaborone
Africa/Harare
Africa/Johannesburg
Africa/Kampala
Africa/Khartoum
Africa/Kigali
Africa/Kinshasa
Africa/Lagos
Africa/Libreville
Africa/Lome
Africa/Luanda
Africa/Lusaka
Africa/Malabo
Africa/Maputo
Africa/Maseru
Africa/Mbabane
Africa/Mogadishu
Africa/Monrovia
Africa/Nairobi
Africa/Ndjamena
Africa/Niamey
Africa/Nouakchott
Africa/Ouagadougou
Africa/Porto-Novo
Africa/Sao_Tome
Africa/Tripoli
Africa/Tunis
Africa/Windhoek
America/Anchorage
America/Anguilla
America/Antigua
America/Argentina/Buenos_Aires
America/Aruba
America/Asuncion
America/Barbados
America/Belize
America/Bogota
America/Buenos_Aires
America/Caracas
America/Cayenne
America/Cayman
America/Chicago
America/Chihuahua
America/Costa_Rica
America/Denver
America/Dominica
America/Edmonton
America/El_Salvador
America/Godthab
America/Grand_Turk
America/Grenada
America/Guadeloupe
America/Guatemala
America/Guayaquil
America/Guyana
America/Halifax
America/Havana
America/Indianapolis
America/Jamaica
America/La_Paz
America/Lima
America/Los_Angeles
America/Managua
America/Manaus
America/Martinique
America/Mazatlan
America/Mexico_City
America/Miquelon
America/Monterrey
America/Montevideo
America/Montserrat
America/Nassau
America/New_York
America/Panama
America/Paramaribo
America/Phoenix
America/Port-au-Prince
America/Port_of_Spain
America/Puerto_Rico
America/Regina
America/Rio_Branco
America/Santiago
America/Santo_Domingo
America/Sao_Paulo
America/St_Johns
America/St_Kitts
America/St_Lucia
America/St_Thomas
America/St_Vincent
America/Tegucigalpa
America/Tijuana
America/Toronto
America/Tortola
America/Vancouver
America/Whitehorse
America/Winnipeg
Arctic/Longyearbyen
Asia/Aden
Asia/Almaty
Asia/Amman
Asia/Ashgabat
Asia/Baghdad
Asia/Bahrain
Asia/Baku
Asia/Bangkok
Asia/Beirut
Asia/Bishkek
Asia/Brunei
Asia/Calcutta
Asia/Chongqing
Asia/Colombo
Asia/Damascus
Asia/Dhaka
Asia/Dubai
Asia/Dushanbe
Asia/Gaza
Asia/Hong_Kong
Asia/Irkutsk
Asia/Istanbul
Asia/Jakarta
Asia/Jerusalem
Asia/Kamchatka
Asia/Karachi
Asia/Kathmandu
Asia/Kolkata
Asia/Krasnoyarsk
Asia/Kuala_Lumpur
Asia/Kuwait
Asia/Macau
Asia/Magadan
Asia/Manila
Asia/Muscat
Asia/Nicosia
Asia/Novosibirsk
Asia/Omsk
Asia/Phnom_Penh
Asia/Pyongyang
Asia/Qatar
Asia/Rangoon
Asia/Riyadh
Asia/Seoul
Asia/Shanghai
Asia/Singapore
Asia/Taipei
Asia/Tashkent
Asia/Tbilisi
Asia/Tehran
Asia/Thimphu
Asia/Tokyo
Asia/Ulaanbaatar
Asia/Ulan_Bator
Asia/Urumqi
Asia/Vientiane
Asia/Vladivostok
Asia/Yakutsk
Asia/Yerevan
Atlantic/Azores
Atlantic/Bermuda
Atlantic/Cape_Verde
Atlantic/Faroe
Atlantic/Reykjavik
Atlantic/South_Georgia
Atlantic/St_Helena
Atlantic/Stanley
Australia/Adelaide
Australia/Brisbane
Australia/Canberra
Australia/Darwin
Australia/Hobart
Australia/Melbourne
Australia/Perth
Australia/Sydney
Canada/Atlantic
Canada/Eastern
Canada/Mountain
Canada/Newfoundland
Canada/Saskatchewan
Europe/Amsterdam
Europe/Athens
Europe/Belgrade
Europe/Berlin
Europe/Bratislava
Europe/Brussels
Europe/Bucharest
Europe/Budapest
Europe/Chisinau
Europe/Copenhagen
Europe/Dublin
Europe/Gibraltar
Europe/Guernsey
Europe/Helsinki
Europe/Isle_of_Man
Europe/Istanbul
Europe/Jersey
Europe/Kiev
Europe/Lisbon
Europe/Ljubljana
Europe/London
Europe/Luxembourg
Europe/Madrid
Europe/Malta
Europe/Minsk
Europe/Monaco
Europe/Moscow
Europe/Oslo
Europe/Paris
Europe/Podgorica
Europe/Prague
Europe/Riga
Europe/Rome
Europe/San_Marino
Europe/Sarajevo
Europe/Skopje
Europe/Sofia
Europe/Stockholm
Europe/Tallinn
Europe/Vaduz
Europe/Vatican
Europe/Vienna
Europe/Vilnius
Europe/Volgograd
Europe/Warsaw
Europe/Zagreb
Europe/Zurich
Hongkong
Indian/Antananarivo
Indian/Chagos
Indian/Christmas
Indian/Cocos
Indian/Comoro
Indian/Kerguelen
Indian/Mahe
Indian/Maldives
Indian/Mauritius
Indian/Mayotte
Indian/Reunion
Pacific/Auckland
Pacific/Efate
Pacific/Fakaofo
Pacific/Fiji
Pacific/Funafuti
Pacific/Guadalcanal
Pacific/Guam
Pacific/Honolulu
Pacific/Kiritimati
Pacific/Midway
Pacific/Nauru
Pacific/Niue
Pacific/Norfolk
Pacific/Noumea
Pacific/Palau
Pacific/Pitcairn
Pacific/Pohnpei
Pacific/Port_Moresby
Pacific/Rarotonga
Pacific/Saipan
Pacific/Tahiti
Pacific/Tarawa
Pacific/Tongatapu
Pacific/Wallis
Singapore
US/Alaska
US/Arizona
US/Central
US/East-Indiana
US/Eastern
US/Hawaii
US/Mountain
US/Samoa
UTC

settings.prospect_timezone

boolean

false

A flag indicating whether the prospect timezone should be used instead of the timezone configured in the settings.timezone field.

settings.daily_enroll

number

-

Indicates how many email messages per day can be sent from the campaign.

The value must be greater than 0 and not greater than your general sending limit.

settings.gdpr_unsubscribe

boolean

false

GDPR-compliant unsubscribe.

It allows your prospects to easily unsubscribe from your emails and delete their data from Woodpecker.

This option will only function when the {{UNSUBSCRIBE}} snippet is added to your email or account signature.

settings.list_unsubscribe

boolean

false

List-unsubscribe header.

List-unsubscribe lets your prospects unsubscribe from your emails in 1 click.

This option will only function when the {{UNSUBSCRIBE}} snippet is added to your email or account signature.

steps

object

-

Defines the campaign flow in the tree-like structure. The first step here has to be always START step.


Available steps

This step always has to be the first (root) step of the campaign. It can’t occur anywhere else in the campaign tree.

  • type – string; only the value START is acceptable here to indicate that this is a START step.

  • followup – object; the follow-up step definition. As this is a START step, the next step must be non-null and will be the first one to include any action with the prospect.


Email step

The email step is used to send an email message to the prospect.

  • type – string; only the value EMAIL is accepted here to indicate that it is an EMAIL step.

  • delivery_time – object; specifies the time intervals when the email messages can be sent.

    The only acceptable object keys are days of week, specifically: SUNDAY, MONDAY, TUESDAY, WEDNESDAY,THURSDAY,FRIDAY,SATURDAY.

    The only acceptable object values are lists of time interval objects. The time interval object is an object with from and to keys, where the time is specified as a string in format HH:mm, e.g. {"from": "08:00", "to": "18:00"}. The from value always has to be lower than to value.

    Multiple time intervals assigned to a single day are allowed, but even if there is only a one-time interval, the array brackets are mandatory. If there is a list of time intervals, specific intervals cannot overlap each other. The absence of a day in the object means that no email will be sent that day.

    To mark the whole day interval, both from="00:00" to="00:00" and from="00:00" to="24:00" formats are supported. However, the first one is used by default (e.g. when asking API for campaign details).

    Example:

    {
    "MONDAY": [
    {"from": "08:00", "to": "12:30"},
    {"from": "13:00", "to": "15:00"},
    {"from": "16:45", "to": "21:00"}
    ],
    "TUESDAY": [
    {"from": "11:00", "to": "19:00"}
    ],
    "SATURDAY": [
    {"from": "00:00", "to": "00:00"}
    ]
    }

    Using the above example, emails will only be sent on Mondays and Tuesdays. On Mondays from 8:00 a.m. to 12:30 p.m., then from 1:00 p.m. to 3:00 p.m., and then from 2:45 p.m. to 9:00 p.m. On Tuesdays, emails will be sent from 11:00 a.m. to 7:00 p.m. On Saturdays, emails will be sent the whole day. In a valid campaign, at least one interval has to be defined.

  • body.versions – array <object>; concrete email definitions. At least one version object is required. Providing more versions will result in using A/B testing for this step. Even if only one version is used, the array brackets are mandatory. The order of versions provided in the array matters. The first provided version will be marked as an A version in the Woodpecker application, the second provided version will be marked as a B version, etc.

    There is a limit of a maximum of 5 versions. All configured versions will be enabled. The version object details can be found below this table.

  • followup_after.range – string; default: DAY; Range used to indicate how long to wait before firing the followup step. The only acceptable values are DAY and HOUR.

    The whole followup_after object is optional. If not provided, the default 1 DAY will be used.

  • followup_after.value – number; default: 1; The concrete value of the time unit from followup_after.range field is used to indicate how long to wait before firing the followup step. If provided, value must be greater than 0 and less than 10000.

    The whole followup_after object is optional. If not provided, the default 1 DAY will be used.

  • followup – object; default: null (meaning no followup); The followup step definition.


Version object

name

data type

default

description

subject

string

(use previous message thread)

Subject of the email message.

This field is always required if the version is part of the first EMAIL step in the path; it must be assigned to all step versions if there is more than one version.

If the step is not the first EMAIL step in the path and the subject field is null, then the message will be sent as a follow-up in the same thread.

message

string

-

The email message that will be sent to the prospect. Can use HTML tags.

signature

string

-

Specifies if the sender's email account signature should be used. The only available values are: SENDER, NO_SIGNATURE.

track_opens

boolean

-

A flag indicating whether Woodpecker should track the email opens.


Snippets

In the subject line or email message step, you can use any of the following snippets:

  • {{FIRST_NAME}}

  • {{LAST_NAME}}

  • {{FULL_NAME}}

  • {{COMPANY}}

  • {{EMAIL}}

  • {{WWW}}

  • {{TAG}}

  • {{LINKEDIN_URL}}

  • {{TITLE}}

  • {{PHONE}}

  • {{ADDRESS}}

  • {{CITY}}

  • {{STATE}}

  • {{COUNTRY}}

  • {{INDUSTRY}}

  • {{UNSUBSCRIBE}}

  • {{SNIPPET_1}}

  • {{SNIPPET_2}}

  • {{SNIPPET_3}}

  • {{SNIPPET_4}}

  • {{SNIPPET_5}}

  • {{SNIPPET_6}}

  • {{SNIPPET_7}}

  • {{SNIPPET_8}}

  • {{SNIPPET_9}}

  • {{SNIPPET_10}}

  • {{SNIPPET_11}}

  • {{SNIPPET_12}}

  • {{SNIPPET_13}}

  • {{SNIPPET_14}}

  • {{SNIPPET_15}}

Currently, Snippet Labels are not supported.

You can set a fallback for each snippet: a default value that will be substituted if the prospect does not have data for that snippet. Snippet fallbacks follow this format: {{SNIPPET_NAME | "Filler Value"}}, where:

  • SNIPPET_NAME: The name of one of the supported snippets among the available positions.

  • Filler Value: The default value to substitute. This can be left blank.

Examples of correctly defined snippet fallbacks:

  • {{FIRST_NAME | "there"}}

  • {{FIRST_NAME | ""}}

  • {{SNIPPET_1 | "contain "quoted" text without escape character"}}

Remember to escape the quotation marks \"there\" when defining Snippet fallbacks in the request.

For further details about snippet fallbacks, please refer to Snippet Fallbacks Documentation.


Campaign statuses

  • RUNNING

  • DRAFT

  • STOPPED

  • PAUSED

  • EDITED

Response payload details

After creating the campaign successfully, the HTTP status 201 CREATED will be returned along with a payload containing the campaign details in the same format as in "Request payload" with some additional fields:

  • id for the campaign - numeric

  • status campaign status; for the newly created campaign, it’s always DRAFT

  • id for every step - string representation of UUID

  • id for every email version - string unique hash of 64 characters

  • version for every email version - the letter mark of the version, only the values A, B, C, D, E are possible

Errors

In case of an error during the campaign creation, the HTTP status 4xx or 5xx will be returned along with the payload containing type, message, and details fields. The type defines the general problem and message can contain some additional information about the problem or instructions on how to fix it. The details field is currently always the null value, but in the future, it may provide some additional data which can help identify the problem in the payload.

Sample error payload

{ 
"type": "MISSING_FEATURES",
"message": "Upgrade your plan",
"details": null
}

Error list

HTTP status

type

description

400

INPUT_DATA_VALIDATION_FAILURE

The request payload is not valid, e.g., required fields are not provided, and there is no subject for the first EMAIL step in the flow.

403

MISSING_FEATURES

The campaign uses features that aren’t available for the account.

409

VALIDATION_FAILURE

There is an issue related to the campaign, such as an assigned email having some problems. The current version of the endpoint does not indicate the problematic fields.

500

UNKNOWN

An unknown error occurred.


Get campaign

To get the name of a campaign, use the following request:

GET /rest/v2/campaigns/{campaign_id:[0-9]+}

Successful response:

If the campaign was found and can be fetch via APIv2. 
HTTP 200 Ok

The payload returned by this endpoint is the same
as the one returned by the campaign's successful creation.

Error response:

If the campaign with given id was not found. 
HTTP 404 Not Found
{
"type": "CAMPAIGN_NOT_EXIST",
"message": "Campaign not found",
"details": null
}
If the campaign with given id contains currently unsupported features. HTTP 409 Conflict 
{
"type": "API_UNSUPPORTED_CAMPAIGN_FEATURES",
"message": "Campaign contains currently unsupported features",
"details": null
}
In case of unexpected error during get the given campaign.
HTTP 500 Internal Server Error
{
"type": "UNKNOWN",
"message": "Unknown error during get campaign call",
"details": null
}

Delete campaign

To delete the campaign from Woodpecker, use the following request:

DELETE /rest/v2/campaigns/{campaign_id:[0-9]+}

Successful response:

If the campaign was successfully stopped.
HTTP 200 Ok

Error response:

If the campaign with given id was not found.
HTTP 404 Not Found
{
"type": "CAMPAIGN_NOT_EXIST",
"message": "Campaign not found",
"details": null
}
If the campaign with given id was related to active workflow.
HTTP 409 Conflict
{
"type": "CAMPAIGN_RELATED_TO_ACTIVE_WORKFLOW",
"message": "Campaign related to active workflow",
"details": null
}
In case of unexpected error during deleting the given campaign.
HTTP 500 Internal Server Error
{
"type": "UNKNOWN",
"message": "Unknown error during delete campaign call",
"details": null
}

Pause campaign

To pause campaigns in Woodpecker, use the following request:

POST /rest/v2/campaigns/{campaign_id:[0-9]+}/pause

Successful response:

If the campaign was successfully paused.
HTTP 200 Ok

Error response:

If the campaign with given id was not found.
HTTP 404 Not Found
{
"type": "CAMPAIGN_NOT_EXIST",
"message": "Campaign not found",
"details": null
}
In case of unexpected error during pausing the given campaign.
HTTP 500 Internal Server Error
{
"type": "UNKNOWN",
"message": "Unknown error during pause campaign call",
"details": null
}

Run campaign

If any of the fields in the campaign do not meet the requirements specified in the campaign POST /campaigns model, a response with an HTTP 400 status code is returned.

The current version of the endpoint allows running a campaign with EMAIL steps and A/B tests (multiple email versions per step). Attempting to run a campaign created with the Woodpecker editor and containing at least one of the following features will result in a response with a 409 status code.

Unsupported campaign features:

  • step with a condition,

  • generic manual task step,

  • call manual task step,

  • LinkedIn manual task step,

  • LinkedIn automation step,

  • AI video snippet,

  • schedule start settings.


To run a campaign, use the following request:

POST /rest/v2/campaigns/{campaign_id:[0-9]+}/run

Successful response:

If the campaign was successfully run.
HTTP 200 Ok

Error response:

If the campaign with given id was not found.
HTTP 404 Not Found
{
"type": "CAMPAIGN_NOT_EXIST",
"message": "Campaign not found",
"details": null
}
If the campaign uses features that are not covered by your product and Add-ons.
HTTP 403 Forbidden
{
"type": "MISSING_FEATURES",
"message": "Upgrade your plan",
"details": null
}
If the campaign cannot be run due to validation problems. 
HTTP 409 Conflict
{
"type": "VALIDATION_FAILURE",
"message": "Validation failure",
"details": null
}
In case of unexpected error during running the given campaign.
HTTP 500 Internal Server Error
{
"type": "UNKNOWN",
"message": "Unknown error during run campaign call",
"details": null
}

Stop campaign

To stop a campaign, use the following request:

POST /rest/v2/campaigns/{campaign_id:[0-9]+}/stop

Successful response:

If the campaign was successfully stopped.
HTTP 200 Ok

Error response:

If the campaign with given id was not found.
HTTP 404 Not Found
{
"type": "CAMPAIGN_NOT_EXIST",
"message": "Campaign not found",
"details": null
}
In case of unexpected error during stopping the given campaign.
HTTP 500 Internal Server Error
{
"type": "UNKNOWN",
"message": "Unknown error during stop campaign call",
"details": null
}
Did this answer your question?