Skip to main content

Overview

ButterCMS webhooks enable real-time notifications when content changes occur in your account. When you publish a page, update a collection item, or create a blog post, ButterCMS sends an HTTP POST request to your configured endpoint with details about the change.

Key use cases

  • Cache Invalidation: Clear your CDN or application cache when content updates
  • Static Site Rebuilds: Trigger a rebuild of your static site (Next.js, Gatsby, etc.)
  • Multi-channel Publishing: Sync content to social media, email lists, or mobile apps
  • Automated Workflows: Send Slack notifications, update analytics, or trigger deployments

How webhooks work

Configuring webhooks

Webhooks are configured through the ButterCMS dashboard.

Step 1: access webhook settings

  1. Log in to your ButterCMS Dashboard
  2. Navigate to Settings > Webhooks
  3. Click Add Webhook

Step 2: configure endpoint

FieldDescription
URLYour webhook endpoint URL (must be HTTPS)
EventsSelect which content events trigger this webhook
HeadersOptional custom headers for authentication
Webhooks require account-level enablement, and availability varies by plan. Contact support to enable webhooks for your account.

Step 3: select events

Choose which events should trigger webhooks: Page Events:
  • page.published - Page is published or republished
  • page.draft - Page is saved as draft
  • page.unpublished - Page is unpublished
  • page.delete - Page is deleted
  • page.* - All page events
Blog Post Events:
  • post.published - Post is published
  • post.draft - Post is saved as draft
  • post.delete - Post is deleted or unpublished
  • post.* - All post events
Collection Item Events:
  • collectionitem.published - Item is published
  • collectionitem.draft - Item is saved as draft
  • collectionitem.unpublished - Item is unpublished
  • collectionitem.delete - Item is deleted
  • collectionitem.* - All collection events

Delivery guarantees

Webhooks are delivered asynchronously via a job queue. While webhook delivery is reliable under normal conditions, there is no automatic retry mechanism for failed deliveries. Implement idempotent handling in case the same event is delivered multiple times.

Response handling

ScenarioButterCMS Behavior
2xx ResponseWebhook delivered successfully
4xx ResponseWebhook failed (client error)
5xx ResponseWebhook failed (server error)
Timeout (5s)Webhook failed (timeout)
Webhooks are delivered on a best-effort basis without automatic retries. Implement appropriate logging and error handling on your endpoint to detect missed webhooks.

Timeout requirement

Your webhook endpoint must respond within 5 seconds. If your processing takes longer, return a 200 immediately and process asynchronously.

Security best practices

Custom authentication headers

Add authentication headers to verify webhook requests originate from ButterCMS:
X-Webhook-Secret: your-secret-key
Authorization: Bearer your-token

Endpoint implementation

const express = require('express');
const app = express();

// Verify webhook authenticity
function verifyWebhook(req) {
  const secret = req.headers['x-webhook-secret'];
  return secret === process.env.WEBHOOK_SECRET;
}

app.post('/webhooks/buttercms', express.json(), (req, res) => {
  // Verify authentication
  if (!verifyWebhook(req)) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  // Process webhook (respond quickly, process async if needed)
  const { data, webhook } = req.body;
  console.log(`Received ${webhook.event} for ${data.id}`);

  // Queue for async processing if needed
  processWebhookAsync(req.body);

  // Return 200 immediately
  res.status(200).json({ received: true });
});

Additional security measures

  • HTTPS Only: Always use HTTPS endpoints for encrypted transmission
  • IP Allowlisting: Restrict access to ButterCMS IP ranges if possible
  • Validate Payloads: Check that payload structure matches expected schema
  • Idempotency: Handle duplicate deliveries using event timestamps or content IDs

Handling duplicates

Since webhooks may be delivered multiple times, implement idempotent processing:
const processedEvents = new Set();

async function handleWebhook(payload) {
  const eventKey = `${payload.webhook.event}-${payload.data.id}-${payload.data.updated}`;

  if (processedEvents.has(eventKey)) {
    console.log('Duplicate event, skipping');
    return;
  }

  processedEvents.add(eventKey);

  // Process the webhook
  await processEvent(payload);

  // Clean up old events periodically
  // (in production, use Redis or database with TTL)
}

Testing webhooks

Local development

Use tools like ngrok or localtunnel to expose your local server:
# Expose local port 3000
ngrok http 3000

# Use the generated URL in ButterCMS webhook settings
# https://abc123.ngrok.io/webhooks/buttercms

Webhook debugging

Log incoming webhooks for debugging:
app.post('/webhooks/buttercms', express.json(), (req, res) => {
  // Log full payload for debugging
  console.log('Webhook received:', JSON.stringify(req.body, null, 2));
  console.log('Headers:', req.headers);

  res.status(200).json({ received: true });
});

Next steps

Webhook Events

Event types and payloads

Cache Invalidation

Use webhooks for caching

Real-Time Sync

Real-time content sync

Monitoring

Monitoring and debugging