Reservation webhooks

Subscribe to and troubleshoot reservation webhook events.

Reservation events

Guesty sends a reservation webhook when a new booking is created or when an existing reservation is updated, such as a status change, listing change, or date adjustment. There are two generations of reservation webhooks:

  1. Legacy: reservation.new, reservation.updated, and reservation_update_shortlist
  2. Version 2 (v2): Reservation.created.v2 and reservation.updated.v2

The main difference is that the new version separates financial and payment data from stay details and adds several improvements:

  • Lean payloads: Reduced data overhead for faster processing. Primarily reservation stay details and the feature name that was edited. Financials and payments have been separated from the reservation webhooks, as well as the complete listing and guest details. You now retrieve the relevant object to obtain complete details.
  • Clearer change tracking: The updated event includes changedFields to tell you exactly what triggered the webhook.
  • Improved Sequencing: Helps mitigate race conditions by providing a publishedAt timestamp and clear event subtypes.

We recommend using the v2 events, since the legacy versions will be phased out by the end of 2026. If you have any issues with v2, let us know. You can find a migration guide here.

Known issues

Currently, updates to the guest folio do not emit webhooks, but endpoints are available to retrieve the data. In addition, there is no reservations v3 resource for payment records. Solutions for both are planned. Until they’re available, you can keep using the legacy resources. If you need help accessing the information, contact our support team, and we’ll assist you.

What Notifications Can I Receive?

The table below describes all reservation events available for subscription. You should run tests with all the events that appear to meet your needs and then adjust your subscription accordingly for the events that help you meet your objectives.

EventDescription
Reservation.newSent when a new booking request or instant booking is created. This is a legacy event that will be deprecated by the end of the year.
reservation.updatedSent when a reservation’s stay details, guest folio, or reservation payment is altered. This is a legacy event that will be deprecated by the end of the year.
reservation_update_shortlistA legacy event, similar to reservation.updated but designed to be a digest of all alterations made within a fixed period of time. The v2 event is still our recommendation rather than this one.
reservation.created.v2Replaces the legacy event. Sent when a new booking request or instant booking is created.
reservation.updated.v2Replaces the legacy event. Sent when there are alterations to the stay details. Excludes guest folio and payment actions.

Data structures

Legacy data structure

The legacy events emitted the full reservation object and event label, with updates adding a reservationBefore object. Due to the size of the payloads, only the top-level parameters are shown. Perform your own tests to map event shapes.

{
  // The event value will be either `reservation.new`, `reservation.updated`, or `reservation_update_shortlist`
  "event: "reservation.event", 
  "meta": {},
  "reservation": {},
  // The following appears on `reservation.updated` events only
  "reservationBefore": {}
}

Legacy payloads included all settings, pricing, and payment information, which made them difficult to manage. To simplify your workflow and follow webhook best practices, we’ve introduced the new v2 structure, explained in the next section.

Examples

Payloads will vary depending on the listing and rate plan. Always perform your own testing to learn and map the data shapes. These examples are truncated due to the size of their payloads.

reservation.new
{
  "event": "reservation.new",
  "meta": {
    "eventId": "ad14d9ae-f5f4-41c9-8c06-2d8595b5373d",
    "messageId": "355f0b4f-0eff-4cbc-90fb-bb3b0892600f"
  },
  "reservation": {
    "__v": 0,
    "_id": "6a96ae8ea07eac3dcadf0aab",
    "accountId": "66053c21dd2adbdfb3b383b7",
    "accountingEnabled": true,
    "additionalFeesAtCreation": [ ... ],
    "atTimeOfConfirmation": { ... },
    "checkIn": "2026-09-16T12:00:00.000Z",
    "checkInDateLocalized": "2026-09-16",
    "checkOut": "2026-09-20T07:00:00.000Z",
    "checkOutDateLocalized": "2026-09-20",
    "confirmationCode": "GY-pCCSraYC",
    "confirmedAt": "2026-09-01T10:53:02.980Z",
    "confirmedPreBookings": [],
    "createdAt": "2026-09-01T10:53:02.981Z",
    "creationFlow": "INTERNAL",
    "creationInfo": null,
    "customFields": [ ... ],
    "daysInAdvance": 15,
    "earlyCheckIn": { ... },
    "flag": false,
    "guest": { ... },
    "guestId": "68b455b9e7d0e5d47378ac4b",
    "guestStay": { ... },
    "guestsCount": 2,
    "guestyFeeDetails": { ... },
    "id": "6a96ae8ea07eac3dcadf0aab",
    "inquiryId": "6a96ae565e369adac2074c32",
    "integration": { ... },
    "isAnalyticsUpToDate": false,
    "isBMApplied": false,
    "isImported": false,
    "isMidStay": false,
    "isProxiedByV3": false,
    "isReturningGuest": true,
    "lastStayListingId": "66054019764cbb000f37c450",
    "lastUpdatedAt": "2026-09-01T10:53:04.293Z",
    "lateCheckOut": { ... },
    "listing": { ... },
    "listingId": "66054019764cbb000f37c450",
    "manuallyCreated": true,
    "money": { ... },
    "mtl": { ... },
    "nightsCount": 4,
    "notes": { ... },
    "numberOfGuests": { ... },
    "plannedArrival": "",
    "plannedDeparture": "",
    "pulledByDailySync": false,
    "review": { ... },
    "source": "manual",
    "sourceMeta": { ... },
    "status": "confirmed",
    "stay": [ ... ],
    "systemSource": "SANDWORM"
  }
}
reservation.updated
{
"event": "reservation.updated",
"meta": {
  "eventId": "e1fa9e19-d28d-4aab-8849-de2888c6684d",
  "messageId": "30ea4919-f7de-4657-9b4a-6a6ee26b5b41"
},
"reservation": {
  "__v": 0,
  "_id": "6a96ae8ea07eac3dcadf0aab",
  "accountId": "66053c21dd2adbdfb3b383b7",
  "accountingEnabled": true,
  "additionalFeesAtCreation": [ ... ],
  "alteredAt": "2026-09-01T11:27:50.030Z",
  "atTimeOfConfirmation": { ... },
  "checkIn": "2026-09-16T12:00:00.000Z",
  "checkInDateLocalized": "2026-09-16",
  "checkOut": "2026-09-20T07:00:00.000Z",
  "checkOutDateLocalized": "2026-09-20",
  "confirmationCode": "GY-pCCSraYC",
  "confirmedAt": "2026-09-01T10:53:02.980Z",
  "confirmedPreBookings": [],
  "conversationId": "68b455bb65642b00132270f9",
  "createdAt": "2026-09-01T10:53:02.981Z",
  "creationFlow": "INTERNAL",
  "creationInfo": null,
  "customFields": [ ... ],
  "daysInAdvance": 15,
  "earlyCheckIn": { ... },
  "flag": false,
  "guest": { ... },
  "guestId": "68b455b9e7d0e5d47378ac4b",
  "guestStay": { ... },
  "guestsCount": 2,
  "guestyFeeDetails": { ... },
  "inquiryId": "6a96ae565e369adac2074c32",
  "integration": { ... },
  "isAnalyticsUpToDate": false,
  "isBMApplied": false,
  "isImported": false,
  "isMidStay": false,
  "isProxiedByV3": false,
  "isReturningGuest": true,
  "keyCode": "1234",
  "lastStayListingId": "66054019764cbb000f37c450",
  "lastUpdatedAt": "2026-09-01T11:27:50.217Z",
  "lateCheckOut": { ... },
  "listing": { ... },
  "listingId": "66054019764cbb000f37c450",
  "manuallyCreated": true,
  "money": { ... },
  "mtl": { ... },
  "nightsCount": 4,
  "notes": { ...  },
  "numberOfGuests": { ... },
  "plannedArrival": "",
  "plannedDeparture": "",
  "pulledByDailySync": false,
  "review": { ... },
  "sharedTopicContext": { ... },
  "source": "manual",
  "sourceMeta": { ... },
  "specialRequests": null,
  "status": "confirmed",
  "stay": [ ... ],
  "systemSource": "SANDWORM"
},
"reservationBefore": {
  "__v": 0,
  "_id": "6a96ae8ea07eac3dcadf0aab",
  "accountId": "66053c21dd2adbdfb3b383b7",
  "accountingEnabled": true,
  "additionalFeesAtCreation": [ ... ],
  "atTimeOfConfirmation": { ... },
  "checkIn": "2026-09-16T12:00:00.000Z",
  "checkInDateLocalized": "2026-09-16",
  "checkOut": "2026-09-20T07:00:00.000Z",
  "checkOutDateLocalized": "2026-09-20",
  "confirmationCode": "GY-pCCSraYC",
  "confirmedAt": "2026-09-01T10:53:02.980Z",
  "confirmedPreBookings": [],
  "conversationId": "68b455bb65642b00132270f9",
  "createdAt": "2026-09-01T10:53:02.981Z",
  "creationFlow": "INTERNAL",
  "creationInfo": null,
  "customFields": [ ... ],
  "daysInAdvance": 15,
  "earlyCheckIn": { ... },
  "flag": false,
  "guestId": "68b455b9e7d0e5d47378ac4b",
  "guestStay": { ... },
  "guestsCount": 2,
  "guestyFeeDetails": { ... },
  "id": "6a96ae8ea07eac3dcadf0aab",
  "inquiryId": "6a96ae565e369adac2074c32",
  "integration": { ... },
  "isAnalyticsUpToDate": false,
  "isBMApplied": false,
  "isImported": false,
  "isMidStay": false,
  "isProxiedByV3": false,
  "isReturningGuest": true,
  "lastStayListingId": "66054019764cbb000f37c450",
  "lastUpdatedAt": "2026-09-01T10:53:11.856Z",
  "lateCheckOut": {
    "blockDay": false
  },
  "listingId": "66054019764cbb000f37c450",
  "manuallyCreated": true,
  "money": { ... },
  "mtl": { ... },
  "nightsCount": 4,
  "notes": { ... },
  "numberOfGuests": { ... },
  "plannedArrival": "",
  "plannedDeparture": "",
  "pulledByDailySync": false,
  "review": { ... },
  "sharedTopicContext": { ... },
  "source": "manual",
  "sourceMeta": { ... },
  "status": "confirmed",
  "stay": [ ... ],
  "systemSource": "SANDWORM"
}
}
reservation_update_shortlist
{
"event": "reservation_update_shortlist",
"meta": {
  "eventId": "4995238e-3590-4af1-b742-fd091457f4f2",
  "messageId": "cceac401-3f8b-4285-9a91-e92d8b71fd09"
},
"reservation": {
  "__v": 0,
  "_id": "68b455ba12fe97b028d809ac",
  "accountId": "66053c21dd2adbdfb3b383b7",
  "accountingEnabled": true,
  "additionalFeesAtCreation": [],
  "agentBooking": false,
  "alteredAt": "2025-08-31T14:06:22.119Z",
  "atTimeOfConfirmation": { ... },
  "checkIn": "2025-09-04T07:00:00.000Z",
  "checkInDateLocalized": "2025-09-04",
  "checkOut": "2025-09-10T07:00:00.000Z",
  "checkOutDateLocalized": "2025-09-10",
  "confirmationCode": "GY-BCWSu5kE",
  "confirmedPreBookings": [],
  "conversationId": "68b455bb65642b00132270f9",
  "createdAt": "2025-08-31T14:01:30.096Z",
  "creationInfo": null,
  "customFields": [],
  "daysInAdvance": 3,
  "earlyCheckIn": { ... },
  "flag": false,
  "guest": { ... },
  "guestId": "68b455b9e7d0e5d47378ac4b",
  "guestsCount": 2,
  "guestyFeeDetails": { ... },
  "inquiryId": "68b456dc30af3f0597827604",
  "integration": { ... },
  "isBMApplied": false,
  "isImported": false,
  "isMidStay": false,
  "isProxiedByV3": false,
  "isReturningGuest": false,
  "keyCode": null,
  "lastStayListingId": "66054019764cbb000f37c450",
  "lastUpdatedAt": "2025-08-31T14:06:24.599Z",
  "lateCheckOut": { ... },
  "listing": { ... },
  "listingId": "66054019764cbb000f37c450",
  "manuallyCreated": true,
  "money": {
    "_id": "68b455bafcab9c1d7d4030e2",
    "altered": false,
    "autoPaymentsPolicy": [],
    "balanceDue": 1210.2,
    "bundledFees": [ ... ],
    "channelAfBreakdown": [ ... ],
    "channelCommissionRules": { ... },
    "commission": 79.8,
    "commissionFormula": "net_income*0.3",
    "commissionIncTax": 93.37,
    "commissionTax": 13.57,
    "commissionTaxPercentage": 17,
    "createdAt": "2025-08-31T14:01:30.517Z",
    "currency": "EUR",
    "deductedFees": [],
    "fareAccommodation": 66,
    "fareAccommodationAdjusted": 66,
    "fareAccommodationAdjustment": 0,
    "fareAccommodationBundleFeesApplied": 0,
    "fareAccommodationDiscount": 0,
    "fareCleaning": 200,
    "hostPayout": 1210.2,
    "hostPayoutUsd": 1414.12,
    "hostServiceFee": 29.26,
    "hostServiceFeeIncTax": 34.23,
    "hostServiceFeeTax": 4.97,
    "invoiceItems": [ ... ],
    "isFullyPaid": false,
    "netIncome": 266,
    "netIncomeFormula": "fare_accommodation + fare_cleaning",
    "nightlyRateInvoiceItems": [ ... ],
    "ownerRevenue": 172.63,
    "ownerRevenueFormula": "net_income - pm_commission",
    "paymentProviderIds": [ ... ],
    "payments": [ ... ],
    "paymentsDue": 0,
    "platform": "manual",
    "reservationId": "68b455ba12fe97b028d809ac",
    "settingsSnapshot": { ... },
    "subTotalPrice": 895.71,
    "totalFees": 858.97,
    "totalPaid": 0,
    "totalRefunded": 0,
    "totalTaxes": 314.49,
    "updatedAt": "2025-08-31T14:06:24.149Z",
    "useAccountRevenueShare": false,
    "version": 2
  },
  "mtl": { ... },
  "nightsCount": 6,
  "notes": { ... },
  "numberOfGuests": { ... },
  "pendingTasks": [],
  "plannedArrival": "10:00",
  "plannedDeparture": "10:00",
  "pulledByDailySync": false,
  "reasonForVisit": "other",
  "review": { ... },
  "source": "manual",
  "sourceMeta": { ... },
  "specialRequests": "",
  "status": "closed",
  "stay": [ ... ],
  "systemSource": "SANDWORM",
  "transportation": { ... },
  "reservation_changes": {
    "_id": "68b455ba12fe97b028d809ac",
    "accountId": "66053c21dd2adbdfb3b383b7",
    "guest_data_changed": { ... },
    "reservationId": "68b455ba12fe97b028d809ac"
  }
}

📘

Number of Webhooks

Alterations to reservations may produce three legacy webhooks for the same event. These are different, and we recommend that you analyze them to derive an effective schema for mapping with your systems. Additionally, you should always pull the latest reservation state from the API and compare it to what you have stored.


V2 data structure

The v2 events follow a similar structure to the legacy webhooks, but the data is more concise and flatter.

{
  // The `data` object contains the reservation details.
  "data: {},
  "event": "reservation.event.v2",
  // The `meta` object contains the `changedFields` information for updated reservations.
  "meta": {}
}

Examples

reservation.created.v2
{
  "data": {
    "accountId": "66053c21dd2adbdfb3b383b7",
    "checkIn": "2026-09-16T15:00:00.000Z",
    "checkInDateLocalized": "2026-09-16",
    "checkOut": "2026-09-20T10:00:00.000Z",
    "checkOutDateLocalized": "2026-09-20",
    "confirmationCode": "GY-pCCSraYC",
    "confirmedAt": "2026-09-01T10:53:02.980Z",
    "createdAt": "2026-09-01T10:53:02.981Z",
    "guestId": "68b455b9e7d0e5d47378ac4b",
    "guestsCount": 2,
    "inquiryId": "6a96ae565e369adac2074c32",
    "lastStayListingId": "66054019764cbb000f37c450",
    "numberOfGuests": {
      "numberOfAdults": 2,
      "numberOfChildren": 0,
      "numberOfInfants": 0,
      "numberOfPets": 0
    },
    "platform": "direct",
    "quoteId": "6a96ae574f2a40c752bfaf5b",
    "reservationId": "6a96ae8ea07eac3dcadf0aab",
    "source": "manual",
    "status": "confirmed",
    "stay": [
      {
        "checkInDateLocalized": "2026-09-16",
        "checkOutDateLocalized": "2026-09-20",
        "eta": "2026-09-16T15:00:00",
        "etd": "2026-09-20T10:00:00",
        "guestsCount": 2,
        "numberOfGuests": {
          "numberOfAdults": 2,
          "numberOfChildren": 0,
          "numberOfInfants": 0,
          "numberOfPets": 0
        },
        "ratePlanId": "697ba9c8b40c6fc14db5a396",
        "unitId": "66054019764cbb000f37c450",
        "unitTypeId": "66054019764cbb000f37c450"
      }
    ],
    "unitId": "66054019764cbb000f37c450",
    "unitTypeId": "66054019764cbb000f37c450"
  },
  "event": "reservation.created.v2",
  "meta": {
    "eventId": "b708e831-d9fc-44d5-b94a-3ff72a0ef815",
    "publishedAt": "2026-09-01T10:53:03.025Z"
  }
}
reservation.updated.v2
{
  "data": {
    "accountId": "66053c21dd2adbdfb3b383b7",
    "checkIn": "2026-09-16T15:00:00.000Z",
    "checkInDateLocalized": "2026-09-16",
    "checkOut": "2026-09-20T10:00:00.000Z",
    "checkOutDateLocalized": "2026-09-20",
    "confirmationCode": "GY-pCCSraYC",
    "confirmedAt": "2026-09-01T10:53:02.980Z",
    "conversationId": "68b455bb65642b00132270f9",
    "createdAt": "2026-09-01T10:53:02.981Z",
    "guestId": "68b455b9e7d0e5d47378ac4b",
    "guestsCount": 2,
    "integrationId": "660d12b08048010013b6a2ef",
    "lastStayListingId": "66054019764cbb000f37c450",
    "numberOfGuests": {
      "numberOfAdults": 2,
      "numberOfChildren": 0,
      "numberOfInfants": 0,
      "numberOfPets": 0
    },
    "platform": "direct",
    "quoteId": "6a96ae574f2a40c752bfaf5b",
    "reservationId": "6a96ae8ea07eac3dcadf0aab",
    "source": "manual",
    "status": "confirmed",
    "stay": [
      {
        "checkInDateLocalized": "2026-09-16",
        "checkOutDateLocalized": "2026-09-20",
        "eta": "2026-09-16T15:00:00",
        "etd": "2026-09-20T10:00:00",
        "guestsCount": 2,
        "numberOfGuests": {
          "numberOfAdults": 2,
          "numberOfChildren": 0,
          "numberOfInfants": 0,
          "numberOfPets": 0
        },
        "ratePlanId": "697ba9c8b40c6fc14db5a396",
        "unitId": "66054019764cbb000f37c450",
        "unitTypeId": "66054019764cbb000f37c450"
      }
    ],
    "unitId": "66054019764cbb000f37c450",
    "unitTypeId": "66054019764cbb000f37c450"
  },
  "event": "reservation.updated.v2",
  "meta": {
    "changedFields": [
      "notes"
    ],
    "eventId": "f0aa793e-a132-4fba-a0d6-8ac8c421442a",
    "publishedAt": "2026-09-01T11:27:50.039Z",
    "subType": "NOTES_ALTERED"
  }
}
📘

Best Practice

After receiving a webhook, we advise you to invoke the API to fetch the most recent reservation data and compare this fresh data with your locally stored records to determine the full extent of the changes.


FAQs

Why am I receiving two webhooks for the same reservation update?

To ensure all reservation changes are captured after the event, two webhooks are generated. They differ in content, and we recommend you analyze their schema and content to map them to your systems.

Why am I receiving three webhooks for the same reservation update?

To ensure all reservation changes are captured after the event, three webhooks are generated. They differ in content, and we recommend analyzing their schemas and content to map them to your systems.

You should always pull the latest reservation state from the API and compare it with what you have stored.

Why have I received so many reservation update webhooks in such a short time?

Retroactively applying account- or listing-level financial setting changes to reservations may trigger a webhook for each update.

Why have I received the 'reservation.updated' webhook before 'reservation.new'?

This situation may arise when an update is made right after a reservation is created. If a background process related to the reservation’s creation finishes after the update, it could delay the delivery of the creation webhook. In such cases, it's essential to rely on the most up-to-date information.

When in doubt, pull a fresh copy of the reservation from the API.

How do I identify an owner’s reservation?

There is currently no consistent way to determine if a reservation is an owner reservation from the webhook payload. data.source may contain "owner" or "owner-guest" as a partial signal, but it may not be sufficient for all cases. The solution is to retrieve the reservation from the API upon receipt of the webhook and evaluate the creationInfo value.




Did this page help you?