Webhooks
Receive real-time notifications when events occur in your BookingScheduler account
Overview
Webhooks allow you to build integrations that subscribe to certain events in your BookingScheduler account. When one of those events is triggered, we'll send an HTTP POST payload to the webhook's configured URL.
Webhooks can be used to:
- Update your internal systems when bookings are created or modified
- Send custom notifications to customers
- Sync data with external platforms
- Trigger automated workflows
Setting Up Webhooks
- 1Go to Webhook Settings
Navigate to Organization Settings → Integrations → Webhooks
- 2Add Endpoint URL
Enter the URL where you want to receive webhook events
- 3Select Events
Choose which events you want to subscribe to
- 4Save and Test
Save your webhook and send a test event to verify it works
Available Events
Booking Events
Booking Created
Triggered when a new booking is created
Payload Example
{
"event": "booking.created",
"timestamp": "2024-01-15T10:00:00Z",
"data": {
"id": "book_123",
"experienceId": "exp_456",
"experienceName": "City Walking Tour",
"customerName": "John Doe",
"customerEmail": "[email protected]",
"startTime": "2024-02-15T14:00:00Z",
"participants": 2,
"status": "CONFIRMED",
"totalAmount": 9000,
"currency": "USD"
}
}Booking Confirmed
Triggered when a pending booking is confirmed
Payload Example
{
"event": "booking.confirmed",
"timestamp": "2024-01-15T10:05:00Z",
"data": {
"id": "book_123",
"status": "CONFIRMED",
"confirmedAt": "2024-01-15T10:05:00Z"
}
}Booking Cancelled
Triggered when a booking is cancelled
Payload Example
{
"event": "booking.cancelled",
"timestamp": "2024-01-15T10:10:00Z",
"data": {
"id": "book_123",
"status": "CANCELLED",
"cancelledAt": "2024-01-15T10:10:00Z",
"reason": "Customer request",
"refundAmount": 9000,
"refundStatus": "PENDING"
}
}Booking Updated
Triggered when booking details are modified
Payload Example
{
"event": "booking.updated",
"timestamp": "2024-01-15T10:15:00Z",
"data": {
"id": "book_123",
"changes": {
"participants": {
"old": 2,
"new": 3
},
"totalAmount": {
"old": 9000,
"new": 13500
}
}
}
}Payment Events
Payment Succeeded
Triggered when a payment is successfully processed
Payload Example
{
"event": "payment.succeeded",
"timestamp": "2024-01-15T10:20:00Z",
"data": {
"id": "pay_789",
"bookingId": "book_123",
"amount": 9000,
"currency": "USD",
"method": "card",
"status": "SUCCEEDED"
}
}Payment Failed
Triggered when a payment fails
Payload Example
{
"event": "payment.failed",
"timestamp": "2024-01-15T10:25:00Z",
"data": {
"id": "pay_789",
"bookingId": "book_123",
"amount": 9000,
"currency": "USD",
"status": "FAILED",
"errorCode": "CARD_DECLINED",
"errorMessage": "The card was declined"
}
}Customer Events
Customer Created
Triggered when a new customer is created
Payload Example
{
"event": "customer.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "cust_321",
"name": "Jane Smith",
"email": "[email protected]",
"phone": "+1234567890",
"createdAt": "2024-01-15T10:30:00Z"
}
}Handling Webhooks
Example webhook handler implementation
// Express.js example
const express = require('express');
const app = express();
app.post('/webhooks/bookingscheduler', express.json(), (req, res) => {
const event = req.body;
// Verify webhook signature (see Signature Verification section)
const signature = req.headers['x-bookingscheduler-signature'];
if (!verifySignature(signature, req.body)) {
return res.status(401).send('Invalid signature');
}
// Handle different event types
switch (event.event) {
case 'booking.created':
console.log('New booking:', event.data.id);
// Your custom logic here
break;
case 'booking.cancelled':
console.log('Booking cancelled:', event.data.id);
// Your custom logic here
break;
case 'payment.succeeded':
console.log('Payment succeeded:', event.data.id);
// Your custom logic here
break;
default:
console.log('Unhandled event:', event.event);
}
// Acknowledge receipt
res.status(200).send('OK');
});
app.listen(3000);Signature Verification
BookingScheduler signs webhook payloads with a signature that you can use to verify the webhook came from us. The signature is included in the X-BookingScheduler-Signature header.
Verification Steps:
- Get your webhook signing secret from your dashboard
- Compute an HMAC with the SHA256 hash function
- Compare the computed signature with the received signature
Example Implementation (Node.js):
const crypto = require('crypto');
function verifySignature(signature, payload) {
const secret = process.env.WEBHOOK_SIGNING_SECRET;
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}Best Practices
Do
- ✓ Verify webhook signatures
- ✓ Respond with 200 status code quickly
- ✓ Process webhooks asynchronously
- ✓ Implement retry logic for failed processing
- ✓ Log all webhook events
- ✓ Use HTTPS endpoints
Don't
- ✗ Process webhooks synchronously
- ✗ Assume webhooks arrive in order
- ✗ Rely on duplicate webhook prevention
- ✗ Expose your webhook endpoint publicly without verification
- ✗ Use HTTP (non-secure) endpoints