webflow-webhooks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWebflow Webhooks
Webflow Webhook
Receive, verify, and process Webflow webhook events for form submissions, CMS changes, ecommerce orders, site publishing, and more.
接收、验证并处理Webflow webhook事件,涵盖表单提交、CMS变更、电商订单、站点发布等场景。
Quick Start Workflow
快速开始流程
Prerequisite: You need a Webflow account with an active site. For signature verification, create webhooks via the API (not the dashboard) — see Setup.
- Create webhook: Register a webhook via the Webflow API for your desired event type
- Receive events: Set up an endpoint that accepts POST requests with raw body parsing
- Verify signatures: Validate and
x-webflow-signatureheadersx-webflow-timestamp - Process events: Route events by and handle each accordingly
triggerType - Acknowledge: Return to confirm receipt (other statuses trigger retries)
200
前提条件:你需要一个带有活跃站点的Webflow账户。若要进行签名验证,请通过API(而非仪表盘)创建webhook——详见设置。
- 创建webhook:通过Webflow API为你需要的事件类型注册webhook
- 接收事件:设置一个支持原始请求体解析的POST请求端点
- 验证签名:校验和
x-webflow-signature请求头x-webflow-timestamp - 处理事件:根据路由事件并分别处理
triggerType - 确认接收:返回状态码确认已接收(其他状态码会触发重试)
200
Signature Verification
签名验证
javascript
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
}
}javascript
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
事件处理
javascript
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');
}
const isValid = verifyWebflowSignature(
req.body.toString(),
signature,
timestamp,
process.env.WEBFLOW_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(req.body);
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;
case 'collection_item_published':
console.log('Published CMS items:', event.payload.items);
break;
}
res.status(200).send('OK');
});javascript
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');
}
const isValid = verifyWebflowSignature(
req.body.toString(),
signature,
timestamp,
process.env.WEBFLOW_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(req.body);
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;
case 'collection_item_published':
console.log('Published CMS items:', event.payload.items);
break;
}
res.status(200).send('OK');
});Event Types
事件类型
Webflow supports 14 webhook event types across 6 categories: Forms, Site, Pages, Ecommerce, CMS, and Comments. See references/event-types.md for the complete reference with all payload schemas and examples.
| Category | Events | Required Scope |
|---|---|---|
| Forms | | |
| Site | | |
| Pages | | |
| Ecommerce | | |
| CMS | | |
| Comments | | |
Webflow支持6大分类下的14种webhook事件类型:表单、站点、页面、电商、CMS和评论。完整的参考文档包含所有负载 schema 和示例,请查看**references/event-types.md**。
| 分类 | 事件 | 所需权限范围 |
|---|---|---|
| 表单 | | |
| 站点 | | |
| 页面 | | |
| 电商 | | |
| CMS | | |
| 评论 | | |
Environment Variables
环境变量
bash
undefinedbash
undefinedFor webhooks created via OAuth App
For webhooks created via OAuth App
WEBFLOW_WEBHOOK_SECRET=your_oauth_client_secret
WEBFLOW_WEBHOOK_SECRET=your_oauth_client_secret
For webhooks created via API (after April 2025)
For webhooks created via API (after April 2025)
WEBFLOW_WEBHOOK_SECRET=whsec_xxxxx # Returned when creating webhook
undefinedWEBFLOW_WEBHOOK_SECRET=whsec_xxxxx # Returned when creating webhook
undefinedBest Practices
最佳实践
- Always verify signatures: Use HMAC-SHA256 verification for webhooks created via OAuth or API — see Verification
- Use raw body for verification: Never verify against parsed JSON; configure your framework accordingly
- Validate timestamps: Enforce a 5-minute window (300000ms) to prevent replay attacks
- Return 200 quickly: Acknowledge receipt immediately; process events asynchronously for heavy workloads
- Handle retries gracefully: Webflow retries up to 3 times on failure (10-minute intervals) — implement idempotency
- Use HTTPS in production: Webhook endpoints must use HTTPS for security
- 始终验证签名:对通过OAuth或API创建的webhook使用HMAC-SHA256验证——详见验证
- 使用原始请求体进行验证:绝不要对解析后的JSON进行验证;请相应配置你的框架
- 校验时间戳:强制执行5分钟(300000毫秒)的时间窗口以防止重放攻击
- 快速返回200状态码:立即确认接收;对于繁重的工作负载,异步处理事件
- 优雅处理重试:Webflow在请求失败时最多重试3次(间隔10分钟)——实现幂等性
- 生产环境使用HTTPS:Webhook端点必须使用HTTPS以保障安全
Important Notes
重要说明
- Never handle secrets in plain text. API tokens, OAuth client secrets, and webhook signing secrets must always be stored in environment variables or a secrets manager. Never ask the user for tokens or secrets directly, and never hard-code them in source files.
- Webhooks created through the Webflow dashboard do NOT include signature headers
- Only webhooks created via OAuth apps or API include and
x-webflow-signaturex-webflow-timestamp - 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, 10-minute intervals)
- 绝不要明文处理密钥。API令牌、OAuth客户端密钥和webhook签名密钥必须始终存储在环境变量或密钥管理系统中。绝不要直接向用户索要令牌或密钥,也绝不要在源文件中硬编码它们。
- 通过Webflow仪表盘创建的webhook不包含签名请求头
- 只有通过OAuth应用或API创建的webhook才会包含和
x-webflow-signaturex-webflow-timestamp - 时间戳验证(5分钟窗口 - 300000毫秒)对于防止重放攻击至关重要
- 返回200状态码确认接收;其他状态码会触发重试(最多3次,间隔10分钟)
Reference Documentation
参考文档
Each reference file includes YAML frontmatter with , , and for searchability. Use the search script available in to quickly find relevant references by tag or keyword.
namedescriptiontagsscripts/search_references.py- references/event-types.md: Complete reference for all 14 event types with scopes, payload schemas, and examples
- references/webhook-api.md: REST API v2 endpoints for creating, listing, getting, and deleting webhooks
- references/overview.md: Webhook concepts, delivery behavior, limits, and security considerations
- references/setup.md: Dashboard and API configuration, OAuth, scopes, environment setup
- references/verification.md: HMAC-SHA256 signature verification, common gotchas, debugging
- references/faq.md: FAQ and troubleshooting for delivery issues, signature failures, and API errors
每个参考文件都包含YAML前置元数据,包括、和,以便于搜索。使用中的搜索脚本,可通过标签或关键词快速找到相关参考内容。
namedescriptiontagsscripts/search_references.py- references/event-types.md:所有14种事件类型的完整参考,包含权限范围、负载schema和示例
- references/webhook-api.md:用于创建、列出、获取和删除webhook的REST API v2端点
- references/overview.md:Webhook概念、交付行为、限制和安全注意事项
- references/setup.md:仪表盘和API配置、OAuth、权限范围、环境设置
- references/verification.md:HMAC-SHA256签名验证、常见问题、调试方法
- references/faq.md:交付问题、签名失败和API错误的常见问题与故障排除
Searching References
搜索参考文档
bash
undefinedbash
undefinedList all references with metadata
List all references with metadata
python scripts/search_references.py --list
python scripts/search_references.py --list
Search by tag (exact match)
Search by tag (exact match)
python scripts/search_references.py --tag <tag>
python scripts/search_references.py --tag <tag>
Search by keyword (across name, description, tags, and content)
Search by keyword (across name, description, tags, and content)
python scripts/search_references.py --search <query>
undefinedpython scripts/search_references.py --search <query>
undefinedScripts
脚本
- : Search reference files by tag, keyword, or list all with metadata
scripts/search_references.py
- :通过标签、关键词搜索参考文件,或列出所有带元数据的参考文件
scripts/search_references.py