Appearance
🔔 Webhooks API Reference
Thông tin nhanh
- Mục đích: Nhận events tự động khi có thay đổi trong CRM (lead mới, booking, cuộc gọi)
- Security: HMAC-SHA256 signature trên mỗi payload
- Retry: 3 lần, exponential backoff (1s → 4s → 16s)
- Auth (manage): JWT Bearer token (Admin routes)
- Delivery log: Audit trail cho mọi webhook delivery
Xem thêm: Agent API · Agent Tokens · Architecture
Event Types
| Event | Trigger | Payload chính |
|---|---|---|
lead.created | Lead mới được tạo (từ Admin, Public API, hoặc Agent) | lead_id, customer_id, phone, name, source |
lead.updated | Lead được cập nhật status/priority | lead_id, changes, old_status, agent |
booking.created | Booking mới | booking_id, customer_id, service, date |
booking.updated | Booking cập nhật status | booking_id, status, old_status |
call.completed | Cuộc gọi được log | call_id, lead_id, booking_id, outcome, agent |
review.created | Đánh giá mới | review_id, customer_id, rating |
* | Nhận tất cả events | (tuỳ event) |
Webhook Payload Format
json
{
"event": "lead.created",
"timestamp": "2026-03-17T10:30:00.000Z",
"data": {
"lead_id": "uuid",
"customer_id": "uuid",
"phone": "0901234567",
"name": "Nguyễn Văn A",
"source": "agent"
}
}Webhook Headers
Mỗi HTTP POST tới subscriber URL sẽ có các headers:
| Header | Mô tả |
|---|---|
Content-Type | application/json |
X-Webhook-Event | Tên event (ví dụ lead.created) |
X-Webhook-Signature | sha256=<hmac_hex> — dùng để verify payload |
X-Webhook-Attempt | Số lần thử (1, 2, hoặc 3) |
User-Agent | SaleHay-CRM-Webhook/1.0 |
Xác minh Signature
Dùng secret của webhook subscription để verify HMAC-SHA256:
javascript
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expected}` === signature;
}
// Trong webhook handler:
app.post('/webhook', (req, res) => {
const payload = JSON.stringify(req.body);
const sig = req.headers['x-webhook-signature'];
if (!verifyWebhook(payload, sig, 'YOUR_WEBHOOK_SECRET')) {
return res.status(401).send('Invalid signature');
}
// Process event...
const { event, data } = req.body;
console.log(`Event: ${event}`, data);
res.status(200).send('OK');
});Retry Logic
- Attempt 1: Gửi ngay lập tức
- Attempt 2: Sau 1 giây
- Attempt 3: Sau 4 giây
- Thành công: Response status 2xx → dừng retry
- Bỏ qua: Response status 4xx (client error) → dừng retry, không thử lại
- Timeout: 8 giây per request
Management Endpoints (Admin)
Quản lý webhook subscriptions qua Admin API (JWT auth required, RBAC: settings:r/w).
Danh sách webhooks
GET /api/settings/webhooksResponse 200:
json
{
"webhooks": [
{
"id": "uuid",
"url": "https://example.com/webhook",
"events": ["lead.created", "call.completed"],
"is_active": true,
"created_at": "2026-03-15T...",
"created_by_name": "Admin",
"total_deliveries": 42,
"successful_deliveries": 40
}
]
}Tạo webhook
POST /api/settings/webhooksRequest Body:
json
{
"url": "https://example.com/webhook",
"events": ["lead.created", "lead.updated", "call.completed"],
"secret": "optional_custom_secret"
}| Field | Type | Bắt buộc | Mô tả |
|---|---|---|---|
url | string | ✅ | URL nhận webhook (HTTPS khuyến nghị) |
events | string[] | ❌ | Danh sách events (default: ["lead.created"]) |
secret | string | ❌ | Secret để ký HMAC (tự sinh nếu không truyền) |
Response 201:
json
{
"webhook": {
"id": "uuid",
"url": "https://example.com/webhook",
"events": ["lead.created", "lead.updated", "call.completed"],
"secret": "abc123...",
"created_at": "2026-03-17T..."
},
"message": "Save the secret for signature verification."
}:::caution Secret chỉ hiển thị một lần duy nhất khi tạo. Lưu lại ngay để dùng verify signature. :::
Xóa webhook
DELETE /api/settings/webhooks/:idResponse 200:
json
{ "ok": true }