Update step
Use this request to update a step's delivery times. This request replaces the entire delivery_times
object. Any existing values not included in the request will be removed.
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
PATCH https://api.woodpecker.co/rest/v2/campaigns/{campaign_id}/steps/{step_id}
You can fetch the step_id
and version_id
using the GET /campaigns structure endpoint.
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 request body is the delivery time object. Below is a simplified example that would overwrite the current settings and configure the campaign to be sent on two specific days.
{
"delivery_time": {
"WEDNESDAY": [
{
"from": "09:00",
"to": "17:00"
}
],
"THURSDAY": [
{
"from": "09:00",
"to": "11:00"
},
{
"from": "14:00",
"to": "16:00"
}
]
}
}
Body schema
The delivery_time
object defines the time intervals during which email messages can be sent. You can assign up to three time intervals to a single day. The timezone will follow the settings of the timezone
and prospect_timezone
of the campaign configuration.
Field | Type | Default | Required | Description |
---|---|---|---|---|
MONDAY ...SUNDAY | array[object] | - | Yes | Array of time windows for each day. Maximum 3 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 |
└─[].from | string | - | Yes | Start time in "HH:mm" format (24-hour) |
└─[].to | string | - | Yes | End time in "HH:mm" format (24-hour) |
Request sample
Update step delivery times
- cURL
- Python
- Java
- Node.js
curl --request PATCH "https://api.woodpecker.co/rest/v2/campaigns/{campaign_id}/steps/{step_id}" \
--header "Content-Type: application/json" \
--header "x-api-key: {YOUR_API_KEY}" \
--data '{
"delivery_time": {
"WEDNESDAY": [
{
"from": "09:00",
"to": "17:00"
}
],
"THURSDAY": [
{
"from": "09:00",
"to": "11:00"
},
{
"from": "14:00",
"to": "16:00"
}
]
}
}'
import requests
def updateStepDeliveryTimes(campaign_id, step_id):
url = f"https://api.woodpecker.co/rest/v2/campaigns/{campaign_id}/steps/{step_id}"
headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"delivery_time": {
"WEDNESDAY": [
{
"from": "09:00",
"to": "17:00"
}
],
"THURSDAY": [
{
"from": "09:00",
"to": "11:00"
},
{
"from": "14:00",
"to": "16:00"
}
]
}
}
response = requests.patch(url, headers=headers, json=payload)
if response.status_code == 200:
print("PATCH successful:", response.json())
else:
print("PATCH failed with status:", response.status_code)
if __name__ == "__main__":
updateStepDeliveryTimes(123, 456) # Example IDs
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class WoodpeckerApiClient {
private static final String API_KEY = "{YOUR_API_KEY}";
public static void main(String[] args) {
int campaignId = 123;
int stepId = 456;
updateStepDeliveryTimes(campaignId, stepId);
}
public static void updateStepDeliveryTimes(int campaignId, int stepId) {
try {
String url = "https://api.woodpecker.co/rest/v2/campaigns/" + campaignId + "/steps/" + stepId;
String jsonData = "{"
+ "\"delivery_time\": {"
+ "\"WEDNESDAY\": ["
+ " {\"from\": \"09:00\", \"to\": \"17:00\"}"
+ "],"
+ "\"THURSDAY\": ["
+ " {\"from\": \"09:00\", \"to\": \"11:00\"},"
+ " {\"from\": \"14:00\", \"to\": \"16:00\"}"
+ "]"
+ "}"
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(url))
.header("x-api-key", API_KEY)
.header("Content-Type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString(jsonData))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println("PATCH response: " + response.body());
} else {
System.err.println("PATCH request failed: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
const axios = require("axios");
async function updateStepDeliveryTimes(campaignId, stepId) {
const url = `https://api.woodpecker.co/rest/v2/campaigns/${campaignId}/steps/${stepId}`;
const headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
};
const data = {
delivery_time: {
WEDNESDAY: [
{
from: "09:00",
to: "17:00"
}
],
THURSDAY: [
{
from: "09:00",
to: "11:00"
},
{
from: "14:00",
to: "16:00"
}
]
}
};
try {
const response = await axios.patch(url, data, { headers: headers });
if (response.status === 200) {
console.log("PATCH successful:", response.data);
} else {
console.error("PATCH failed with status:", response.status);
}
} catch (error) {
console.error("Request error:", error.response?.status || error.message);
}
}
updateStepDeliveryTimes(123, 456); // Example IDs
Response
Response examples
- 200
- 400
- 401
- 404
- 409
- 500
The campaign has been updated. A full campaign payload will be returned.
Invalid request or malformed syntax. Please review the request
{
"code": "INPUT_DATA_VALIDATION_FAILURE" | "Bad Request",
"message": "Input data validation failure" | "Value of {field_name} is incorrect.",
"details": null
}
Body schema
Field | Type | Description |
---|---|---|
code | string | Error code |
message | string | Descriptive error message |
details | string/null | Additional information. Currently always null |
An issue with authorization. Please review the authorization guide
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid api key",
"timestamp": "2025-03-05 17:57:00"
}
Body schema
Field | Type | Description |
---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
detail | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred, YYYY-MM-DD HH:MM:SS UTC |
Please review the request URL.
{
"title": "Not Found",
"status": 404,
"detail": "Requested resource does not exist",
"timestamp": "2025-03-05 17:57:00"
}
Body schema
Field | Type | Description |
---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
detail | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred, YYYY-MM-DD HH:MM:SS UTC |
Returned when the campaign or step is either not found or is in a state that doesn't allow editing.
{
"code": "NOT_EDITABLE_STATUS" | "BRANCH_NOT_EDITABLE" | "CAMPAIGN_NOT_EXIST" | "BRANCH_NOT_FOUND",
"message": "The campaign must be in DRAFT or EDITED status to be updated" | "Step is not allowed to be edited" | "Campaign not found" | "Step not found",
"details": null
}
Body schema
Field | Type | Description |
---|---|---|
code | string | Error code |
message | string | Descriptive error message |
details | string/null | Additional information. Currently always null |
An unknown error while updating the campaign. Please try again later.
{
"type": "UNKNOWN",
"message": "Unknown error during campaign call",
"details": null
}