Agent skill

Guesty Webhooks Skill

Receive and verify Guesty webhooks (delivered by Svix). Use when setting up Guesty webhook handlers, debugging svix-signature verification, fetching the secret from GET /webhooks-v2/secret, or handling short-term rental events like reservation.created.v2, reservation.updated.v2, reservation.new, reservation.updated, and listing.updated.

Install this skill

npx skills add hookdeck/webhook-skills --skill guesty-webhooks


Guesty (property management for short-term rentals) sends webhooks through Svix. Every request is signed with the endpoint's signing secret and carries svix-id, svix-timestamp, and svix-signature headers. The event name is in the body's event field (not type).

When to Use This Skill

  • How do I receive Guesty webhooks?
  • How do I verify Guesty webhook signatures (svix-signature)?
  • Where do I get the Guesty webhook secret?
  • How do I handle reservation.created.v2 / reservation.updated.v2 events?
  • How do I handle legacy reservation.new / reservation.updated events?
  • Why is my Guesty webhook signature verification failing?
  • How do I deduplicate Guesty webhooks?

Verification (core)

Signed content is ${svix-id}.${svix-timestamp}.${raw_body}, HMAC-SHA256 keyed with the base64-decoded bytes after the whsec_ prefix, base64-encoded. The header holds one or more space-separated v1,<signature> entries. Use the official svix SDK (Node and Python) — it handles all of that, the 5-minute timestamp tolerance, and constant-time comparison:

const { Webhook } = require('svix');

const wh = new Webhook(process.env.GUESTY_WEBHOOK_SECRET); // "whsec_..." from GET /webhooks-v2/secret
wh.verify(rawBody, {                                        // raw Buffer/string, never re-serialized JSON
  'svix-id': req.headers['svix-id'],
  'svix-timestamp': req.headers['svix-timestamp'],
  'svix-signature': req.headers['svix-signature'],
}); // throws WebhookVerificationError on a bad signature or stale timestamp

const event = JSON.parse(rawBody.toString('utf8'));
// event.event === 'reservation.created.v2', event.meta.eventId, event.data / event.reservation / ...

Python: from svix.webhooks import Webhook and call Webhook(secret).verify(raw_body, headers) the same way.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

The payload is { "event": "<name>", "meta": { "eventId": ... }, <object>: {...} }. The object key depends on the event: data (reservation v2), reservation (legacy reservation), listing, guest, payment.

EventObject keyTriggered When
reservation.created.v2dataA booking request or instant booking is created (recommended)
reservation.updated.v2dataStay details change; meta.changedFields / meta.subType say what changed
reservation.newreservationLegacy: booking created (being phased out by end of Feb 2027)
reservation.updatedreservationLegacy: reservation, folio, or payment changed; also has reservationBefore
listing.newlistingA listing is created
listing.updatedlistingA listing's settings or content change
listing.removedlistingA listing is deleted
guest.createdguestA guest record is created
payments.receivedpaymentA reservation payment succeeds

Other events: reservation_update_shortlist, calendar.updated.v2, listing.calendar.updated, reservation.messageReceived, reservation.messageSent, guest.updated, guest.deleted, task.created, task.updated, task.deleted, guest-folio.created, guest-folio.updated, and the other payments.* events. See references/overview.md.

Environment Variables

# Per-endpoint signing secret (Svix default format: whsec_ + base64 key)
GUESTY_WEBHOOK_SECRET=whsec_xxxxx

Retrieve it with GET https://open-api.guesty.com/v1/webhooks-v2/secret?url=<your endpoint URL> or from Guesty's webhooks developer dashboard (Developer tools → Webhooks). Deleting and recreating a subscription can issue a new secret.

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 guesty --path /webhooks/guesty

Guesty subscriptions are created through the API (POST /v1/webhooks) and the URL must be HTTPS on port 443, so register the Hookdeck tunnel URL.

Key Gotchas

  • Raw body — verify the exact bytes Guesty sent; parse JSON only afterwards.
  • Deduplicate on svix-id and on meta.eventId (when present). Recovery processes can re-emit old events.
  • Out-of-order delivery — order by __v / lastUpdatedAt (or meta.publishedAt on v2), and re-fetch the object from the API.
  • Respond 2xx within 15 seconds; anything else (including 3xx) is retried on a schedule spanning about 28 hours.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →