Webhook Integration
Connect BuzzRank to any CMS or backend using our webhook API.
Overview
BuzzRank can publish content to any platform via webhooks. When an article is ready to publish, BuzzRank sends a POST request to your configured endpoint with all the article data.
Use Case: Custom CMS, headless CMS (Strapi, Sanity, Contentful), static site generators, or any backend that can receive HTTP requests.
Request Format
All requests are POST with JSON body:
POST https://your-endpoint.com/buzzrank-webhook
Content-Type: application/json
X-BuzzRank-Signature: <hmac-sha256-signature>
{
"action": "verify" | "create_post" | "update_post" | "schedule_post" | "upload_media" | "get_post",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": { ... }
}Signature Verification
If you configure a webhook secret, all requests are signed using HMAC-SHA256. The signature is in the X-BuzzRank-Signature header.
How to verify (Node.js example):
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your handler:
app.post('/buzzrank-webhook', (req, res) => {
const signature = req.headers['x-buzzrank-signature'];
const payload = JSON.stringify(req.body);
if (!verifySignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the webhook...
});Actions
Sent when testing the connection from BuzzRank. Return HTTP 200 to confirm the endpoint is working.
Request:
{
"action": "verify",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {}
}Response:
HTTP 200 OK
{ "success": true }Sent when publishing a new article. You must return the created post ID (and optionally the URL).
Request:
{
"action": "create_post",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {
"title": "How to Optimize Your Website for SEO",
"content": "<h2>Introduction</h2><p>SEO is important...</p>",
"slug": "how-to-optimize-website-seo",
"excerpt": "Learn the best practices for SEO optimization...",
"featuredImageUrl": "https://images.buzzrank.io/abc123.jpg",
"metaTitle": "SEO Optimization Guide | Your Site",
"metaDescription": "Complete guide to optimizing your website...",
"status": "draft" | "publish" | "scheduled",
"scheduledAt": "2026-01-15T09:00:00.000Z"
}
}Response (required):
HTTP 200 OK
{
"id": "post-123",
"url": "https://yoursite.com/blog/how-to-optimize-website-seo"
}Sent when updating an already published article. Only modified fields are included.
Request:
{
"action": "update_post",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {
"id": "post-123",
"title": "Updated Title",
"content": "<p>Updated content...</p>",
"status": "publish"
}
}Response:
HTTP 200 OK
{ "success": true }Request:
{
"action": "schedule_post",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {
"id": "post-123",
"scheduledAt": "2026-01-15T09:00:00.000Z"
}
}Response:
HTTP 200 OK
{ "success": true }Sent when BuzzRank needs to upload an image. You should download the image from the provided URL and store it in your media library.
Request:
{
"action": "upload_media",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {
"imageUrl": "https://images.buzzrank.io/generated-image-abc123.jpg"
}
}Response (required):
HTTP 200 OK
{
"id": "media-456",
"url": "https://yoursite.com/uploads/image-abc123.jpg"
}Sent to check the status of a published article.
Request:
{
"action": "get_post",
"timestamp": "2026-01-11T12:00:00.000Z",
"data": {
"id": "post-123"
}
}Response:
HTTP 200 OK
{
"id": "post-123",
"url": "https://yoursite.com/blog/how-to-optimize-website-seo",
"title": "How to Optimize Your Website for SEO",
"content": "<h2>Introduction</h2><p>...</p>",
"status": "publish",
"publishedAt": "2026-01-11T12:00:00.000Z"
}Error Handling
Return appropriate HTTP status codes for errors:
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request (invalid data) |
| 401 | Unauthorized (invalid signature) |
| 404 | Post not found (for update/get) |
| 500 | Server error |
Example Implementation (Express.js)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.BUZZRANK_WEBHOOK_SECRET;
// Verify signature middleware
function verifyBuzzRank(req, res, next) {
const signature = req.headers['x-buzzrank-signature'];
if (!WEBHOOK_SECRET || !signature) {
return next(); // Skip if no secret configured
}
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
next();
}
app.post('/buzzrank-webhook', verifyBuzzRank, async (req, res) => {
const { action, data } = req.body;
try {
switch (action) {
case 'verify':
return res.json({ success: true });
case 'create_post':
const post = await createPostInYourCMS(data);
return res.json({ id: post.id, url: post.url });
case 'update_post':
await updatePostInYourCMS(data.id, data);
return res.json({ success: true });
case 'schedule_post':
await schedulePostInYourCMS(data.id, data.scheduledAt);
return res.json({ success: true });
case 'upload_media':
const media = await uploadMediaToYourCMS(data.imageUrl);
return res.json({ id: media.id, url: media.url });
case 'get_post':
const existing = await getPostFromYourCMS(data.id);
if (!existing) return res.status(404).json({ error: 'Not found' });
return res.json(existing);
default:
return res.status(400).json({ error: 'Unknown action' });
}
} catch (error) {
console.error('Webhook error:', error);
return res.status(500).json({ error: 'Internal error' });
}
});
app.listen(3000);Testing Your Webhook
You can test your webhook endpoint using curl:
# Test verify action
curl -X POST https://your-endpoint.com/buzzrank-webhook \
-H "Content-Type: application/json" \
-d '{"action": "verify", "timestamp": "2026-01-11T12:00:00.000Z", "data": {}}'
# Test with signature (replace SECRET with your webhook secret)
PAYLOAD='{"action":"verify","timestamp":"2026-01-11T12:00:00.000Z","data":{}}'
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "YOUR_SECRET" | cut -d' ' -f2)
curl -X POST https://your-endpoint.com/buzzrank-webhook \
-H "Content-Type: application/json" \
-H "X-BuzzRank-Signature: $SIGNATURE" \
-d "$PAYLOAD"Need Help?
If you need assistance implementing your webhook integration, contact us at support@buzzrank.io