Order domain mailboxes
Order mailboxes for domains you already purchased in Woodpecker.
The mailboxes are preconfigured for cold emailing and ready to use in Woodpecker. To purchase a new domain together with mailboxes, use the order domains endpoint.
Request
This endpoint will create billable mailbox assets
Mailbox purchases are paid from your prepaid funds, so you need enough balance before placing an order. After purchase, mailbox renewals are covered by your regular monthly Woodpecker billing cycle. Use the get domain providers endpoint to check mailbox pricing before placing an order.
Endpoint
POST https://api.woodpecker.co/rest/v2/domains/mailboxes/order
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
{
"mailboxes": [
{
"first_name": "Richard",
"last_name": "Hendricks",
"email": "richard@piedpiper.com"
}
]
}
Body schema
| Field | Type | Required | Description |
|---|---|---|---|
mailboxes | array | Yes | Mailboxes to order for existing active domains |
└─ first_name | string | Yes | Mailbox owner's first name. Used to display the 'from name' |
└─ last_name | string | Yes | Mailbox owner's last name. Used to display the 'from name' |
└─ email | string | Yes | Mailbox email address to order |
Request samples
Order a mailbox
- cURL
- Python
- Java
- Node.js
- PHP
curl --request POST \
--url "https://api.woodpecker.co/rest/v2/domains/mailboxes/order" \
--header "x-api-key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--data '{
"mailboxes": [
{
"first_name": "Richard",
"last_name": "Hendricks",
"email": "richard@piedpiper.com"
}
]
}'
import requests
def order_mailboxes():
url = "https://api.woodpecker.co/rest/v2/domains/mailboxes/order"
headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"mailboxes": [
{
"first_name": "Richard",
"last_name": "Hendricks",
"email": "richard@piedpiper.com"
}
]
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 202:
return f"Mailbox order accepted: {response.status_code}"
else:
raise Exception(f"POST request failed: {response.status_code}, {response.text}")
if __name__ == "__main__":
try:
result = order_mailboxes()
print("POST response:", result)
except Exception as e:
print("Error:", e)
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class WoodpeckerApiClient {
public static void main(String[] args) {
try {
String url = "https://api.woodpecker.co/rest/v2/domains/mailboxes/order";
String jsonData = """
{
"mailboxes": [
{
"first_name": "Richard",
"last_name": "Hendricks",
"email": "richard@piedpiper.com"
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", "{YOUR_API_KEY}")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonData))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 202) {
System.out.println("POST response: Mailbox order accepted: " + response.statusCode());
} else {
throw new Exception("POST request failed: " + response.statusCode() + ", " + response.body());
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
const axios = require('axios');
async function orderMailboxes() {
const url = 'https://api.woodpecker.co/rest/v2/domains/mailboxes/order';
const headers = {
'x-api-key': '{YOUR_API_KEY}',
'Content-Type': 'application/json'
};
const data = {
mailboxes: [
{
first_name: 'Richard',
last_name: 'Hendricks',
email: 'richard@piedpiper.com'
}
]
};
try {
const response = await axios.post(url, data, { headers });
console.log('POST response:', `Mailbox order accepted: ${response.status}`);
} catch (error) {
console.error('POST request failed:', error.response ? error.response.status : error.message);
}
}
orderMailboxes();
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.woodpecker.co/rest/v2/',
'headers' => [
'x-api-key' => getenv('WOODPECKER_API_KEY'),
'Content-Type' => 'application/json',
],
]);
try {
$response = $client->post('domains/mailboxes/order', [
'json' => [
'mailboxes' => [
[
'first_name' => 'Richard',
'last_name' => 'Hendricks',
'email' => 'richard@piedpiper.com',
],
],
],
]);
echo $response->getStatusCode(), "\n";
echo $response->getBody(), "\n";
} catch (RequestException $e) {
echo "Error: ", $e->getMessage(), "\n";
if ($e->hasResponse()) {
echo $e->getResponse()->getBody(), "\n";
}
}
Response
Response examples
- 202
- 400
- 401
- 422
- 500
- 503
The order has been accepted for processing. Use the list domain mailboxes endpoint to review the processing status.
Invalid request or malformed request syntax
{
"title": "Bad Request",
"status": 400,
"details": "error details",
"timestamp": "2026-05-06T12:00:00Z"
}
Body schema
| Field | Type | Description |
|---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
details | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred |
Authentication failed. Please review the authentication guide
{
"title": "Unauthorized",
"status": 401,
"details": "error details",
"timestamp": "2026-05-06T12:00:00Z"
}
Body schema
| Field | Type | Description |
|---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
details | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred |
Returned when the request body is valid JSON but contains invalid or missing fields, or when business validation fails before the order can be accepted.
If code is insufficient_funds, add prepaid funds in Woodpecker before retrying the order.
{
"type": "validation_error",
"message": "Invalid field(s)",
"code": "invalid_fields",
"request_id": "dc4faa0f-78bf-54e9-9d5d-ce9538f2eec5",
"fields": [
{
"field": "mailboxes[0].email",
"issue": "Email domain must exist in order domains or active firm domains",
"value": "richard@missing.com"
}
]
}
Body schema
| Field | Type | Description |
|---|---|---|
type | string | Error type |
message | string | Error message |
code | string | Error code. Possible business error values include domain_owner_required, insufficient_funds, and payment_failed |
request_id | string or null | Request identifier when available |
fields | array/null | Fields that failed validation. Present for field-level validation errors |
└─ field | string | Field with a validation issue |
└─ issue | string | Detailed description of the validation issue |
└─ value | string/null | Rejected value, or null for a missing required field |
Unexpected server error
{
"title": "Internal Server Error",
"status": 500,
"details": "error details",
"timestamp": "2026-05-06T12:00:00Z"
}
Body schema
| Field | Type | Description |
|---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
details | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred |
Service unavailable or communication error
{
"title": "Service Unavailable",
"status": 503,
"details": "error details",
"timestamp": "2026-05-06T12:00:00Z"
}
Body schema
| Field | Type | Description |
|---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
details | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred |