Overview
Webhooks let you receive HTTP notifications when events happen in your workspace. Instead of polling the API, you can subscribe to specific events and Voyant will send a POST request to your endpoint.
Creating a subscription
Create a subscription
curl -X POST https://api.voyantcloud.com/v1/webhooks/subscriptions \
-H "Authorization: Bearer $VOYANT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/voyant",
"events": ["booking.created", "booking.updated"]
}'
The response includes a secret - store it securely. You’ll need it to verify webhook signatures.Verify signatures
Validate incoming webhooks using the X-Webhook-Signature header:import crypto from "node:crypto"
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payload, "utf8")
.digest("hex")
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex")
)
}
Handle events
Return a 2xx status to acknowledge receipt. Non-2xx responses trigger retries.app.post("/webhooks/voyant", (req, res) => {
const signature = req.get("X-Webhook-Signature")
if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(400).send("Invalid signature")
}
const event = req.get("X-Webhook-Event")
// Handle the event...
res.status(200).send({ ok: true })
})
Event types
Subscribe to specific events or use wildcards:
| Pattern | Description |
|---|
booking.created | Single event |
booking.* | All booking events |
* | All events |
Available events
Bookings & Payments
booking.created, booking.updated, booking.cancelled, booking.confirmed
booking.payment.success, booking.payment.failed
payment.succeeded, payment.failed, payment.refunded
Products & Catalog
product.created, product.updated, product.deleted
product.published, product.archived
Inventory
departure.created, departure.updated, departure.capacity.changed
inventory.updated
Customers
customer.created, customer.updated, customer.deleted
Collections & Tags
collection.created, collection.updated, collection.deleted
tag.created, tag.updated, tag.deleted
Every webhook request includes these headers:
| Header | Description |
|---|
X-Webhook-Signature | HMAC-SHA256 signature for verification |
X-Webhook-Event | Event type (e.g., booking.created) |
X-Delivery-Attempt | Attempt number (1, 2, 3…) |
Retries
Failed deliveries are retried with exponential backoff. Return 2xx to acknowledge, or 410 Gone to permanently disable the subscription.
Implement idempotency in your webhook handler - you may receive the same event more than once.
Managing subscriptions
# List subscriptions
curl https://api.voyantcloud.com/v1/webhooks/subscriptions \
-H "Authorization: Bearer $VOYANT_API_KEY"
# Rotate secret (invalidates the old one)
curl -X POST https://api.voyantcloud.com/v1/webhooks/subscriptions/SUBSCRIPTION_ID/rotate-secret \
-H "Authorization: Bearer $VOYANT_API_KEY"
# Delete subscription
curl -X DELETE https://api.voyantcloud.com/v1/webhooks/subscriptions/SUBSCRIPTION_ID \
-H "Authorization: Bearer $VOYANT_API_KEY"
Next steps