Skip to content

🔔 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

EventTriggerPayload chính
lead.createdLead mới được tạo (từ Admin, Public API, hoặc Agent)lead_id, customer_id, phone, name, source
lead.updatedLead được cập nhật status/prioritylead_id, changes, old_status, agent
booking.createdBooking mớibooking_id, customer_id, service, date
booking.updatedBooking cập nhật statusbooking_id, status, old_status
call.completedCuộc gọi được logcall_id, lead_id, booking_id, outcome, agent
review.createdĐánh giá mớireview_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:

HeaderMô tả
Content-Typeapplication/json
X-Webhook-EventTên event (ví dụ lead.created)
X-Webhook-Signaturesha256=<hmac_hex> — dùng để verify payload
X-Webhook-AttemptSố lần thử (1, 2, hoặc 3)
User-AgentSaleHay-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/webhooks

Response 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/webhooks

Request Body:

json
{
  "url": "https://example.com/webhook",
  "events": ["lead.created", "lead.updated", "call.completed"],
  "secret": "optional_custom_secret"
}
FieldTypeBắt buộcMô tả
urlstringURL nhận webhook (HTTPS khuyến nghị)
eventsstring[]Danh sách events (default: ["lead.created"])
secretstringSecret để 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/:id

Response 200:

json
{ "ok": true }

🔒 Internal Documentation — Dev Team Only