mcpField
W
webflow-webhooks

webflow-webhooks

github.com/hookdeckDevelopment95190 installsUpdated today
Repository

About webflow-webhooks

webflow-webhooks is a skill that guides implementation of Webflow webhook receivers, signature checks, and event processing. It is for developers handling Webflow form, ecommerce, publishing, and CMS events, with notes on signature prerequisites and local testing.

Key features

  1. 01Webhook signature verification guidance
  2. 02Replay-window timestamp validation
  3. 03Common Webflow event references
  4. 04Raw-body handling example
  5. 05Local testing with Hookdeck CLI

Use cases

  1. 01Verifying signed Webflow webhook requests
  2. 02Processing form submissions and orders
  3. 03Updating systems when CMS items change
  4. 04Testing webhook delivery during local development

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hookdeck/webhook-skills --skill webflow-webhooks

After installing, type/webflow-webhooksin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

examples/express/
.env.example
package.json
README.md
examples/express/src/
index.js
examples/express/test/
webhook.test.js
examples/fastapi/
.env.example
main.py
README.md
requirements.txt
test_webhook.py
examples/nextjs/
.env.example
package.json
README.md
vitest.config.ts
examples/nextjs/app/webhooks/webflow/
route.ts
examples/nextjs/test/
webhook.test.ts
references/
overview.md
setup.md
verification.md

Details

From the project README

Webflow Webhooks

When to Use This Skill

  • How do I receive Webflow webhooks?
  • How do I verify Webflow webhook signatures?
  • How do I handle form_submission events from Webflow?
  • How do I process Webflow ecommerce order events?
  • Why is my Webflow webhook signature verification failing?
  • Setting up Webflow CMS collection item webhooks

Essential Code

Signature Verification (Manual)
const crypto = require('crypto');

function verifyWebflowSignature(rawBody, signature, timestamp, secret) {
  // Check timestamp to prevent replay attacks (5 minute window - 300000 milliseconds)
  const currentTime = Date.now();
  if (Math.abs(currentTime - parseInt(timestamp)) > 300000) {
    return false;
  }

  // Generate HMAC signature
  const signedContent = `${timestamp}:${rawBody}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedContent)
    .digest('hex');

  // Timing-safe comparison
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  } catch {
    return false; // Different lengths = invalid
  }
}
Processing Events
app.post('/webhooks/webflow', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webflow-signature'];
  const timestamp = req.headers['x-webflow-timestamp'];

  if (!signature || !timestamp) {
    return res.status(400).send('Missing required headers');
  }

  // Verify signature (use OAuth client secret or webhook-specific secret)
  const isValid = verifyWebflowSignature(
    req.body.toString(),
    signature,
    timestamp,
    process.env.WEBFLOW_WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(400).send('Invalid signature');
  }

  // Parse the verified payload
  const event = JSON.parse(req.body);

  // Handle different event types
  switch (event.triggerType) {
    case 'form_submission':
      console.log('New form submission:', event.payload.data);
      break;
    case 'ecomm_new_order':
      console.log('New order:', event.payload);
      break;
    case 'collection_item_created':
      console.log('New CMS item:', event.payload);
      break;
    // Add more event handlers as needed
  }

  // Always return 200 to acknowledge receipt
  res.status(200).send('OK');
});

Common Event Types

EventTriggered WhenUse Case
form_submissionForm submitted on siteContact forms, lead capture
site_publishSite is publishedClear caches, trigger builds
ecomm_new_orderNew ecommerce orderOrder processing, inventory
ecomm_order_changedOrder status changesUpdate fulfillment systems
collection_item_createdCMS item createdContent syndication
collection_item_changedCMS item updatedUpdate external systems
collection_item_deletedCMS item deletedRemove from external systems
collection_item_publishedCMS item publishedInvalidate caches, publish downstream

Webflow documents 13 event types on All Events; its official webflow-api SDK TriggerType enum carries those plus collection_item_published. The user_account_* events are deprecated — see references/overview.md.

Environment Variables

# For webhooks created via OAuth App
WEBFLOW_WEBHOOK_SECRET=your_oauth_client_secret

# For webhooks created via API (after April 2025)
WEBFLOW_WEBHOOK_SECRET=whsec_xxxxx  # Returned when creating webhook

Local Development

For local webhook testing, install Hookdeck CLI:

Then start the tunnel:

npx hookdeck-cli listen 3000 webflow --path /webhooks/webflow

No account required. Provides local tunnel + web UI for inspecting requests.

Resources

Important Notes

  • Webhooks created through the Webflow dashboard do NOT include signature headers
  • Only webhooks created via OAuth apps or API include x-webflow-signature and x-webflow-timestamp
  • Always use raw body for signature verification, not parsed JSON
  • Timestamp validation (5 minute window - 300000 milliseconds) is critical to prevent replay attacks
  • Return 200 status to acknowledge receipt; other statuses trigger retries (up to 3 times)

Recommended: webhook-handler-patterns

This skill pairs well with webhook-handler-patterns for production-ready implementations:

Related Skills

Sources:

Comments

Markdown supported