Intro to notifications
Note: If you are interested in this feature, contact your Technical Account Manager before implementing it.
The notification service (also referred to as "webhooks") enables us to push real-time notifications to your service endpoint when asynchronous events occur. HTTPS is used to send these notifications to your app as a JSON payload. You can then use these notifications to execute actions in your system.
Note that
- Notifications are not "bundled"; they are sent as they occur.
- In the event that you have issues receiving a webhook notification (because of a database failure, network outage, unavailable callback URL, and so on), we attempt to resend the notification according to its retry policy.
To enable notifications, you must create and configure a callback configuration and then subscribe to events types (the full procedure is provided below). The callback configuration and its subscriptions are collectively referred to as the "notification profile". One profile is used for all of your lodging partners. See below for the complete procedure.
Event types
To support workflows across the API's capabilities, the following event types are available for subscription. (You can use the notificationEventTypes
query to retrieve this list of available event types.)
Event type name | Sent when | Retry policy |
---|---|---|
GuestReviewSubmitted | A traveler left a review. | Every 25 seconds, up to 50 retry attempts. |
MessageAttributesUpdated | A message's status changed, as it moves through moderation. | Every hour for one day. |
MessageReceived | A traveler or PM sent a message. | Every hour for one day. |
MessageThreadCreated | A new message thread was created when a reservation was created. | Every hour for one day. |
PropertyStatusChanged | A property became active or inactive. | Every hour for seven days. |
PropertyStatusMinRequirementMissing | A property was created with the minimum required information (address, name, type, location, and default locale). | Every hour for seven days. |
ReservationNotificationEvent | A reservation was created, modified, or cancelled by a traveler. | Exponential backoff strategy where the retry interval is increased exponentially after every attempt for up to 2.5 hours. After the notification expires, an email message is sent to you. |
ReviewsApproved | A traveler review was approved. | Every 25 seconds, up to 50 retry attempts. |
ReviewsManagementResponseApproved | A PM's review response was approved. | Every 25 seconds, up to 50 retry attempts. |
ReviewsManagementResponseRejected | A PM's review response was rejected. | Every 25 seconds, up to 50 retry attempts. |
Implementation details and requirements
If multiple GraphQL capabilities are implemented, you may want to create multiple callback configurations (one callback URL is specified per configuration) and then you can subscribe to specific event types. For example, you could create one callback configuration for property status events and one for reviews events. (The notification profile comprises all callback configurations and their subscriptions.)
Endpoint requirements when creating an HTTPS service endpoint (callback URL):
Because traveler data and payment information is passed, you must secure all endpoints using a client-certificate (rather than whitelisting the endpoint IP address).
- Obtain a certificate from a Trusted Root Certificate Authority. Some well-known providers are GeoTrust, Verisign, Actalis, Comodo, DigiCert, GoDaddy, and Entrust. The TLS certificate cannot be self-signed, and there needs to be a complete certificate chain including the root, intermediate, and server certificate.
- Test your certificate prior to sending endpoint URLs to Vrbo.
- Install the certificate(s) and deliver endpoints at least two to three weeks prior to the anticipated launch date. This allows enough time to address certificate issues and retest the integration if issues arise with the certificate.
- Keep your certificate current; expired certificates can cause booking transactions to fail.
Then, be aware of the following security guidelines:
- TLS 1.2 or 1.3 is required to provide over-the-wire encryption (HTTPS).
- Use the default HTTPS port (443) but do not explicitly include the port in the endpoint URL.
The service endpoint (callback URL) must return HTTP status code 200 after successful receipt of notifications.
Downstream processing of events must occur asynchronously.
Be sure to allow for comma-delimiting hashes in the HTTP headers of notifications (complete details below).
Set the request timeout to 10 seconds or less, and ensure your service responds to requests immediately after they are received (less than five seconds is recommended, less that one second is ideal). See
requestTimeoutSeconds
inCreateNotificationCallbackConfigInput
andUpdateNotificationCallbackConfigInput
to set the timeout.In rare instances, duplicate webhook notifications may be sent. The
notification_id
attribute in the payload enables you to identify duplicates. We recommend that you implement logic to check if a notification has already been received.
Enabling notifications
Before beginning, share your callback URLs with your TAM and wait for confirmation before completing these steps. Then, be sure to complete the steps for each callback configuration, if implementing more than one callback service endpoint (URL).
Generate an API key that you can use when registering your callback URL.
Create an HTTPS service endpoint (callback URL) on your local server, and then deploy your endpoint so that it’s a publicly accessible HTTPS URL.
The URL must be able to accept a notification payload, and it must return HTTP status code 200 after successful receipt of the notification. Downstream processing of the event must occur asynchronously. (If you subscribe to notifications before the callback URL can accept traffic, our retry logic will generate unnecessary errors in our monitoring reports. If you do not return status code 200, we continue to resend the notification to your server as per retry policy.)
Your endpoint must use Transport Layer Security (TLS) 1.2 or 1.3, to provide over-the-wire encryption (HTTPS).
Create a callback configuration using the
createNotificationCallbackConfig
mutation. Input to this mutation includes the callback URL, API key, partner email address, and request timeout value. This also registers your callback URL and creates the notification profile if it does not exist.When creating the callback configuration, the API generates a secret along with its expiration date and time, which are returned in the mutation response. You can use the secret to validate the signature of payloads when you receive notifications from the webhooks service.Note: Immediately after registering the callback URL, we send a GET request to your endpoint, to check connectivity from the Expedia network and verify whether the URL is whitelisted. This is issued once and can be ignored.By default, the secret is valid for one year. You can determine when it will expire using the
secretExpirationDateTime
field; we recommend that you renew the secret at least 30 days before the expiry date. If the secret expires, notifications fail to be sent for active subscriptions, though we attempt to retry sending them (according to the retry policy for the event type). If the secret is refreshed during these retry attempts, notifications are sent successfully. After the secret is refreshed, you have up to three days to replace the old secret (as specified when refreshing the secret).The following is passed in the HTTP headers of the notification:
- API key.
- Timestamp, in epoch time.
- Signature, in this format:
sha256=hash(timestamp.notification_payload)
. This is a Base64-encoded HMAC-SHA256 hash of the timestamp and notification payload using the secret as the key. If the old secret is still active, the format issha256=hash(timestamp.notification_payload) with newSecret,hash(timestamp.notification_payload) with oldSecret
. Note that you must code for comma-delimiting hashes in both cases.
Here is an example of the headers for a
MessageAttributesUpdated
notification:1"transactionId": "11111111-1111-11ec-97a3-5d06cc689918"2"api-key": "apiKey"3"x-eg-notification-timestamp": "1674149042995"4"x-eg-notification-signature-v2": "sha256=hash(1732710561482.{"event_name":"MessageAttributesUpdated","creation_time":"2024-11-28T10:27:18.212Z","notification_id":"53c7cb70-d772-4ddd-ad04-b1fcae1620c8","payload":{"property_id":"11840519","message_thread_id":"46c35257-1e78-45c0-a64d-cc5fae75d007","message_id":"20aeeade-0bf4-48f2-8c8b-9cda524551a9","from_role":"SUPPLIER","reservation_id":"368177214","message_attributes":[{"attribute":"reviewStatus","value":"ACCEPTED"}]}}, WUsM9s+yTDln9AfZVVAY+g==)"Subscribe to event types using the
subscribeNotificationEventType
mutation.PropertyStatusMinRequirementMissing
PropertyStatusChanged
MessageThreadCreated
MessageReceived
MessageAttributesUpdated
Reservation management capability:
MessageThreadCreated
MessageReceived
ReservationNotificationEvent
GuestReviewSubmitted
ReviewsApproved
ReviewsManagementResponseApproved
ReviewsManagementResponseRejected
Verify the authenticity of requests (to make sure the requests are from Expedia) by
- Verifying the API key provided in the request header
- Confirming the security hash that you generate is same as what we send along with the payload
After enabling notifications, you can use these mutations to manage your callback configuration(s) and subscriptions:
notificationProfile
query - Retrieves the partner profile.sendTestNotification
mutation - Sends a test notification using the specified event type and payload. The notification is sent to the configured callback URL.updateNotificationCallbackConfig
mutation - Updates the callback configuration, including the callback URL, API key, and request timeout value.refreshNotificationCallbackConfigSecret
mutation - Refreshes the secret of the callback configuration.updateNotificationEventTypeSubscription
mutation - Updates the callback ID associated with the registered event type.undeliveredNotifications
query - Retrieves any undelivered notifications for a given event type.unsubscribeNotificationEventType
mutation - Unsubscribes from event types.deleteNotificationCallbackConfig
mutation - Deletes a callback configuration using the callback ID.
Notification payloads
This section provides format and examples of each payload type.
Property status event type payloads
This section provides a description of the payload attributes and examples of each event type.
Attribute | Description |
---|---|
event_name | Event name value. |
creation_time | UTC timestamp when event occurred. |
notification_id | Notification ID. |
property_id | Expedia property ID. Child attribute of payload . |
property_active_status | Boolean indicating whether the property is active. Child attribute of payload . |
checkpoints | Array of advertisers (partners); name and status (whether it's been satisfied) are provided for each advertiser. |
- PropertyStatusMinRequirementMissing
- PropertyStatusChanged
1{2 "event_name": "PropertyStatusMinRequirementMissing",3 "creation_time": "2023-09-26T07:50:51.726Z",4 "notification_id": "8c7ffeec-5eb6-4cd7-8557-0f6d9290f359",5 "payload": {6 "property_id": "71888474",7 "checkpoints": [8 {9 "name": "HasImages",10 "status": "false"11 },12 {13 "name": "HasRates",14 "status": "false"15 },16 {17 "name": "HasBookingType",18 "status": "false"19 },20 {21 "name": "HasCancellationPolicy",22 "status": "false"23 },24 {25 "name": "HasHouseRules",26 "status": "false"27 },28 {29 "name": "HasCheckInCheckOut",30 "status": "false"31 },32 {33 "name": "HasPropertyDetails",34 "status": "false"35 },36 {37 "name": "HasPropertyDescription",38 "status": "false"39 },40 {41 "name": "HasBathroom",42 "status": "false"43 },44 {45 "name": "HasMaxOccupancy",46 "status": "false"47 },48 {49 "name": "HasPropertyType",50 "status": "false"51 }52 ]53 }54}
Reservation event type payloads
This section provides a description of the payload attributes and examples of the event type.
Attribute | Description |
---|---|
event_name | Event name value. |
creation_time | UTC timestamp when event occurred. |
notification_id | Notification ID. |
property_id | Expedia property ID. Child attribute of payload . |
property_source | Source platform of the property. Valid values are VRBO or EXPEDIA_GROUP. Child attribute of payload . |
reservation_id | Reservation ID. Child attribute of payload . |
confirmation_token | Notification token to be sent to Expedia to confirm receipt of the notification (between 1-50 characters in length). Child attribute of payload . |
action_type | Reservation state. Valid values are BOOKED, MODIFIED, or CANCELLED. Child attribute of payload . |
- ReservationNotificationEvent
1{2 "event_name":"ReservationNotificationEvent",3 "creation_time":"2024-10-10T09:49:08.297506452Z",4 "notification_id":"e85b23f3-5d13-412a-8a63-9a974373d0899",5 "payload": {6 "property_id": "64250",7 "reservation_id": "12345",8 "confirmation_token": "LPtu3SI+ZovWJincjJrv9+GZUpln8ofYfrKhAaWQOBM=",9 "action_type": "BOOKED",10 "property_source": "EXPEDIA_GROUP"11 }12}
Messaging event type payloads
This section provides a description of the payload attributes and examples of each event type.
Attribute | Description |
---|---|
event_name | Event name value. |
creation_time | UTC timestamp when the message was created (including retries). |
notification_id | Notification ID. |
property_id | Expedia property ID. Child attribute of payload . |
message_thread_id | Message thread ID. Child attribute of payload . |
message_id | Message ID. Child attribute of payload . |
message_type | Message type; refer to Message types for the list of possible values. Child attribute of payload . |
from_role | Sender. Child attribute of payload . Possible values include TRAVELER and SUPPLIER. |
reservation_id | Expedia reservation ID. Child attribute of payload . Present if associated with a message or message thread. |
message_attributes | Array of attribute child attributes, which each include name and value . Currently, only the reviewStatus message attribute is supported, which indicates the review status of the message. Possible values include IN_REVIEW, ACCEPTED, and BLOCKED. message_attributes is a child attribute of payload . |
- MessageThreadCreated
- MessageReceived
- MessageAttributesUpdated
1{2 "event_name": "MessageThreadCreated",3 "notification_id": "63376d68-651a-11ed-9022-0242ac120442",4 "creation_time": "2023-01-10T17:13:36.140Z",5 "payload": {6 "property_id": "15239779",7 "message_thread_id": "63676d68-651a-11ed-9022-0242ac120432",8 "reservation_id": "63676d68-651a-11ed-9022-0242ac120882"9 }10}
Reviews event type payloads
This section provides a description of the payload attributes and examples of each event type.
Attribute | Description |
---|---|
event_name | Event name value. |
creation_time | UTC timestamp when the event occurred. |
notification_id | Notification ID. |
property_id | Expedia property ID. Child attribute of payload . |
eg_reservation_id | Expedia reservation ID. Child attribute of payload . |
supplier_reservation_id | Property manager's reservation ID. Child attribute of payload . |
review_id | Review ID. Child attribute of payload . |
- GuestReviewSubmitted
- ReviewsApproved
- ReviewsManagementResponseApproved
- ReviewsManagementResponseRejected
1{2 "event_name": "GuestReviewSubmitted",3 "creation_time": "2023-10-04T16:02:58.978Z",4 "notification_id": "9c065ff3-7c21-4eef-be11-da11f543590c",5 "payload": {6 "eg_reservation_id": "5ee844ca-e753-491b-a391-be8598597259",7 "supplier_reservation_id": "19043678",8 "property_id": "82898394"9 }10}