Webhook (JSON)
Một quy tắc Webhook POST mọi phản hồi khớp dưới dạng JSON tới một URL bạn cung cấp. Dùng nó để đưa dữ liệu vào CRM, công cụ bảng tính, máy chủ của riêng bạn, hoặc một nền tảng tự động hóa như Zapier, Make hay n8n.
Tạo quy tắc webhook
- Nhấp + Quy tắc mới và chọn Webhook
- Khi nào: giữ Mọi phản hồi, hoặc chọn Chỉ sau khi được phê duyệt / Khi bị từ chối và đặt người phê duyệt. Thêm điều kiện Chỉ khi để chỉ gửi những phản hồi khớp
- Đến: dán URL điểm cuối của bạn (chỉ HTTPS). Không có bước Nội dung: quy tắc gửi payload JSON cố định. Xem dữ liệu gửi đi bên dưới URL hiển thị payload với các câu hỏi trong biểu mẫu của bạn, sẵn sàng để sao chép
- Nhấp Tạo quy tắc, rồi sao chép khóa ký chỉ hiển thị một lần (xem bên dưới)

Gửi thử gửi một payload mẫu có chữ ký tới điểm cuối và hiển thị mã trạng thái HTTP nó trả về. URL đã lưu được lưu trữ mã hóa và hiển thị che bớt; nhấp Thay thế để dán URL mới.
Payload
Mỗi yêu cầu là POST, Content-Type: application/json, với nội dung sau:
{
"version": 1,
"event": "submitted",
"form": { "id": "1AbC...", "name": "Workshop sign-up" },
"response": {
"id": "a3f1...",
"submittedAt": "2026-01-31T09:30:00.000Z",
"respondentEmail": "respondent@example.com",
"answers": [
{ "questionId": "q1", "title": "Your name", "value": "Ada Lovelace" },
{ "questionId": "q3", "title": "Department", "value": "Ops" }
]
},
"rule": { "id": "rule id", "name": "Zapier: new lead" }
}
eventlà một trongsubmitted,approved,rejected; nó cũng đi kèm trong headerX-Skyfield-Eventresponse.respondentEmaillànulltrừ khi biểu mẫu thu thập địa chỉ emailanswers[].valueluôn là chuỗi; câu trả lời hộp kiểm được nối bằng,rule.idvàrule.namexác định quy tắc đã chạy;namelànullkhi quy tắc không có tên- Với
approvedvàrejected, có thêmapproval: { "decision": "approved", "decidedBy": "Dana" }.decidedBylà tên người phê duyệt nhập trên trang xác nhận, nếu không có thì là email của người phê duyệt, hoặcnull
version giữ ở 1 chừng nào cấu trúc trên còn ổn định. Trường mới có thể được thêm; không trường nào bị xóa hay đổi tên mà không tăng phiên bản.
Xác minh chữ ký
Mỗi yêu cầu mang header X-Skyfield-Signature: sha256=<hex>, là HMAC-SHA256 của nội dung yêu cầu thô với khóa là khóa ký của quy tắc. Hãy xác minh trước khi tin tưởng một yêu cầu.

Khóa (whsec_...) được hiển thị một lần, ngay sau lần lưu mang lại cho quy tắc URL webhook đầu tiên. Hãy sao chép lúc đó; nó không thể hiển thị lại. Thay URL sau này vẫn giữ nguyên khóa. Nếu làm mất, mở quy tắc, nhấp Khóa ký mới, rồi lưu: khóa mới hiển thị một lần và khóa cũ ngừng hoạt động ngay lập tức.
Tính HMAC trên các byte nội dung đúng như nhận được. Phân tích rồi tuần tự hóa lại JSON trước sẽ làm thay đổi khoảng trắng và phá vỡ phép so sánh.
Node.js
import { createHmac, timingSafeEqual } from 'node:crypto'
// rawBody: string or Buffer of the request body, before any JSON parsing
function verify(rawBody, header, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
const a = Buffer.from(expected)
const b = Buffer.from(header ?? '')
return a.length === b.length && timingSafeEqual(a, b)
}
// Express example: use express.raw() so req.body is the untouched bytes
app.post('/hook', express.raw({ type: 'application/json' }), (req, res) => {
if (!verify(req.body, req.get('X-Skyfield-Signature'), process.env.SKYFIELD_SECRET))
return res.status(401).end()
const payload = JSON.parse(req.body)
res.status(200).end()
})
Python
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest("sha256=" + digest, header or "")
# Flask example
@app.post("/hook")
def hook():
if not verify(request.get_data(), request.headers.get("X-Skyfield-Signature"), SECRET):
return "", 401
payload = request.get_json()
return "", 200
Phản hồi bằng bất kỳ mã trạng thái 2xx nào. Nội dung phản hồi được bỏ qua.
Zapier, Make, n8n
Cả ba đều chấp nhận webhook JSON thông thường:
- Zapier: trigger Webhooks by Zapier, sự kiện Catch Hook (hoặc Catch Raw Hook để tự xác minh chữ ký). Dán URL Zapier hiển thị vào quy tắc
- Make: thêm module Webhooks, Custom webhook, sao chép URL của nó
- n8n: thêm node Webhook, phương thức POST, và dùng production URL của nó
Gửi thử từ quy tắc, rồi ánh xạ các trường response.answers trong nền tảng. Payload mẫu dùng câu trả lời giữ chỗ nên mọi trường đều có mặt.
Phân phối và giới hạn
- Điểm cuối phải truy cập được trên internet công cộng qua HTTPS. Địa chỉ riêng và cục bộ bị từ chối khi lưu
- Chuyển hướng không được theo: hãy dùng URL cuối cùng
- Điểm cuối có 5 giây để trả lời. Hết thời gian chờ hoặc phản hồi 5xx được thử lại một lần
- Phản hồi 404 hoặc 410 nghĩa là điểm cuối không còn: quy tắc bị tạm dừng và bạn nhận một email. Dán URL mới vào quy tắc để tiếp tục
- Trang Lịch sử liệt kê mỗi lượt gửi kèm mã trạng thái HTTP mà điểm cuối của bạn trả về
- Một quy tắc webhook bị tạm dừng hoặc bị tắt không chặn các quy tắc khác trên biểu mẫu
Những điều nên biết
- Quy tắc webhook tuân theo Gửi khi, nên một điểm cuối có thể nhận một quyết định phê duyệt thay vì mọi lượt gửi. Xem Gửi khi
- Để chỉ gửi những phản hồi đã được duyệt, đặt Gửi khi của quy tắc thành Chỉ sau khi được phê duyệt và chọn người phê duyệt. Xem Phê duyệt. Khi đó payload mang
approval.decision - Đổi kênh… chuyển một quy tắc webhook sang Email hoặc một kênh chat; nhập đích đến mới tại đó. Chuyển lại sang Webhook nghĩa là phải dán lại URL
- Quy tắc webhook cần giấy phép đang hoạt động. Bản dùng thử miễn phí cũng được tính. Xem những gì cần giấy phép
