What Are Webhooks?
Webhooks are a powerful tool for developers that allow you to send real-time data from one application to another whenever a specific event occurs. In RankPill, you can use a webhook to automatically send all the data for a newly published article to a URL of your choice.
This enables you to create custom integrations with any service that can receive an HTTP POST request, such as:
- A Next.js, Hugo, or Jekyll site
- A custom-built CMS
- A Zapier or Make.com automation workflow
- A serverless function (e.g., AWS Lambda, Vercel Functions)
- A Discord or Slack notification channel
How to Set Up a Webhook
-
Navigate to Webhook Settings: Go to
Settings
>Integrations
in your RankPill dashboard and click on the "Webhooks" integration. -
Enter Your Webhook URL: In the input field, paste the public URL of the endpoint you've created to receive the webhook data. This URL must be able to accept a
POST
request with a JSON payload. -
Choose Authentication Type: Select whether you want signature-based authentication (recommended) or simple Bearer token authentication.
-
Connect and Save: Click "Connect". RankPill will securely store your URL and generate a unique Secret Key.
-
Copy Your Secret Key: The secret key is essential for verifying that the incoming requests are genuinely from RankPill. Copy this key and store it securely in your application's environment variables (e.g., as
RANKPILL_WEBHOOK_SECRET
).
Authentication and Security
To ensure the security of your endpoint, RankPill includes authentication information in every webhook request. We support multiple authentication methods for maximum compatibility:
Authentication Methods
1. Signature-based Authentication (Default & Recommended)
X-RankPill-Signature
header: Contains a HMAC SHA-256 signatureAuthorization
header: Contains the same signature in formatsha256=<signature>
- Provides cryptographic verification that the request hasn't been tampered with
2. Bearer Token Authentication (Configurable)
Authorization
header: ContainsBearer <your-secret-key>
- Simpler to implement but less secure than signature verification
- Choose this if your endpoint specifically requires Bearer token format
The signature is a HMAC SHA-256 hash, created using your Secret Key and the raw JSON payload of the request.
Headers Sent by RankPill
Every webhook request from RankPill includes these headers:
Content-Type: application/json
X-RankPill-Signature: <hmac-sha256-signature>
- HMAC signature for verificationAuthorization: sha256=<hmac-sha256-signature>
- Same signature in standard Authorization header format
Note: For maximum compatibility, RankPill sends the signature in both the custom X-RankPill-Signature
header and the standard Authorization
header. You can verify using either one.
Verification Examples
Here's how to verify the signature in a Next.js API route:
Method 1: Signature Verification (Most Common)
// /pages/api/rankpill-webhook.js
import crypto from 'crypto';
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
// Get the raw request body
const rawBody = await getRawBody(req);
const secret = process.env.RANKPILL_WEBHOOK_SECRET;
// Verify signature from either header
const xSignature = req.headers['x-rankpill-signature'];
const authHeader = req.headers['authorization'];
let isValid = false;
// Method 1: Check X-RankPill-Signature header
if (xSignature) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
isValid = xSignature === expectedSignature;
}
// Method 2: Check Authorization header with signature
if (!isValid && authHeader && authHeader.startsWith('sha256=')) {
const signature = authHeader.replace('sha256=', '');
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
isValid = signature === expectedSignature;
}
// Method 3: Check Bearer token (if you're using bearer auth)
if (!isValid && authHeader && authHeader.startsWith('Bearer ')) {
const token = authHeader.replace('Bearer ', '');
isValid = token === secret;
}
if (!isValid) {
return res.status(401).json({ message: 'Invalid authentication.' });
}
// Process the article data
const article = JSON.parse(rawBody);
console.log('Successfully received article:', article.title);
// TODO: Add your logic here to save the article, create a file, etc.
res.status(200).json({ message: 'Webhook received successfully!' });
}
// Helper to get the raw body in Next.js
function getRawBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on('data', chunk => chunks.push(chunk));
req.on('end', () => resolve(Buffer.concat(chunks)));
req.on('error', reject);
});
}
Method 2: Simple Bearer Token Verification
If you prefer simple bearer token authentication, you can use this approach:
// /pages/api/rankpill-webhook.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
// Verify bearer token
const authHeader = req.headers['authorization'];
const expectedToken = `Bearer ${process.env.RANKPILL_WEBHOOK_SECRET}`;
if (!authHeader || authHeader !== expectedToken) {
return res.status(401).json({ message: 'Missing or invalid authorization header' });
}
// Process the article data
const article = req.body;
console.log('Successfully received article:', article.title);
// TODO: Add your logic here to save the article, create a file, etc.
res.status(200).json({ message: 'Webhook received successfully!' });
}
Payload Data Structure
The webhook will send a cleaned article object containing only the public content data as a JSON payload. Here is an example of the data you can expect to receive:
{
"title": "How to Build Backlinks for Better SEO",
"content_html": "<h1>How to Build Backlinks for Better SEO</h1><p>Building high-quality backlinks is one of the most important...</p>",
"content_markdown": "# How to Build Backlinks for Better SEO\n\nBuilding high-quality backlinks is one of the most important...",
"slug": "how-to-build-backlinks-for-better-seo",
"meta_description": "Learn proven strategies to build high-quality backlinks that will improve your website's search engine rankings and drive more organic traffic.",
"status": "published",
"featured_image": "https://images.unsplash.com/photo-1516321318423-f06f85e504b3",
"published_url": "https://yourblog.com/blog/how-to-build-backlinks-for-better-seo",
"scheduled_date": null,
"published_at": "2024-03-15T10:30:00Z"
}
By using this data, you can dynamically create pages, update your content, or trigger any other custom workflow you can imagine.
Troubleshooting
Common Issues
401 Unauthorized: "Missing authorization header"
- Cause: Your endpoint expects an
Authorization
header in Bearer format - Solution: In your RankPill webhook settings, change the Authentication Type to "Bearer Token" instead of "Signature"
401 Unauthorized: "Auth header is not 'Bearer token'"
- Cause: Your endpoint specifically requires Bearer token format but RankPill is sending signature format
- Solution: In your RankPill webhook settings, change the Authentication Type to "Bearer Token"
401 Unauthorized: "Invalid signature"
- Cause: Signature verification is failing
- Solutions:
- Ensure you're using the raw request body for signature calculation (not parsed JSON)
- Verify your secret key matches exactly what's shown in RankPill settings
- Check that your HMAC implementation uses SHA-256
- Make sure there are no extra characters or encoding issues with the secret
Webhook not triggering
- Cause: Articles may not be publishing due to integration requirements
- Solution: Ensure your business has a valid publishing integration configured (Webflow, WordPress, Shopify, Wix, or Webhooks)
Testing Your Webhook
You can test your webhook endpoint using curl:
# Test with signature verification
curl -X POST https://your-endpoint.com/webhook \
-H "Content-Type: application/json" \
-H "X-RankPill-Signature: your-test-signature" \
-H "Authorization: sha256=your-test-signature" \
-d '{"title":"Test Article","content_html":"<p>Test content</p>"}'