Webhooks send your server or automation tool a message each time a post is published on a website. Use them with the WordPress plugin, Zapier, Make, your own app, or any service that accepts an HTTPS URL.
Set up a webhook
- Sign in to the dashboard.
- Open Websites and select your site.
- Open Integrations and add a Webhook.
- Enter your URL — it must start with
https://. - Optionally add a Secret if your endpoint should verify that requests come from Auto Blogger.
You can add more than one webhook per website. Each URL receives the same notification when a post goes live.
Request details
Each delivery is an HTTPS POST with a JSON body.
| Header | Value |
|---|---|
Content-Type |
application/json |
Accept |
application/json |
Idempotency-Key |
Unique per publish (e.g. 42-1716206400) — use this to ignore duplicate deliveries after a retry |
X-Webhook-Signature |
Only when you set a Secret — see Verify the signature |
Your endpoint should respond with any 2xx status within about 30 seconds. Queue heavy work on your side after you respond.
Example payload
When a post goes live, the body looks like this (pretty-printed for readability):
{
"event": "post.published",
"website": {
"uuid": "550e8400-e29b-41d4-a716-446655440000"
},
"post": {
"id": 42,
"slug": "how-we-grew-organic-traffic",
"title": "How we grew organic traffic",
"meta_title": "How we grew organic traffic | Acme Blog",
"meta_description": "A practical guide to improving search visibility without sacrificing quality.",
"published_at": "2026-05-20T14:30:00+00:00",
"url": "https://www.example.com/how-we-grew-organic-traffic",
"html_excerpt": "Search visibility comes from consistent publishing and clear structure…",
"html": "<p>Search visibility comes from consistent publishing…</p>"
}
}
When the post has a cover image, an images object is included:
{
"event": "post.published",
"website": {
"uuid": "550e8400-e29b-41d4-a716-446655440000"
},
"post": {
"id": 42,
"slug": "how-we-grew-organic-traffic",
"title": "How we grew organic traffic",
"meta_title": "How we grew organic traffic | Acme Blog",
"meta_description": "A practical guide to improving search visibility without sacrificing quality.",
"published_at": "2026-05-20T14:30:00+00:00",
"url": "https://www.example.com/how-we-grew-organic-traffic",
"html_excerpt": "Search visibility comes from consistent publishing and clear structure…",
"html": "<p>Search visibility comes from consistent publishing…</p>",
"images": {
"optimizedImage": "https://cdn.example.com/media/42/conversions/cover.jpg",
"alt": "Chart showing traffic growth",
"title": "Organic traffic growth",
"banner_facebook": "https://cdn.example.com/media/42/conversions/og.jpg",
"banner_pressebox_shortstory": "https://cdn.example.com/media/42/conversions/og.jpg",
"banner_own_blog": "https://cdn.example.com/media/42/conversions/og.jpg"
}
}
}
Field reference
| Field | Description |
|---|---|
event |
Always post.published for publish notifications |
website.uuid |
Your website’s identifier (same as in feed URLs) |
post.id |
Internal post ID (use with Idempotency-Key for deduplication) |
post.slug |
URL slug on your site |
post.title |
Post headline |
post.meta_title |
SEO title (falls back to the post title when not set) |
post.meta_description |
SEO description |
post.published_at |
ISO 8601 timestamp when the post went live |
post.url |
Full public URL on your website |
post.html_excerpt |
Plain-text summary (up to 500 characters) |
post.html |
Full article HTML |
post.images |
Present only when a cover image exists — URLs for social and embed use |
Verify the signature
If you configured a Secret, every request includes:
X-Webhook-Signature: sha256=<hex>
The value is sha256= followed by the HMAC-SHA256 of the raw request body (the exact JSON bytes), using your secret as the key.
Important:
- Verify against the raw body before your framework re-encodes JSON.
- Compare signatures in a constant-time way to reduce timing attacks.
PHP
$secret = 'your-webhook-secret';
$rawBody = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (! hash_equals($expected, $header)) {
http_response_code(401);
exit('Invalid signature');
}
$payload = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
Node.js
const crypto = require('crypto');
const secret = 'your-webhook-secret';
const rawBody = req.body; // use raw body middleware, not parsed JSON
const header = req.headers['x-webhook-signature'] ?? '';
const expected =
'sha256=' +
crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
const valid =
header.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
if (!valid) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(rawBody);
Python
import hmac
import hashlib
secret = b"your-webhook-secret"
raw_body = request.get_data() # bytes, before JSON parsing
header = request.headers.get("X-Webhook-Signature", "")
expected = "sha256=" + hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, header):
return "Invalid signature", 401
payload = json.loads(raw_body)
Test your endpoint
You can simulate a delivery locally (replace URL and secret):
BODY='{"event":"post.published","website":{"uuid":"550e8400-e29b-41d4-a716-446655440000"},"post":{"id":42,"slug":"test","title":"Test","meta_title":"Test","meta_description":"","published_at":"2026-05-20T12:00:00+00:00","url":"https://www.example.com/test","html_excerpt":"Hi","html":"<p>Hi</p>"}}'
SECRET='your-webhook-secret'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')"
curl -sS -X POST 'https://your-server.example/webhooks/auto-blogger' \
-H 'Content-Type: application/json' \
-H "X-Webhook-Signature: $SIG" \
-H 'Idempotency-Key: 42-1716206400' \
-d "$BODY"
Retries and duplicates
- Failed deliveries are retried a few times (after about 10 minutes, then about 1 hour).
- The same publish may arrive more than once — use
Idempotency-Key(orpost.id+published_at) to process each publish only once. - Check delivery status on the post in your dashboard, or use Resend webhooks if you need another attempt.
Related guides
- Content feeds — pull posts on a schedule instead
- Troubleshooting — webhooks not arriving or signature errors