Webhooks

Currently, supported webhooks types include: * NEW_ORDER, * NEW_CONTACT, * UPDATED_ORDER, * CANCELED_ORDER, * NEW_PRODUCT, * UPDATED_PRODUCT, * DELETED_PRODUCT

A webhook is sent to a configured endpoint as HTTP POST calls. Webhooks payload is in JSON format, using the same model as Rezdy Public API. The request body is a booking object for order webhooks, a customer object for contact webhooks, a product object for product webhooks.

A webhook consumer should be able to handle idempotent calls, for each webhook triggering event we will attempt a single successful delivery, however in rare cases there might occur a duplicate delivery for the same webhook event.

NEW_ORDER

The webhook is fired whenever a new order is created regardless of the source - if it's API, Internal or Online order.

Some agents create bookings using a 2-steps process. They create reservations first (orders in PROCESSING order status) and then confirm orders by updating their status. In such case the NEW_ORDER webhooks will be fired for reservations (PROCESSING status) and then UPDATED_ORDER webhooks will be fired upon bookings confirmation (orders status CONFIRMED or PENDING_SUPPLIER/PENDING_CUSTOMER if configured on product). Therefore the recommended way to process all confirmed bookings is to setup a NEW_ORDER and an UPDATED_ORDER webhook (they can use the same target URL) and filter bookings with CONFIRMED order status only.

UPDATED_ORDER

The webhook is fired whenever an existing order is updated regardless of the change.

Rezdy does not calculate any differences between the previous, and the current order model, nor provides any indication what kind of update fired the webhook, therefore this has to be calculated by the webhook listener. Furthermore, the payload of the updated order does not necessarily need to be different from a previous one, since not every order change will cause a modification of the exposed public model.

CANCELED_ORDER

The webhook is fired whenever an order is cancelled regardless of the cancellation source - if the status change has been done internally by the supplier or by the reseller.

NEW_CONTACT

The webhook is fired whenever a new contact is created regardless of the source - internally or by a new order.

A new order can trigger both NEW_ORDER and NEW_CONTACT webhook in case of a new customer which is not matched among the existing contacts.

NEW_PRODUCT

The webhook is fired whenever a new product is created.

A complete product creation might have multiple steps on Rezdy therefore for a new product you need to expect one NEW_PRODUCT call, followed by multiple UPDATED_PRODUCT calls as each product tab submission in UI will trigger a product update.

UPDATED_PRODUCT

The webhook is fired whenever an existing product is updated.

Rezdy does not calculate any differences between the previous, and the current product model, nor provides any indication what kind of update fired the webhook, therefore this has to be calculated by the webhook listener. Furthermore, the payload of the updated product does not necessarily need to be different from a previous one, since not every order change will cause a modification of the exposed public model.

DELETED_PRODUCT

The webhook is fired whenever a product is deleted.

Webhook consumer response

A webhook consumer has to respond to a webhook with a successful HTTP response code including any 20X(e.g: 200, 201, 202, 204...), otherwise, the webhook fails will be recorded until its suspended.

For each configured webhook, if execution fails consequently more than 20 times, the webhook will be disabled and alert e-mail will be sent to the company e-mail address. The webhook has to be then manually activated via the Webhook configuration screen on Rezdy.

NEW_CONTACT example payload

Request

POST [configured endpoint] 

Headers:

Accept: application/json,application/xml
Content-Type: application/json

Body:

{
    "id": 9873,
    "firstName": "Homer",
    "middleName": "",
    "lastName": "Simpson",
    "name": "Homer Simpson",
    "email": "homersimpson.3@rezdy.com",
    "companyName": "",
    "phone": "+61484123456",
    "mobile": "",
    "fax": "",
    "skype": "",
    "preferredLanguage": "",
    "marketing": false,
    "aboutUs": "",
    "addressLine": "",
    "postCode": "",
    "city": "",
    "state": "",
    "countryCode": ""
}

Response

HTTP response code (any of 20X e.g: 200, 201, 202, 204...):

200 OK

Body (arbitrary):

{}

NEW_ORDER, UPDATE_ORDER, CANCELED_ORDER example payload

Request

POST [configured endpoint] 

Headers:

Accept: application/json
Content-Type: application/json

Body:

{
    "orderNumber": "DU000157",
    "status": "PENDING_SUPPLIER",
    "supplierId": 9401,
    "supplierName": "Homer",
    "resellerId": 1075,
    "resellerName": "Rezdy Demo",
    "customer": {
        "id": 9870,
        "firstName": "Homer",
        "lastName": "Simpson",
        "name": "Homer Simpson",
        "email": "homersimpson@rezdy.com",
        "mobile": "+61484123456"
    },
    "items": [
        {
            "productName": "AnyDate",
            "productCode": "PZJFH4",
            "startTime": "2017-08-16T09:00:00Z",
            "startTimeLocal": "2017-08-16 19:00:00",
            "quantities": [
                {
                    "optionLabel": "Group from 1 to 2",
                    "optionPrice": 100,
                    "value": 1
                }
            ],
            "totalQuantity": 1,
            "amount": 100,
            "extras": [],
            "participants": [
                {
                    "fields": [
                        {
                            "label": "First Name",
                            "value": "Homer"
                        },
                        {
                            "label": "Last Name",
                            "value": "Simpson"
                        },
                        {
                            "label": "Gender",
                            "value": ""
                        }
                    ]
                }
            ],
            "transferReturn": false,
            "subtotal": 107,
            "vouchers": [],
            "totalItemTax": 7
        }
    ],
    "totalAmount": 109.14,
    "totalCurrency": "AUD",
    "totalPaid": 107,
    "totalDue": 2.1399994,
    "dateCreated": "2018-07-31T00:02:39Z",
    "dateUpdated": "2018-07-31T02:22:44Z",
    "datePaid": "2018-07-31T00:02:42Z",
    "dateReconciled": "2018-07-31T00:02:39Z",
    "comments": "",
    "internalNotes": "",
    "payments": [
        {
            "type": "REZDY_PAYOUTS",
            "amount": 10,
            "currency": "AUD",
            "date": "2018-07-31T00:02:42Z",
            "label": "STRIPE Application Fee: ch_1CtlK0IQxFAfFTHyKDGRlqd5",
            "recipient": "REZDY"
        },
        {
            "type": "REZDY_PAYOUTS",
            "amount": 97,
            "currency": "AUD",
            "date": "2018-07-31T00:02:42Z",
            "label": "STRIPE: ch_1CtlK0IQxFAfFTHyKDGRlqd5",
            "recipient": "SUPPLIER"
        }
    ],
    "fields": [
        {
            "label": "How did you hear about us?",
            "value": "Internet"
        }
    ],
    "source": "MARKETPLACE_PREF_RATE",
    "resellerSource": "API",
    "sourceChannel": "REZDYDEMO",
    "resellerComments": "REZDYDEMO order",
    "surcharge": 2.14,
    "commission": 10,
    "vouchers": [],
    "paymentOption": "CREDITCARD",
    "resellerReference": ""
}

Response

HTTP response code (any of 20X e.g: 200, 201, 202, 204...):

200 OK

Body (arbitrary):

{}

NEW_PRODUCT, UPDATED_PRODUCT, DELETED_PRODUCT example payload

Request

POST [configured endpoint] 

Headers:

Accept: application/json
Content-Type: application/json

Body:

{
    "productType": "ACTIVITY",
    "name": "High Tatras guided hiking tour",
    "shortDescription": "A guided hiking tour in High Tatras mountains.",
    "description": "A guided hiking tour in <b>High Tatras</b> mountains.&nbsp;<p><br></p><p>The tour takes about 10 hours and it's 20 km walk with about 1500m altitude difference and therefore it's <b>suitable only for participants with a good stamina</b>.</p><p><br></p><p>Discount is provided for a group of more than 10 partiicpants.</p>",
    "productCode": "PKN0SN",
    "internalCode": "hightatras",
    "timezone": "Europe/Prague",
    "advertisedPrice": "80.0",
    "priceOptions": [
        {
            "price": "100.0",
            "label": "Adult",
            "seatsUsed": 1,
            "minQuantity": 0,
            "priceGroupType": "EACH"
        },
        {
            "price": "80.0",
            "label": "Group from 10 to 20",
            "seatsUsed": 1,
            "minQuantity": 10,
            "maxQuantity": 20,
            "priceGroupType": "EACH"
        }
    ],
    "currency": "AUD",
    "unitLabel": "Hiker",
    "unitLabelPlural": "Hikers",
    "quantityRequired": true,
    "quantityRequiredMin": 3,
    "quantityRequiredMax": 20,
    "images": [
        {
            "itemUrl": "https://img.rezdy.com/PRODUCT_IMAGE/45720/out.jpg",
            "thumbnailUrl": "https://img.rezdy.com/PRODUCT_IMAGE/45720/out_tb.jpg",
            "mediumSizeUrl": "https://img.rezdy.com/PRODUCT_IMAGE/45720/out_med.jpg",
            "largeSizeUrl": "https://img.rezdy.com/PRODUCT_IMAGE/45720/out_lg.jpg"
        }
    ],
    "bookingMode": "DATE_ENQUIRY",
    "charter": false,
    "extras": [
        {
            "name": "Hiking gear rental",
            "description": "Rental of hiking clothes, shoes, sticks. The price is per a piece of equipment rented.",
            "price": "10.0",
            "extraPriceType": "ANY"
        }
    ],
    "bookingFields": [
        {
            "label": "Title",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "TITLE"
        },
        {
            "label": "Mobile",
            "requiredPerParticipant": false,
            "requiredPerBooking": true,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "MOBILE"
        },
        {
            "label": "Email",
            "requiredPerParticipant": false,
            "requiredPerBooking": true,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "EMAIL"
        },
        {
            "label": "Address",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "ADDRESS"
        },
        {
            "label": "City",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "CITY"
        },
        {
            "label": "Country",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "COUNTRY"
        },
        {
            "label": "State/County/Region",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "STATE"
        },
        {
            "label": "Postcode/ZIP",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "POSTCODE"
        },
        {
            "label": "Special Requirements",
            "requiredPerParticipant": false,
            "requiredPerBooking": false,
            "visiblePerParticipant": false,
            "visiblePerBooking": true,
            "fieldType": "SPECIALREQS"
        },
        {
            "label": "First Name",
            "requiredPerParticipant": true,
            "requiredPerBooking": true,
            "visiblePerParticipant": true,
            "visiblePerBooking": true,
            "fieldType": "FIRSTNAME"
        },
        {
            "label": "Last Name",
            "requiredPerParticipant": true,
            "requiredPerBooking": true,
            "visiblePerParticipant": true,
            "visiblePerBooking": true,
            "fieldType": "LASTNAME"
        }
    ],
    "confirmMode": "MANUAL",
    "confirmModeMinParticipants": 0,
    "dateCreated": "2016-01-18T00:00:22Z",
    "minimumNoticeMinutes": 2880,
    "durationMinutes": 600,
    "dateUpdated": "2020-10-15T05:02:11Z",
    "locationAddress": {
        "addressLine": "Slovakia",
        "city": "Vysoke Tatry",
        "countryCode": "sk",
        "latitude": 49.137508,
        "longitude": 20.2182305,
        "postCode": "",
        "state": ""
    },
    "additionalInformation": "",
    "languages": [
        "en_us"
    ],
    "waitListingEnabled": true,
    "qrCodeType": "INTERNAL",
    "barcodeOutputType": "PARTICIPANT"
}

Response

HTTP response code (any of 20X e.g: 200, 201, 202, 204...):

200 OK

Body (arbitrary):

{}