Update mailbox profile picture
Add or update the profile picture for an existing mailbox. This helps recipients recognize the sender more easily. Currently, this feature is supported for Google mailboxes.
Request
Endpoint
PATCH https://api.woodpecker.co/rest/v2/domains/{domain_name}/mailboxes/{mailbox_email}/profile_picture
Headers
x-api-key: {YOUR_API_KEY}
Content-Type: application/json
For details on how to authenticate your requests, please see the authentication guide.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
domain_name | Yes | string | Domain name |
mailbox_email | Yes | string | Mailbox email address. The mailbox must belong to the domain in domain_name. URL-encode the mailbox email address, for example richard%40piedpiper.com |
Body
{
"avatar": "ikAtLQMKKAFooAWkoELVrT4w92..."
}
Body schema
| Field | Type | Required | Description |
|---|---|---|---|
avatar | string | Yes | PNG or JPEG image encoded as Base64. Send only the Base64 content, without a Data URL prefix such as data:image/png;base64, |
The decoded image can be up to 5 MB or 4096x4096 pixels. We recommend using smaller, lightweight images when possible.
Request samples
Update profile picture
- cURL
- Python
- Java
- Node.js
- PHP
curl --request PATCH \
--url "https://api.woodpecker.co/rest/v2/domains/piedpiper.com/mailboxes/richard%40piedpiper.com/profile_picture" \
--header "x-api-key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--data '{
"avatar": "iVBORw0KGgoAAAANSUhEUgAA..."
}'
import requests
def update_mailbox_profile_picture(domain_name, mailbox_email):
encoded_mailbox_email = requests.utils.quote(mailbox_email, safe="")
url = f"https://api.woodpecker.co/rest/v2/domains/{domain_name}/mailboxes/{encoded_mailbox_email}/profile_picture"
headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"avatar": "iVBORw0KGgoAAAANSUhEUgAA..."
}
response = requests.patch(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"PATCH request failed: {response.status_code}, {response.text}")
if __name__ == "__main__":
try:
data = update_mailbox_profile_picture("piedpiper.com", "richard@piedpiper.com")
print("PATCH response:", data)
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;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class WoodpeckerApiClient {
public static void main(String[] args) {
try {
String domainName = "piedpiper.com";
String mailboxEmail = "richard@piedpiper.com";
String encodedMailboxEmail = URLEncoder.encode(mailboxEmail, StandardCharsets.UTF_8);
String url = "https://api.woodpecker.co/rest/v2/domains/" + domainName + "/mailboxes/" + encodedMailboxEmail + "/profile_picture";
String jsonData = """
{
"avatar": "iVBORw0KGgoAAAANSUhEUgAA..."
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", "{YOUR_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 {
throw new Exception("PATCH request failed: " + response.statusCode() + ", " + response.body());
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
const axios = require('axios');
async function updateMailboxProfilePicture(domainName, mailboxEmail) {
const encodedMailboxEmail = encodeURIComponent(mailboxEmail);
const url = `https://api.woodpecker.co/rest/v2/domains/${domainName}/mailboxes/${encodedMailboxEmail}/profile_picture`;
const headers = {
'x-api-key': '{YOUR_API_KEY}',
'Content-Type': 'application/json'
};
const data = {
avatar: 'iVBORw0KGgoAAAANSUhEUgAA...'
};
try {
const response = await axios.patch(url, data, { headers });
console.log('PATCH response:', response.data);
} catch (error) {
console.error('PATCH request failed:', error.response ? error.response.status : error.message);
}
}
updateMailboxProfilePicture('piedpiper.com', 'richard@piedpiper.com');
<?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 {
$domainName = 'piedpiper.com';
$mailboxEmail = rawurlencode('richard@piedpiper.com');
$response = $client->patch("domains/{$domainName}/mailboxes/{$mailboxEmail}/profile_picture", [
'json' => [
'avatar' => 'iVBORw0KGgoAAAANSUhEUgAA...',
],
]);
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
- 200
- 400
- 401
- 422
- 500
- 503
The profile picture has been updated
{
"success": true
}
Body schema
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the profile picture update succeeded |
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.
{
"type": "validation_error",
"message": "Invalid field(s)",
"code": "invalid_fields",
"request_id": "dc4faa0f-78bf-54e9-9d5d-ce9538f2eec5",
"fields": [
{
"field": "avatar",
"issue": "must be a valid Base64 encoded file",
"value": null
}
]
}
Body schema
| Field | Type | Description |
|---|---|---|
type | string | Error type |
message | string | Error message |
code | string | Error code |
request_id | string or null | Request identifier when available |
fields | array | Fields that failed validation |
└─ field | string | Field with a validation issue. Possible fields include domain_name, mailbox_email, and avatar |
└─ 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 |