RankPill Logo

Integrations

Webhooks

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

  1. Navigate to Webhook Settings: Go to Settings > Integrations in your RankPill dashboard and click on the "Webhooks" integration.

  2. 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.

  3. Choose Authentication Type: Select whether you want signature-based authentication (recommended) or simple Bearer token authentication.

  4. Connect and Save: Click "Connect". RankPill will securely store your URL and generate a unique Secret Key.

  5. 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 signature
  • Authorization header: Contains the same signature in format sha256=<signature>
  • Provides cryptographic verification that the request hasn't been tampered with

2. Bearer Token Authentication (Configurable)

  • Authorization header: Contains Bearer <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 verification
  • Authorization: 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>"}'