Viator Merchant API Certification

Jun 10, 2021 | Merchant API, Travel Commerce Partners

This page is your complete guide to Viator’s API certification requirements, including instructions and best practices for each element we certify.

Please note that this resource focuses on the elements required to pass certification. If you are looking for more detailed information on a particular concept or endpoint, please refer to our technical documentation.

viator merchant api

Who is this guide for?

This page is intended for Merchant Partners who are using the Viator Partner API.

As a Viator Merchant Partner, you use Viator’s merchant API to display and book Viator’s tours and activities. Your organization is the merchant of record, and is responsible for all transactions carried out by your customers, as well as post booking processes and customer support.

Why do we certify API implementations?

Because the merchant API grants transactional access to Viator’s product inventory, it is important we certify that your system meets our minimum criteria and represents an optimized implementation.

More specifically, certification is designed to verify that:

  • Your API endpoint usage follows our guidelines
  • Your system can not generate bookings with invalid data
  • Your travelers receive all information necessary to participate in their tour or activity

How do we certify API implementations?

Before a new merchant partner implementation can be given the go-ahead to launch, Viator must verify that each certification requirement is met. Certification may be conducted by:

  • The partner granting Viator access to their testing environment (recommended).
  • A comprehensive call between the partner’s developers and Viator’s technical onboarding team where each certification element is demonstrated.

When your implementation is ready for certification, please contact our API onboarding team.

The table below presents a high-level overview of the elements of your API implementation that must be certified before launch. Each element listed here will be covered in greater detail later in this guide.

appropriate endpoint usage

Rules for endpoint usage

If you have a specific use case which would, if implemented, violate any of the rules given below that describe appropriate endpoint usage, you must first seek approval from your Onboarding representative.

V1 API:

  • If a booking has been made, has availability been checked appropriately beforehand? This could be done with either /booking/availability/tourgrades or /booking/calculateprice. We recommend using the /booking/calculateprice endpoint for the final check, it’s the only endpoint that returns the total price (merchant net rate + transaction fee) pre-booking.
  • Language of service must be appropriately implemented for bookings based on data returned under langServices for each tourGrade in /product response.
  • If implemented, booking questions must be displayed to the customer with the relevant message (for example: “Enter passport number for all passengers”) and responses must be passed in the booking request.
  • The bookingStatus returned in the response to /booking/book service should be always verified prior to confirming the booking to the end customer. In case a timeout has been implemented for /booking/book service it should not be shorter than 120 seconds.

V2 API:

Product Ingestion

  1. Please do not attempt to ingest the full content of products with each ingestion run. You should ingest the full product catalogue once, and then ingest only updates (this reduces load on our systems and theirs and improves ingestion time for the partner) with the /products/modified-since endpoint. The more frequently this endpoint is called, the better as this way less data will be returned and the update will be much faster.
    The /products/{product-code} and /products/bulk/ endpoints should not be used for ingesting and updating the product catalogue unless you are ingesting products that haven’t been ingested before (for example, due to additional filtering rules on your end). The relevant endpoint serving this purpose is /products/modified-since.
  2. If you are an ingestion partner (storing our content in your local database), please ensure that tags and booking questions are cached. We suggest a periodic weekly update, unless a new tag or booking question is detected in the product content.

Availability Ingestion

  1. Similar to product ingestion, please ingest schedules for all products once and update from there on with the /availability/schedules/modified-since endpoint. The more frequently this endpoint is called, the better as this way less data will be returned and the update will be much faster.
  2. You should never use the availability real-time request ( /availability/check ) for ingestion purposes.
  3. If you are converting prices from our supplier currency into your desired currency using the exchange rate endpoints, you should call the exchange rate once per day based on the expiry timestamp to determine the rate and apply to all products priced in that currency (this greatly reduces the number of calls to our system).

Real-time Availability APIs

  1. You must check availability real-time (along with pricing) even if you have already ingested availability schedules. This is because the availability or price you ingest may become stale immediately after you ingest it (i.e. our supplier makes product unavailable or changes the price in the system after the ingestion took place).
  2. You must verify availability (real time) of a bookable item/ passenger-mix/travel date combination before a booking or booking hold request is made for that same bookable item / pax-mix / travel date. This is irrespective of the booking engine. a bookable item is what a customer actually purchases (i.e. the product or the product option or the start time – whichever is the lowest level on the product).
  3. Availability (real-time) requests should only be made when the customer has selected a date, passenger-mix and one of the following combinations:
    1. a product – returns availability for the product or production options and/or start times
    2. a product and a start time – returns availability for the product start time
    3. a product and an option – returns availability for the product option or the product option start times
    4. a product, an option and a start time – returns availability for the product option start time.

Each of the above serves a specific purpose in the UI. For example, if you want to list availability for all of the options and start times of any product, you would call availability for the product only which returns availability and pricing for all its options and start times. If you just want to check that a product start time the customer is booking is available, you would call availability using the product and start time as parameters. Using the right request for the right scenario is important to keep processing fast.

The request to /availability/check endpoint should be made with the currency in which you wish to be invoiced by Viator. This way you will be able to verify the final rate in that specific currency and avoid possible pricing discrepancies that could occur due to exchange rate fluctuations. This is especially important if you decided not to use the /exchange-rates endpoint.

Placing a Booking Hold

  • This endpoint holds price and inventory for x amount of time. x is defined by our supplier for inventory, and standard across all products for price.
  • This endpoint must only be called when there is strong intention from your customer to purchase. This means that it should be called immediately prior to the credit card payments being requested from the customer. This has two benefits:
    • it ensures the customer has time to enter details of the card without the risk of the inventory being sold out or the price changing.
    • it ensures that inventory is only held when there is a strong likelihood of a purchase, therefore not holding inventory that may otherwise be sold to someone else.
  • Booking hold must not ever be used for checking availability. It should be done after availability and pricing is verified in real-time with /availability/check endpoint.
  • Partner is responsible for verifying the timestamp returned under the validUntil field for pricing and availability in the response to /bookings/hold to ensure that the booking is made within the time of hold. A new hold can be placed only in case the previous hold expires.
Z

Checking Booking Status

  1. Booking Status should not be called more than once every 3 minutes, if partner supports manual confirmation products.

Locations

  1. When getting details of location references with /locations/bulk, please make sure to use no more than 500 location references in each request.
    Locations should be updated only on an on-demand basis, when a new location reference is returned in the product content response.

Suggested Best Practices

  • If you are wanting to exclude specific products, you can do so at the time of ingestion. That is, when ingesting products, you can simply assess if the product contains undesired attributes and simply discard the product (not store it).
  • You should only ingest schedules for the products you have ingested – that is, if you have excluded products from the product ingestion, you should not ingest availability for those. You can filter on ingestion by discarding information for products you are not interested in.
  • The bookingStatus field returned in the response to /bookings/book should be always verified prior to confirming the booking to the end customer. In case a timeout has been implemented for /bookings/book service it should not be shorter than 120 seconds.
secure checkout

HTTPS

Your platform must have a valid HTTPS security certificate during all stages of the checkout process. For the purposes of certification, the checkout process is defined as any part of the booking journey in which customer data is handled.

Z

Requirements

  1. All stages of the checkout process must have a valid HTTPS security certificate.

Best practices

  1. Your entire tours and activities platform is recommended to have a valid HTTPS security certificate.
protected seo content

Protected SEO content

The merchant API grants pre-approved partners access to Viator’s protected SEO content. Any protected SEO content you choose to display must not be allowed to be indexed by search engines.

Z

Requirements

  1. Content from the following endpoints must be non-indexed:
  2. Content retrieved from the viatorUniqueContent object via a product content endpoint must must not be indexable by search engines.
appropriate use of branding

Appropriate use of branding

A traveler will book tours or activities through your organization and must be assisted through your customer service processes. To avoid confusion, Viator branding must not be present on your platform.

Z

Requirements

  1. No Viator branding or mention of Viator may be included on your platform apart from the booking vouchers returned by the API.

Managing product and availability ingestion

The merchant API allows for two general approaches to managing products and availability. Ingestion partners use the API to build a local database of Viator product content and availability schedules, then use this database to power their experiences platform. Search partners do not store products and availability locally, but use data retrieved directly from our search endpoints to power their platform.

If you are an ingestion partner, you must ingest and periodically refresh local databases of Viator’s product catalogue and availability schedule information. The API offers two modified-since endpoints for content ingestion: /products/modified-since will return product content, and /availability/schedules/modified-since will return availability and schedules.

Our instructions in this guide assume that you are using the modified-since endpoints to manage content ingestion, as this is by far the most efficient method. However, it should be noted that the following endpoints may also be used to return product and availability data:

Note: Ingesting and refreshing product and availability content will follow the same conventions. It is important that product ingestion and availability ingestion be performed as separate processes, as nextCursor elements are not compatible between the two endpoints.

Ingesting Viator’s complete product and availability catalogue

1

Make a request to the /products/modified-since or /availability/schedules/modified-since endpoint, with no values supplied for the modified-since or cursor parameters.

GET https://api.sandbox.viator.com/partner/products/modified-since?count=500
{

“products”: [

{},

],
“nextCursor”: “MTU3NDA0MzU1NQ==”

}

2

Make a subsequent request to the endpoint, with the cursor parameter set to the value of the nextCursor element returned by your previous request.

https://api.sandbox.viator.com/partner/products/modified-since?count=500&cursor=MTU3NDA0MzU1NQ==
{

“products”: [

{},

],
“nextCursor”: AJKSHDJKKJhaskaSJHK==

}

3

Continue to make requests with the cursor parameter set to the value of the nextCursor element returned by the previous request. Eventually, a request will return no data in the products element, and will not include a nextCursor value. This indicates that all products have been returned. To optimize ingestion time, we recommend setting the count parameter to it’s maximum value of 500 for each request.

Refreshing your local product and availability catalogue

1

Make a request to the /products/modified-since or /availability/schedules/modified-since endpoint, with the cursor parameter set to the value of the most recent nextCursor element returned by a request to the same endpoint. This value may be found in the response to your second to last such request.

2
Continue to make requests with the cursor parameter set to the value of the nextCursor element of the previous request, until a request again does not include a nextCursor value.
3

To periodically refresh your database, repeat steps one and two in a regular cadence.

Guidelines for ingesting auxiliary data

To filter your inventory and to manage certain display elements, you may choose to ingest additional data through our supplemental endpoints. Our recommended best practices for how often to refresh your cached data from our supplemental endpoints are as follows:

  • /products/tags: Refresh after each product ingestion cycle
  • /products/booking-questions: Refresh weekly at a set time
  • /locations/bulk: Rrefresh after each product ingestion cycle if new locations are identified, otherwise refresh on a monthly basis
  • /reviews/product: Refresh after each product ingestion cycle only when the total review count has changed for the product, otherwise refresh on a weekly basis (with the limit of 30 requests per minute)
Z

Requirements

  1. After you ingest all product content and availability schedules, do not attempt to re-ingest the full catalogue on each ingestion cycle. This will reduce the load on our systems, and improve your ingestion time.

  2. Do not schedule product and availability ingestion cycles at a cadence higher than once hourly.

  3. Never use /availability/check to ingest schedules or future availability. This endpoint may only be used to check live availability on a per-product basis once a passenger mix and travel date have been selected.
  4. If you are converting prices from our supplier’s currency into your desired currency, limit requests to the /exchange-rates endpoint to once daily. These conversion rates should be applied to all products in the specified currency until the next refresh cycle.

Best practices

  1. Schedule each product and availability ingestion cycle for one hour after the previous cycle has been completed.

  2. If you would like to exclude certain products or product types, you can do so at the time of ingestion. When ingesting products, assess whether the product contains undesired attributes and discard the product (do not store it).

  3. You should only ingest schedules for the products you have ingested – that is, if you have excluded products from the product ingestion, you should not ingest the availability schedules for those products. You can filter on ingestion by discarding information for products you are not interested in.

cancellation policy

Cancellation policy

To certify your API implementation, we must confirm that your users will be made aware of a product’s cancellation policy before booking. Most Viator products offer a full refund if the booking is cancelled up to 24 hours before the start of the tour or activity.

As the merchant of record, you may adjust the cancellation policy you offer on Viator products, so long as your policy is stricter than Viator’s. For example, you may choose to offer no refund for a product with Viator’s standard cancellation policy, but you may not choose to offer a refund on a product with an all-sales-final policy. Learn more about cancellation policies or view our technical documentation

Displaying cancellation policy

1

Locate the cancellationPolicy object in the response from any of the product content endpoints.

2

Within the cancellationPolicy object, display the text in the description field to the user. If cancelIfBadWeather and/or cancelIfInsufficientTravelers are true, communicate this to your users (i.e. “this activity may be cancelled due to bad weather”).

“cancellationPolicy”: {

“type”: “STANDARD”,
“description”: “For a full refund, cancel at least 24 hours before the scheduled departure time.”,

“cancelIfBadWeather”: false,
“cancelIfInsufficientTravelers”: false,
“refundEligibility”: […]

},

Z

Requirements

  1. Cancellation policy must be communicated to the booker before purchase.

  2. Any non-Viator cancellation policy must be as strict or stricter than Viator’s policy.

Best practices

  1. Display cancellation policy in writing on the product detail page and on the checkout page.
age bands

Validating passenger mix

Tour operators place constraints on the number and age ranges of passengers allowed to book each product. Before you make a booking, you must ensure that the booker’s party consists of an acceptable combination of passengers and their respective age(s) for the product in question. This combination is referred to as the passenger mix.

Validating party requirements

1
Locate the bookingRequirements object in the response from any of the product content endpoints.
2

Using the minTravelersPerBooking and maxTravelersPerBooking fields as reference, set upper and lower bounds on the total number of travelers your users may input when booking this product. The total number of travelers refers to the total number of travelers across all ageBands.

3
If requiresAdultForBooking is true, at least one traveler with the ADULT or SENIOR ageBand must be included in the passenger mix.
“bookingRequirements”: {

“minTravelersPerBooking”: 1,
“maxTravelersPerBooking”: 15,
“requiresAdultForBooking”: false

},

Z

Requirements

  1. Users must not be able to input a total number of travelers greater than the maxTravelersPerBooking value, or less than the minTravelersPerBooking value.
  2. If requiresAdultForBooking is true, users must not have the option to create a booking without an adult or senior traveler present.

Best practices

  1. Communicate the maximum and minimum travelers to the user. For example: “This experience is bookable by 2-15 travelers.”

  2. If an adult or senior traveler is required, communicate this to the user. For example: “At least one adult or senior per party.”

  3. Do not include the option to select invalid passenger mixes. From a UX perspective, preventing your users from selecting invalid mixes at all is preferable to displaying error messages.

Validating age bands

1
Locate the ageBands array, found in the pricingInfo object in the response from any of the product content endpoints.
2
The ageBands array will contain information on the particular age bands this product offers. For each individual ageBand, use the startAge and endAge fields to communicate the appropriate age range to the user. For example, an ADULT ageBand with a startAge of 18 and an endAge of 60 may be displayed as “Adult (18-60).” The age range specified for a given ageBand is set by the tour operator and will vary between products, so this process must be performed on a per-product basis.
3

For each individual ageBand, refer to the minTravelersPerBooking and maxTravelersPerBooking fields to set upper and lower bounds on the number of travelers of that ageBand. The minTravelersPerBooking and maxTravelersPerBooking fields in the pricingInfo object must not be confused with the fields of the same name in the bookingRequirements object.

Note: The ageBand for products with per-unit pricing will always be TRAVELER.

“pricingInfo”: {

“type”: “PER_PERSON”,
“ageBands”: [

{
“ageBand”: “ADULT”,
“startAge”: 18,
“endAge”: 60,
“minTravelersPerBooking”: 0,
“maxTravelersPerBooking”: 9
},

]

},

Z

Requirements

  1. Partners must select the appropriate ageBand for each booker, based on the age of the traveler.
  2. Users must not be able to input a total number of travelers greater than the maxTravelersPerBooking value, or less than the minTravelersPerBooking value specified for each individual ageBand.

Best practices

  1. Avoid excluding products with specific age bands, as this will significantly limit your available inventory.

  2. Collect age bands on the product detail page, just before displaying tour options.

booking items

Validating bookable items

Products may consist of multiple variants of the tour or experience, such as varying start times and/or product-options. You must ensure that when making a booking, your users may only specify a start time and/or product option that is valid for the product in question. This grouping is referred to as a bookable item. Bookable items are used to check availability and to create bookings.

Displaying product options

1
Determine whether the productOptions array is present in the response from any of the product content endpoints. If no productOptions array is present, the product does not include product options.
2
Referencing the fields in the productOptions array, display the title and description of each productOptionCode, as well as any languageGuides (type and language) specific to the relevant porductOptionCode object. If the user chooses to book this product, a valid productOptionCode must be specified in the /bookings/book request. Typically, this information is displayed to users once they select a passenger mix and a date.
“productOptions”: [

{

“productOptionCode”: “1045AMSBWT”,
“description”: “Pickup included”,
“title”: “Small Airboat with Pickup”,
“languageGuides”: [

{

“type”: “GUIDE”,
“language”: “en”,
“legacyGuide”: “en/SERVICE_GUIDE”

}

]

},

Displaying start times

1

Locate the bookableItems.seasons.pricingRecords.timedEntries array in the response from any of the availability schedules endpoints. This array will include all data on start times and availability for a product; or, if available, its product options.

2
Display each available startTime field in the timedEntries array. If a startTime is specific to a productOptionCode, be sure to display this time as a choice within the product option.

“bookableItems”: [

{

“productOptionCode”: “TG2”,
“seasons”: [

{

“startDate”: “2021-05-30”,
“endDate”: “2021-12-31”,
“pricingRecords”: [

{

“daysOfWeek”: [

“MONDAY”,
“TUESDAY”,

],
“timedEntries”: [

{

“startTime”: “17:00”

},
{

“startTime”: “09:00”

},

],

}

]

}

]

}

Z

Requirements

  1. Bookable items must be displayed accurately, and must be selected by the user prior to any /availability/check or /bookings/hold requests.
real time availability

Checking real-time availability and pricing

Before you make a booking, you must use the /availability/check endpoint to verify that the bookable item is still available for your user’s desired date and passenger mix. This is because the availability or price you ingest for a product might have changed immediately following ingestion; for example, if the product’s supplier happens to change its price or availability in the interim.

Requesting real time availability and pricing

1

Determine the bookable item(s) for the product, and collect one of the following combinations (a bookable item):

  1. The product code (productCode)
  2. The product code, and the user’s desired start time (productCode and startTime)
  3. The product code, and the user’s desired product option (productCode and productOptionCode)
  4. The product code, the user’s desired valid start time, and the user’s desired product option (productCode, startTime, and productOptionCode)

Each of the above combinations serves a specific purpose in the UI. For example, if you would like to list the availability of all product options and start times for a product, you would only include the productCode. If you just need to check whether the start time requested by the customer is available, you should include productCode and startTime. To keep processing fast, it is important to choose the right request for each scenario.

2

Collect the desired date and the passenger mix for your user. Valid dates for a product can be retrieved from any of the /availability/schedules/ endpoints, and valid passenger mixes for a product can be retrieved from any of the product content endpoints.

3

Make a request to the /availability/check endpoint. In the request body, include the following parameters: the product code (productCode), a valid date of travel (travelDate), a valid passenger mix (paxMix), and your desired currency (currency). If necessary for the product in question, include a valid start time (startTime), and/or a valid product option(productOptionCode).

{

“productCode”: “5713P109”,
“startTime”: “10:00”,
“travelDate”“2020-12-12”,
“currency”: “AUD”,
“paxMix”: [

{
“ageBand”: “ADULT”,
“numberOfTravelers”: 2
},
{
“ageBand”: “INFANT”,
“numberOfTravelers”: 1
}

]

}

Z

Requirements

  1. To ensure a product is available and you’re selling it at the correct price, real-time availability and pricing of a bookable item must be verified prior to booking. This step must be carried out; it is not sufficient to rely on previously-ingested availability and pricing schedule data at this point in the booking workflow.
  2. Calls to the real-time availability endpoint for a product must only be made after the customer has selected a bookable item. Real-time availability requests must not be used to populate schedules or calendar views.

Best practices

  1. In general, the real-time availability check should be made immediately prior to presenting the user with the option to purchase the item. This minimizes the possibility that the customer will attempt to proceed to the payment page only to find that the bookable item is no longer available.
identifying booker

Identifying the booker

When making a booking, you must specify the name of the person making the booking. The booker’s name will appear on the voucher, and is generally the same person who makes the payment. In previous versions of our API, this person was referred to as the ‘lead traveler’.

Instructions

1

On the checkout screen, collect the first and last name of the booker. When making a bookings/book request, this information must be used to populate the firstName and lastName fields in the bookerInfo object. Make sure that the booker fields to collect the booker’s name are differentiated from those for other travelers.

“bookerInfo”: {

“firstName”: “Jon”,
“lastName”: “Edel”

},

Z

Requirements

  1. For each booking, collect the first and last name of the booker, and include this information in the /bookings/book request.

Best practices

  1. If possible on your platform, collect the booker’s information at checkout, rather than earlier on in the user journey.
booking questions

Booking questions

Some Viator products require the traveler(s) to provide information to the tour operator at the time of booking. For example, a museum tour may need the names and ages of each traveler, or a helicopter excursion may need the weights of each traveler. The information is collected via booking questions that the user must answer during checkout.

Displaying booking questions

1

Make a request to the /products/booking-questions endpoint. The response will contain a flat list of all booking questions, including each question’s machine-readable identifier, plain text for display to the user, and parameters for acceptable answers. This data is mostly static and may be stored locally, but we recommend it be refreshed weekly; or ad hoc if an unknown booking question is encountered.

2
In the product data returned by any of the product content endpoints, locate the bookingQuestions array. This array will contain the id of each booking question for this product.
3

Validate each id returned in the bookingQuestions array of the product content response against the corresponding id in the response from the /products/booking-questions endpoint. On the checkout page, display the label text for each question listed in the product data, and collect the appropriate response from the user before booking.

Note: For complete details on each individual booking question, please consult our documentation.

“bookingQuestions”: [

{

“legacyBookingQuestionId”: 1,
“id”: “DATE_OF_BIRTH”,
“type”: “DATE”,
“group”: “PER_TRAVELER”,
“label”: “Date of birth”,
“required”: “MANDATORY”,
“maxLength”: 100

},

]

Z

Requirements

  1. Products with booking questions require valid answers to those questions to be submitted in the request to /bookings/book. The answers must be collected from the customer at the time of checkout.

  2. Booking questions must be displayed and managed in accordance with our documentation. Questions classified as ‘mandatory’ must be answered , and each answer must adhere to the requirements detailed in the respective booking question object.

Best practices

  1. Do not exclude products with booking questions, as this practice will significantly limit your available inventory and revenue opportunity.
traveler pickup

Traveler Pickup

Some tours and activities offer traveler pickup, which is managed via booking questions. Pickup locations may be selected from a list of preset locations, or may be input by the traveler.

Instructions

1
In the product data returned by any of the product content endpoints, locate the bookingQuestions array, and determine whether “PICKUP_POINT” is listed. If this question is present, the product in question offers pick-up services. If a product includes the “PICKUP_POINT” booking question, proceed to the next step.
2
Users may select a pickup location from the list of options in the logistics.travelerPickup.locations array in the product data. These options should be displayed as a dropdown list.

Note: The locations array will include location references, which must be resolved before they are displayed to the user. For guidance on working with location references, please refer to our documentation.

3

If the logistics.travelerPickup.allowCustomTravelerPickup boolean in the product data is true, the user may specify their own pickup point. This should be displayed as an additional option, which, if selected, will allow the user to input their own freetext answer.

{

“legacyBookingQuestionId”: 6,
“id”: “PICKUP_POINT”,
“type”: “LOCATION_REF_OR_FREE_TEXT”,
“group”: “PER_BOOKING”,
“label”: “Hotel pickup”,
“hint”: “E.g. 1234 Cedar Way, Brooklyn NY 00123”,
“units”: [

“LOCATION_REFERENCE”,
“FREETEXT”

],
“required”: “MANDATORY”,
“maxLength”: 1000

}

Z

Requirements

  1. Where applicable, options for traveler pickup options must be offered as part of the appropriate booking question at checkout.
making a booking

Making a booking

As a merchant partner, the API enables you to use the /bookings/book endpoint to book Viator products. Because it is possible to create an invalid booking, it is important to validate all booking data before creating a booking.

As part of the booking process, we recommend you use the /bookings/hold hold endpoint to place a temporary hold on price and inventory before making any bookings. A booking hold must only be placed immediately prior to the user making the purchase. This has two benefits:

  • it ensures the customer has time to enter details of the card without the risk of the inventory being sold out or the price changing.
  • it ensures that inventory is only held when there is a strong likelihood of a purchase, therefore not holding inventory that may otherwise be sold to someone else.

As part of certification, Viator will request that you make a test booking to confirm that your platform is able to appropriately capture and share the booking voucher with the traveler. We also strongly recommend making test bookings to test the validation for each certification element listed above.

To help you with testing, please use this list of products for reference:

  • Instant confirmation: 100337P2
  • Manual confirmation: 11612P1
  • Single tour grade: 100427P4
  • Multiple tour grades: 5836DINNERCRUISE
  • Age band requirements: 3858EE021
  • Booking questions: 5516ST5
  • Hotel pick-up: 10132P16
  • Minimum of 2 travelers: 75909P603
  • Limited availability: 22710P11
  • Standard cancellation policy: 3991MB_ATVM
  • Custom cancellation policy: 40944P355
  • All sales final cancellation policy: 6479UY1DAY

Important: A live booking must never be performed for test purposes, and will be invoiced along with other live bookings. All test bookings should be made in the sandbox environment.

booking workflow

Instructions

Note: These instructions assume that all data provided in /bookings/book and /bookings/hold hold requests has been validated in accordance with the requirements outlined on this page.

1

Select a product to book. You may refer to the above list of products, or any select Viator product with availability.

2
Make a /bookings/hold request (recommended). This request body must include the following parameters: product code (productCode), desired currency for pricing information (currency), date of travel (travelDate), and passenger mix (paxMix). Depending on the product, you may need to include the product option (productOptionCode) and/or the start time (startTime).
POST https://api.sandbox.viator.com/partner/bookings/hold

{

“productCode”: “12546DOUROVALLEY”,
“productOptionCode”: “TOURANDBOAT”,
“travelDate”: “2021-10-01”,
“currency”: “EUR”,
“startTime”: “08:30”,
“paxMix”: [

{
“ageBand”: “ADULT”,
“numberOfTravelers”: 1
}

]

}

3

Make a /bookings/book request. The request body for this request must include the same parameters as the request body of the appropriate /bookings/hold request, otherwise the booking will be rejected. The request body of all booking requests must must include the Viator booking reference returned by the /bookings/hold request (bookingRef), a partner-generated reference number for internal use (partnerBookingRef), the first and last name of the person making the booking (bookerInfo object), and the contact info of the person making the booking (communication.phone, optionally communication.email).

In addition, the following objects may be required, depending on the product in question: languageGuide, bookingQuestionAnswers, and optionally additionalBookingDetails.

POST https://api.sandbox.viator.com/partner/bookings/book

{

“productCode”: “12546DOUROVALLEY”,
“productOptionCode”: “TOURANDBOAT”,
“currency”: “EUR”,
“partnerBookingRef”: “BR-555555555”,
“travelDate”: “2020-11-30”,
“paxMix”: [

{
“ageBand”: “ADULT”,
“numberOfTravelers”: 1
}

],
“languageGuide”: {

“type”: “AUDIO”,
“language”: “en”,
“legacyGuide”: “en/SERVICE_AUDIO”
},

“bookingRef”: “BR-555555555”,
“bookerInfo”: {

“firstName”: “Jon”,
“lastName”: “Edel”

},
“bookingQuestionAnswers”: [

{
“question”: “SPECIAL_REQUIREMENTS”,
“answer”: “NO”,
“travelerNum”: 1
}

],
“communication”: {

“email”: “jedel@tripadvisor.com”,
“phone”: “5555555555”

},
“additionalBookingDetails”: {

“voucherDetails”: {

“companyName”: “Viator”,
“email”: “affiliateapi@viator.com”,
“phone”: “5555555555”,
“voucherText”: “Enjoy your adventure!”

}

}

}

4

If the booking in question was for a manual confirmation product, a /bookings/status request must be made to confirm whether the booking has been accepted by the tour operator. This request should be made periodically until the booking is either confirmed or rejected, throughout the 72 hour window following the bookings/book request. When making a /bookings/status request, include either the bookingRef or the partnerBookingRef returned by the relevant /bookings/book request.

{

“BookingRef”: “BR-555555555”

}

Z

Requirements

  1. A /bookings/hold request may not be made until the user has indicated a high intent to book. Typically, this means that it may not be called until immediately prior to the user entering their payment details.

  2. A /bookings/hold request must never be used to check product availability.

  3. All data included in a booking request (passenger mix, travel date, booking questions, etc.) must be validated for the product in question before a /bookings/hold or a /bookings/book request is made.

  4. A /bookings/status request must not be made more than once every three minutes, per booking.

Tickets_Passes

Voucher access

To ensure that our tour operators honor partner bookings, the traveler must present a voucher which is compatible with the tour operator’s processes, meaning that upon booking, the traveler must receive a standard Viator voucher. The voucher given to the traveler must be unmodified, appearing as it does when returned by the API request, and may not be customized in any way. Please note that custom vouchers with the link to access the Viator voucher will not be accepted. Further, the traveler must be informed what type of voucher the operator accepts: mobile, paper, or both

Displaying voucher type:

1
Locate the ticketInfo object in the response from any of the product content endpoints.
2
Within the ticketInfo object, display the text in the ticketTypeDescription and ticketsPerBookingDescription fields to the user.
“ticketInfo”: {

“ticketTypes”: [

“MOBILE_ONLY”

],
“ticketTypeDescription”: “Mobile or paper ticket accepted”,
“ticketsPerBooking”: “ONE_PER_BOOKING”,
“ticketsPerBookingDescription”: “One per booking”

},

Accessing the voucher:

1

Make a valid booking using the /bookings/book endpoint. When making your request, you may customize some textual elements of the voucher via the fields in the voucherDetails object of the request body.

Note: You may choose to include the logo of your organization on vouchers. This is managed by Viator at the account level, so please contact our API onboarding team for assistance with this feature.

2
Once the booking has been made, provide the traveler access to the voucher returned in the voucherInfo object of the response. You may do this by sharing the link directly with your traveler, or by embedding the voucher into your platform.
“voucherInfo”: {

“url”: “https://shop.live.rc.viator.com/ticket?code=1006658118:1176d4aed0e88ffec7faf11e67183edc0cd40d5b5244b30b0cd08aab14f72b4b”,
“format”: “HTML”

}

Z

Requirements

  1. After a booking is made, the traveler must be able to access an unmodified voucher.

  2. The accepted type(s) of voucher must be communicated to the traveler.

Best practices

  1. The traveler should be able to access their voucher(s) through the booking confirmation email sent by the partner, or when they log in to their account.
  2. Accepted voucher types should be indicated on the product detail page.
certifying cancellation process

Certifying your cancellation process

Most Viator products offer a full or partial refund when cancelled by the booker. Cancellations should be managed by the partner, via the /bookings/{booking-reference}/cancel endpoint.

This check differs from the other elements of certification in that it must be done in the live environment, using your production API key. This means that this check will be the last step before launching our partnership commercially.

Important: Outside of this certification check, a live booking must never be performed for test purposes, and will be invoiced along with other live bookings. All test bookings should be made in the sandbox environment.

Instructions

1

Select a product with future availability, and with Viators standard cancellation policy.

2

Using your production API key, make a valid booking using the /bookings/book endpoint. Be sure to select a date more than 24 hours in the future.

Note: When working in the production environment, https://api.viator.com/partner/… should replace https://api.sandbox.viator.com/partner/… for all endpoints.

3

Using the /bookings/{booking-reference}/cancel endpoint, cancel the booking.

4

Share the booking reference for the cancelled booking with our onboarding team. Viator will confirm that booking data is correctly remitted to your invoice, and will reply with approval to launch (if booking data is correctly remitted), or next steps (if an error is detected).

Z

Requirements

  1. The above booking and cancellation must be performed prior to launch. If a partner enters commercial production without completing this certification check, Viator can not guarantee that refunds will be honored.

Did you find this article useful?