curl --request POST \
--url https://api.sendpost.io/api/v1/account/webhook \
--header 'Content-Type: application/json' \
--header 'X-Account-ApiKey: <api-key>' \
--data '
{
"enabled": true,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"delivered": true,
"dropped": true,
"hardBounced": true,
"softBounced": true,
"opened": true,
"clicked": true,
"unsubscribed": true,
"spam": true
}
'import requests
url = "https://api.sendpost.io/api/v1/account/webhook"
payload = {
"enabled": True,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"delivered": True,
"dropped": True,
"hardBounced": True,
"softBounced": True,
"opened": True,
"clicked": True,
"unsubscribed": True,
"spam": True
}
headers = {
"X-Account-ApiKey": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Account-ApiKey': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
enabled: true,
url: 'https://app.hooli.com/api/webhooks/sendpost',
delivered: true,
dropped: true,
hardBounced: true,
softBounced: true,
opened: true,
clicked: true,
unsubscribed: true,
spam: true
})
};
fetch('https://api.sendpost.io/api/v1/account/webhook', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sendpost.io/api/v1/account/webhook",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'enabled' => true,
'url' => 'https://app.hooli.com/api/webhooks/sendpost',
'delivered' => true,
'dropped' => true,
'hardBounced' => true,
'softBounced' => true,
'opened' => true,
'clicked' => true,
'unsubscribed' => true,
'spam' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Account-ApiKey: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sendpost.io/api/v1/account/webhook"
payload := strings.NewReader("{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Account-ApiKey", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sendpost.io/api/v1/account/webhook")
.header("X-Account-ApiKey", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpost.io/api/v1/account/webhook")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Account-ApiKey"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}"
response = http.request(request)
puts response.read_body{
"id": 117,
"enabled": true,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"processed": false,
"sent": false,
"dropped": true,
"smtpDropped": false,
"delivered": true,
"softBounced": true,
"hardBounced": true,
"opened": true,
"clicked": true,
"unsubscribed": true,
"spam": true,
"uniqueOpen": false,
"uniqueClick": false,
"created": 1704067200000000000
}Create Webhook
Create a new webhook to receive real-time notifications for email events. Your endpoint will receive HTTP POST requests with event data as they occur.
Endpoint Requirements:
- Must be publicly accessible HTTPS URL
- Should return 2xx status within 30 seconds
- Handle potential duplicate events (use event ID for deduplication)
- Implement retry/queue logic for reliability
Choosing Events:
- Engagement Tracking:
uniqueOpened,uniqueClickedfor metrics - Full History:
opened,clickedfor complete event logs - Delivery Monitoring:
delivered,hardBounced,softBounced - Compliance:
unsubscribed,spam
Best Practices:
- Only enable events you actually need
- Store events before processing (async processing)
- Implement idempotency using event IDs
- Set up monitoring for webhook failures
Webhook Payload Example:
{
"eventId": "evt_123",
"event": "delivered",
"messageId": "msg_456",
"recipient": "user@example.com",
"timestamp": "2024-01-15T10:30:00Z"
}
curl --request POST \
--url https://api.sendpost.io/api/v1/account/webhook \
--header 'Content-Type: application/json' \
--header 'X-Account-ApiKey: <api-key>' \
--data '
{
"enabled": true,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"delivered": true,
"dropped": true,
"hardBounced": true,
"softBounced": true,
"opened": true,
"clicked": true,
"unsubscribed": true,
"spam": true
}
'import requests
url = "https://api.sendpost.io/api/v1/account/webhook"
payload = {
"enabled": True,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"delivered": True,
"dropped": True,
"hardBounced": True,
"softBounced": True,
"opened": True,
"clicked": True,
"unsubscribed": True,
"spam": True
}
headers = {
"X-Account-ApiKey": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Account-ApiKey': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
enabled: true,
url: 'https://app.hooli.com/api/webhooks/sendpost',
delivered: true,
dropped: true,
hardBounced: true,
softBounced: true,
opened: true,
clicked: true,
unsubscribed: true,
spam: true
})
};
fetch('https://api.sendpost.io/api/v1/account/webhook', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sendpost.io/api/v1/account/webhook",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'enabled' => true,
'url' => 'https://app.hooli.com/api/webhooks/sendpost',
'delivered' => true,
'dropped' => true,
'hardBounced' => true,
'softBounced' => true,
'opened' => true,
'clicked' => true,
'unsubscribed' => true,
'spam' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Account-ApiKey: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sendpost.io/api/v1/account/webhook"
payload := strings.NewReader("{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Account-ApiKey", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sendpost.io/api/v1/account/webhook")
.header("X-Account-ApiKey", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpost.io/api/v1/account/webhook")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Account-ApiKey"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"enabled\": true,\n \"url\": \"https://app.hooli.com/api/webhooks/sendpost\",\n \"delivered\": true,\n \"dropped\": true,\n \"hardBounced\": true,\n \"softBounced\": true,\n \"opened\": true,\n \"clicked\": true,\n \"unsubscribed\": true,\n \"spam\": true\n}"
response = http.request(request)
puts response.read_body{
"id": 117,
"enabled": true,
"url": "https://app.hooli.com/api/webhooks/sendpost",
"processed": false,
"sent": false,
"dropped": true,
"smtpDropped": false,
"delivered": true,
"softBounced": true,
"hardBounced": true,
"opened": true,
"clicked": true,
"unsubscribed": true,
"spam": true,
"uniqueOpen": false,
"uniqueClick": false,
"created": 1704067200000000000
}Authorizations
This api key can be used for all account level operations
Body
Request body for creating a new webhook endpoint.
Event Selection Tips:
- For basic tracking: Enable
delivered,opened,clicked - For suppression sync: Enable
hardBounced,unsubscribed,spam - For debugging: Enable
dropped,softBounced - Use
uniqueOpen/uniqueClickinstead ofopened/clickedto reduce volume
HTTPS URL endpoint to receive webhook POST requests. Must:
- Use HTTPS (HTTP not allowed for security)
- Be publicly accessible
- Return 2xx status within 10 seconds
- Handle duplicate deliveries (use eventId for idempotency)
"https://app.hooli.com/api/webhooks/sendpost"
Whether the webhook is active immediately after creation. Set to false to configure and test before activating.
true
Fire when email is accepted by SendPost API
false
Fire when email is sent to recipient's mail server
false
Fire when email is accepted by recipient's mail server
true
Fire when email is not sent (suppression, invalid, etc.)
true
Fire when email is rejected at SMTP level
false
Fire on temporary delivery failure (will retry)
true
Fire on permanent delivery failure
true
Fire when email is opened. Fires on EVERY open.
Consider using uniqueOpen instead to reduce volume.
true
Fire when a link is clicked. Fires on EVERY click.
Consider using uniqueClick instead to reduce volume.
true
Fire when recipient clicks unsubscribe link
true
Fire when recipient marks email as spam
true
Fire only on FIRST open of each email (unique opens).
More efficient than opened if you only need engagement metrics.
false
Fire only on FIRST click of each email (unique clicks).
More efficient than clicked if you only need engagement metrics.
false
Response
Webhook created successfully.
Webhook configuration for receiving real-time email event notifications. When events occur (delivery, open, click, bounce, etc.), SendPost sends HTTP POST requests to your configured webhook URL.
Best Practices:
- Use HTTPS endpoints for security
- Respond with 2xx status within 10 seconds
- Implement idempotency using eventId
- Verify webhook signatures (see documentation)
Unique identifier for the webhook configuration
117
Whether the webhook is active. When false, no events will be sent to this webhook. Useful for temporarily pausing notifications during maintenance.
true
HTTPS endpoint URL to receive webhook POST requests. Must be publicly accessible and return 2xx status code.
"https://app.hooli.com/api/webhooks/sendpost"
Trigger webhook when an email is accepted for processing. Fires immediately when API call is successful.
true
Trigger webhook when an email is sent to the recipient's mail server. Indicates the email left SendPost's infrastructure.
true
Trigger webhook when an email is dropped before sending. Common reasons: suppressed address, invalid email, unverified domain.
true
Trigger webhook when an email is dropped at SMTP level. Usually due to policy rejection by receiving server.
false
Trigger webhook when an email is successfully delivered. Note: "Delivered" means accepted by mail server, not inbox placement.
true
Trigger webhook on temporary delivery failure (soft bounce). SendPost will retry delivery automatically.
true
Trigger webhook on permanent delivery failure (hard bounce). The recipient is automatically added to suppression list.
true
Trigger webhook when recipient opens the email. Fires on every open (can fire multiple times per email).
true
Trigger webhook when recipient clicks a link. Fires on every click (can fire multiple times per email).
true
Trigger webhook when recipient clicks the unsubscribe link. The recipient is automatically added to suppression list.
true
Trigger webhook when recipient marks email as spam. The recipient is automatically added to suppression list. Monitor this closely - high spam rates damage sender reputation.
true
Trigger webhook only on the first open of an email (unique opens). Use this instead of 'opened' if you only care about unique engagement.
false
Trigger webhook only on the first click of an email (unique clicks). Use this instead of 'clicked' if you only care about unique engagement.
false
Health status of the webhook (read-only):
active- delivering normallydegraded- recent delivery failuresdisabled- auto-disabled after repeated consecutive failures
active, degraded, disabled "active"
UNIX epoch timestamp in nanoseconds when the webhook was auto-disabled (0 if never). Read-only.
0
Human-readable reason the webhook was auto-disabled (empty if active). Read-only.
""
UNIX epoch timestamp in nanoseconds when the webhook was created
1704067200000000000
Was this page helpful?