Webhooks
Webhooks allow your application to receive real-time notifications when events occur in HMP.
Overview
When an event occurs in HMP (e.g., a new reservation is created), we send an HTTP POST request to your configured webhook URL with details about the event.
Setting Up Webhooks
Create Webhook
POST /api/v1/webhooks
Request Body:
{
"url": "https://yourapp.com/webhooks/hmp",
"events": [
"reservation.created",
"reservation.modified",
"reservation.cancelled",
"guest.checked_in",
"guest.checked_out"
],
"secret": "your_webhook_secret"
}
Response:
{
"data": {
"id": "wh_abc123",
"url": "https://yourapp.com/webhooks/hmp",
"events": [...],
"status": "ACTIVE",
"created_at": "2026-01-22T10:00:00Z"
}
}
List Webhooks
GET /api/v1/webhooks
Update Webhook
PUT /api/v1/webhooks/:id
Delete Webhook
DELETE /api/v1/webhooks/:id
Available Events
Reservation Events
| Event | Description |
|---|---|
reservation.created | New reservation created |
reservation.modified | Reservation details changed |
reservation.cancelled | Reservation cancelled |
reservation.no_show | Guest marked as no-show |
Guest Events
| Event | Description |
|---|---|
guest.checked_in | Guest checked in |
guest.checked_out | Guest checked out |
guest.room_changed | Guest moved to different room |
guest.profile_updated | Guest profile updated |
Housekeeping Events
| Event | Description |
|---|---|
room.status_changed | Room status updated |
room.out_of_order | Room marked out of order |
room.back_in_service | Room returned to inventory |
Billing Events
| Event | Description |
|---|---|
folio.charge_posted | Charge posted to folio |
folio.payment_received | Payment received |
folio.settled | Folio settled |
Channel Events
| Event | Description |
|---|---|
channel.booking_received | Booking from OTA |
channel.modification_received | Modification from OTA |
channel.cancellation_received | Cancellation from OTA |
Webhook Payload
Structure
{
"id": "evt_xyz789",
"type": "reservation.created",
"created_at": "2026-01-22T10:30:00Z",
"property_id": "prop_abc123",
"data": {
// Event-specific data
}
}
Example: Reservation Created
{
"id": "evt_xyz789",
"type": "reservation.created",
"created_at": "2026-01-22T10:30:00Z",
"property_id": "prop_abc123",
"data": {
"reservation": {
"id": "res_xyz789",
"confirmation_number": "HTLABC20260215001",
"status": "CONFIRMED",
"guest": {
"id": "guest_abc",
"name": "John Doe",
"email": "john@email.com"
},
"arrival_date": "2026-02-15",
"departure_date": "2026-02-18",
"rooms": [
{
"room_type": "Deluxe Room",
"rate_plan": "Best Available Rate",
"adults": 2
}
],
"total_amount": 15000.00,
"source": "DIRECT"
}
}
}
Example: Guest Checked In
{
"id": "evt_abc456",
"type": "guest.checked_in",
"created_at": "2026-02-15T14:30:00Z",
"property_id": "prop_abc123",
"data": {
"reservation_id": "res_xyz789",
"guest": {
"id": "guest_abc",
"name": "John Doe"
},
"room": {
"room_number": "405",
"room_type": "Deluxe Room"
},
"check_in_time": "2026-02-15T14:30:00Z",
"expected_checkout": "2026-02-18T11:00:00Z"
}
}
Webhook Security
Signature Verification
Each webhook request includes a signature header for verification:
X-HMP-Signature: sha256=abc123def456...
Verify the signature:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
// In your webhook handler
app.post('/webhooks/hmp', (req, res) => {
const signature = req.headers['x-hmp-signature'];
const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
'your_webhook_secret'
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook
const event = req.body;
console.log(`Received event: ${event.type}`);
res.status(200).json({ received: true });
});
IP Allowlisting
Webhook requests originate from these IP addresses:
52.66.xxx.xxx13.232.xxx.xxx
Retry Policy
If your endpoint returns a non-2xx status code, we retry the webhook:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 5 minutes |
| 3 | 30 minutes |
| 4 | 2 hours |
| 5 | 24 hours |
After 5 failed attempts, the webhook is marked as failed and we send an alert.
Testing Webhooks
Send Test Event
POST /api/v1/webhooks/:id/test
Request Body:
{
"event_type": "reservation.created"
}
View Webhook Logs
GET /api/v1/webhooks/:id/logs
Response:
{
"data": [
{
"id": "log_123",
"event_id": "evt_xyz789",
"event_type": "reservation.created",
"status": "SUCCESS",
"response_code": 200,
"response_time_ms": 150,
"created_at": "2026-01-22T10:30:00Z"
},
{
"id": "log_124",
"event_id": "evt_abc456",
"event_type": "guest.checked_in",
"status": "FAILED",
"response_code": 500,
"response_time_ms": 5000,
"error": "Connection timeout",
"retry_count": 2,
"created_at": "2026-02-15T14:30:00Z"
}
]
}
Best Practices
- Respond quickly - Return 200 status within 5 seconds
- Process asynchronously - Queue webhook processing for reliability
- Handle duplicates - Use event ID for idempotency
- Verify signatures - Always validate webhook authenticity
- Monitor failures - Set up alerts for webhook failures