Webhook: nhận sự kiện đặt phòng
Bạn vẫn đọc được đầy đủ hướng dẫn bên dưới. Khi cần bật, nhắn Zalo OA GoHost — CS sẽ giúp trong 1 ngày làm việc.
Webhook gửi POST tới URL HTTPS của bạn khi một đặt phòng của cơ sở được tạo, sửa, huỷ, nhận hoặc trả phòng
— kể cả đơn do lễ tân hay kênh OTA tạo, không chỉ đơn tạo qua API. Bạn quản lý webhook bằng chính API, theo từng cơ sở, với scope
webhooks:read / webhooks:write (key cũ chưa có hai scope này — xin GoHost thêm).
Sự kiện
Phần tiêu đề “Sự kiện”| Sự kiện | Khi nào |
|---|---|
booking.created | Đặt phòng mới |
booking.updated | Đặt phòng bị sửa (không gửi khi cùng thao tác đã có một sự kiện bên dưới) |
booking.confirmed | Đơn được xác nhận qua API (Confirm Booking); xác nhận trên GoHost đến dưới dạng booking.updated |
booking.cancelled | Đơn bị huỷ |
booking.checked_in | Khách nhận phòng |
booking.checked_out | Khách trả phòng |
webhook.ping | Gửi thử bằng endpoint Ping — không đăng ký được |
1. Đăng ký endpoint
Phần tiêu đề “1. Đăng ký endpoint”curl -s -X POST "$GOHOST_API/properties/<tenant_id>/webhooks" \ -H "Authorization: Bearer $GOHOST_KEY" -H "Content-Type: application/json" \ -d '{ "url": "https://partner.example.com/gohost/webhook", "events": ["booking.created", "booking.cancelled"] }'Phản hồi có secret dạng whsec_… — chỉ hiện một lần, lưu lại để kiểm chữ ký. Body đầy đủ:
Store Webhook Endpoint.
Ràng buộc: URL phải là https (cổng 443), không chứa user:pass, không trỏ vào địa chỉ mạng nội bộ; GoHost
không theo redirect (3xx tính là thất bại). Mỗi key, trên mỗi cơ sở: tối đa 5 endpoint đang bật, mỗi URL
đăng ký một lần.
Gửi thử: Ping → nhận sự kiện webhook.ping.
2. Nội dung mỗi lần gửi
Phần tiêu đề “2. Nội dung mỗi lần gửi”{ "id": "evt_01j…", "type": "booking.created", "created_at": "2026-11-20T14:05:09+07:00", "tenant_id": "<tenant_id>", "data": { "id": "…", "…": "…" }}datacó cùng cấu trúc với Get Booking Detail.created_attheo múi giờ của cơ sở.idkhác nhau cho từng endpoint. Dùng nó để bỏ qua sự kiện trùng — cùng một sự kiện có thể tới nhiều lần khi GoHost gửi lại.
Header đi kèm: X-Gohost-Signature, X-Gohost-Event-Id, X-Gohost-Event, X-Gohost-Timestamp,
User-Agent: GoHost-Webhook/1.0.
3. Kiểm chữ ký
Phần tiêu đề “3. Kiểm chữ ký”X-Gohost-Signature có dạng t=<unix timestamp>,v1=<chữ ký>, trong đó chữ ký là
HMAC-SHA256 (hex) của chuỗi "<t>.<raw body>" với khoá là secret của endpoint.
- Tách
tvàv1từ header. - Tính HMAC-SHA256 của
t + "." + body gốc(đúng byte nhận được, chưa parse JSON). - So sánh với
v1bằng hàm so sánh an toàn thời gian. - Từ chối nếu
tlệch giờ máy bạn quá 5 phút (chống gửi lại).
// Node.js — Express: dùng express.raw({ type: 'application/json' }) để giữ nguyên bodyimport crypto from 'node:crypto';
function verifyGohostSignature(rawBody, header, secret) { const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('='))); const t = Number(parts.t); if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'); const a = Buffer.from(expected); const b = Buffer.from(parts.v1 ?? ''); return a.length === b.length && crypto.timingSafeEqual(a, b);}// PHPfunction verifyGohostSignature(string $rawBody, string $header, string $secret): bool { parse_str(str_replace(',', '&', $header), $p); $t = (int) ($p['t'] ?? 0); if ($t === 0 || abs(time() - $t) > 300) return false; $expected = hash_hmac('sha256', $t . '.' . $rawBody, $secret); return hash_equals($expected, $p['v1'] ?? '');}Đổi secret: Rotate Secret — secret cũ mất hiệu lực ngay, cập nhật bên bạn trước khi gọi.
4. Trả lời và gửi lại
Phần tiêu đề “4. Trả lời và gửi lại”- Trả mã 2xx trong 5 giây là thành công. Xử lý nặng thì đưa vào hàng đợi rồi trả 200 ngay.
- Không thành công: ngoài lần gửi đầu, GoHost gửi lại tối đa 8 lần, cách nhau 5 giây, 30 giây, 2 phút, 10 phút, 30 phút, 2 giờ, 6 giờ, 24 giờ (tổng 9 lần thử).
- Trả
410 Gone: endpoint bị tắt ngay. 8 sự kiện liên tiếp đều thất bại hết 9 lần thử: endpoint tự tắt — bật lại bằng Update Webhook Endpoint (is_active: true). - Xem lịch sử gửi (giữ 14 ngày): Deliveries.
- API key bị tắt thì mọi webhook của key đó cũng tắt theo và không bật lại được.
Vui lòng không nhập tên, số điện thoại hay thông tin cá nhân của bạn hoặc của khách.
Hỗ trợ trực tiếp 8:00–22:00 hằng ngày, kể cả cuối tuần.