Webhook Events
VardaCal Platform API can send real-time webhook notifications to your application when events occur in your account. Set up webhooks to receive instant updates about bookings, event types, and more.
Pro Tip: Use webhooks to keep your system synchronized with VardaCal without polling the API. This saves API calls and provides real-time updates.
Setting Up Webhooks
Create webhook endpoints using the Platform API to start receiving event notifications.
1. Create a Webhook Endpoint
Use the Platform API to register your webhook URL:
curl -X POST https://api.vardacal.com/api/v1/platform/webhooks \
-H "X-API-Key: vca_live_sk_..." \
-H "X-API-Secret: secret_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/vardacal",
"events": ["booking.created", "booking.cancelled"],
"enabled": true
}'
Response:
{
"id": 123,
"url": "https://your-app.com/webhooks/vardacal",
"events": ["booking.created", "booking.cancelled"],
"enabled": true,
"secret": "whsec_abc123...",
"created_at": "2025-10-28T12:00:00Z"
}
Important: Save the secret value - you'll need it to verify webhook signatures.
2. Handle Webhook Requests
Create an endpoint in your application to receive webhook POST requests:
// Express.js webhook handler
app.post('/webhooks/vardacal', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-vardacal-signature'];
const payload = req.body;
// Verify signature (see Security section below)
if (!verifySignature(payload, signature)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
// Handle different event types
switch(event.type) {
case 'booking.created':
console.log('New booking:', event.data);
// Add to your database, send notifications, etc.
break;
case 'booking.cancelled':
console.log('Cancelled booking:', event.data);
// Update your records
break;
}
// Always respond with 200 to acknowledge receipt
res.status(200).send('Webhook received');
});
Available Events
Booking Events
-
booking.createdTriggered when a new booking is created -
booking.cancelledTriggered when a booking is cancelled -
booking.rescheduledTriggered when a booking is rescheduled -
booking.confirmedTriggered when a booking is confirmed by the host -
booking.reminder.sentTriggered when a reminder is sent for a booking
Event Type Events
-
event_type.createdTriggered when a new event type is created -
event_type.updatedTriggered when an event type is updated -
event_type.deletedTriggered when an event type is deleted
Payload Examples
Here's what webhook payloads look like for different event types:
booking.created
{
"id": "evt_abc123",
"type": "booking.created",
"created_at": "2025-10-28T14:30:00Z",
"data": {
"id": 456,
"event_type_id": 123,
"start_time": "2025-11-01T10:00:00Z",
"end_time": "2025-11-01T10:30:00Z",
"status": "confirmed",
"attendee": {
"name": "John Doe",
"email": "john@example.com",
"phone": "+1234567890"
},
"meeting_url": "https://meet.vardacal.com/abc123",
"created_at": "2025-10-28T14:30:00Z"
}
}
booking.cancelled
{
"id": "evt_def456",
"type": "booking.cancelled",
"created_at": "2025-10-28T15:00:00Z",
"data": {
"id": 456,
"event_type_id": 123,
"start_time": "2025-11-01T10:00:00Z",
"status": "cancelled",
"cancellation_reason": "Attendee requested cancellation",
"cancelled_at": "2025-10-28T15:00:00Z"
}
}
Webhook Security
Every webhook request includes an HMAC signature in the X-VardaCal-Signature header. Always verify this signature to ensure the webhook came from VardaCal and hasn't been tampered with.
Security Warning: Never process webhooks without verifying the signature. This prevents attackers from sending fake webhook requests to your endpoint.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
// Compute expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
// Use timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Usage in Express handler
app.post('/webhooks/vardacal', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-vardacal-signature'];
const secret = process.env.WEBHOOK_SECRET; // From webhook creation response
if (!verifyWebhookSignature(req.body.toString(), signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Signature is valid, process the webhook
const event = JSON.parse(req.body);
// ... handle event
});
Delivery & Retries
Automatic Retries
If your endpoint doesn't respond with a 2xx status code, VardaCal will automatically retry the webhook with exponential backoff:
- • Attempt 1: Immediate
- • Attempt 2: After 1 minute
- • Attempt 3: After 5 minutes
- • Attempt 4: After 15 minutes
- • Attempt 5: After 1 hour
Best Practice: Respond with a 200 status code as quickly as possible. Process the webhook data asynchronously using a background job queue to avoid timeouts.
Testing Webhooks
Test your webhook endpoint without waiting for real events:
curl -X POST https://api.vardacal.com/api/v1/platform/webhooks/123/test \
-H "X-API-Key: vca_live_sk_..." \
-H "X-API-Secret: secret_..."
This sends a test webhook.test event to your endpoint.