openapi: 3.2.0 info: title: Viator Partner Payments API description: "\n\n## Updates\n\n### Latest updates: \n\n| Date | Description |\n|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| 5 May 2026 | Added support for product option level logistics resolution via a new optional `logistics` object. |\n| 13 Feb 2025 | Added `videos` object to [/products/{product-code}](#operation/products), [/products/modified-since](#operation/productsModifiedSince), [/products/bulk](#operation/productsBulk), [/products/search](#operation/productsSearch) and [/search/freetext](#operation/searchFreeText) responses. |\n| 4 Feb 2025 | Added `AED`, `ARS`, `CLP`, `CNY`, `COP`, `FJD`, `IDR`, `ILS`, `ISK`, `KRW`, `MXN`, `MYR`, `PEN`, `PHP`, `PLN`, `RUB`, `THB`, `TRY` and `VND` as currency options in the request to [/products/search](#operation/productsSearch) and [/search/freetext](#operation/searchFreeText). \n| 11 Sep 2025 | Updated [/bookings/modified-since](#operation/bookingsModifiedSince) response with new `eventTypes` and enabled endpoint access to all partner types. \n| 01 Jul 2025 | Added [/amendment/check/{booking-reference}](#operation/amendmentCheck), [/amendment/quote](#operation/amendmentQuote) and [/amendment/amend/{quote-reference}](#operation/amendmentAmend) endpoints to [Bookings](#tag/Bookings) section \n| 27 Mar 2025 | Update [/search/freetext](#operation/searchFreeText) request section add filtering by tags for \"searchType\": \"PRODUCTS\" \n| 20 Mar 2025 | Added [/products/recommendations](#operation/productsRecommendations) to [Products](#tag/Products) section. This endpoint will provide product-to-product recommendations to users. |\n| 19 Mar 2025 | Updated endpoints [/availability/schedules/{product-code}](#operation/availabilitySchedules), [/availability/schedules/bulk](#operation/availabilitySchedulesBulk), [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince), [/availability/check](#operation/availabilityCheck), [/search/freetext](#operation/searchFreeText), [/products/search](#operation/productsSearch), [/bookings/cart/hold](#operation/bookingsCartHold) and [/bookings/hold](#operation/bookingsHold) as well as [Inclusions & exclusions](#section/Appendices/Inclusions-and-exclusions) with `Extra Charges` information |\n| 11 Feb 2025 | Removed `TRANSACTION_NOT_ALLOWED`, `CARD_INACTIVE` and `CARD_RESTRICTED` rejection reasons from [/bookings/cart/book](#tag/Bookings/operation/bookingsCartBook). |\n| 4 Dec 2024 | Updated [/bookings/cart/book](#tag/Bookings/operation/bookingsCartBook) response with the following new rejection reason: `PROCESSOR_ISSUE_WITH_PAYMENT`. |\n| 19 Nov 2024 | Updated [/bookings/cart/book](#tag/Bookings/operation/bookingsCartBook) response with the following new rejection reasons: `SUSPECTED_FRAUD`, `SOFT_DECLINE`, `HARD_DECLINE`, `THREE_D_SECURE_REQUIRED`, `INTERNAL_ERROR`, `PROCESSOR_UNAVAILABLE`. |\n| 24 Oct 2024 | Deprecated [/v1/product/photos](#operation/v1ProductPhotos) endpoint |\n| 23 Oct 2024 | Added [/attractions/search](#operation/attractionsSearch) and [/attractions/{attraction-id}](#operation/attractions) to [Attractions](#tag/Attractions) section
Added [/destinations](#operation/destinations) to [Auxiliary](#tag/Auxiliary) section
Updated [Access to endpoints](#section/Access-to-endpoints) section to include new endpoints and removed the ones marked for deprecation
Updated [Resolving references](#section/Workflows/Resolving-references) section |\n| 21 Oct 2024 | Removed `VIATOR_EXCLUSIVE` flag from product search endpoints |\n| 1 Oct 2024 | Removed COVID-19 safety attributes from `AdditionalInfo` schema (part of product content response; e.g., from [/products/{product-code}](#operation/products) endpoint) |\n| 6 Aug 2024 | Changes to behaviour with `DEFAULT` tour grade for product, availability, book hold and confirm endpoints. See note at end of section [Product Option Code](#section/Key-concepts/Product-options). Note: these changes are backwards compatible. |\n| 29 Jul 2024 | Updated [/bookings/modified-since](#operation/bookingsModifiedSince) response with new eventType: CUSTOMER_CANCELLATION, for Customer initiated cancellations. |\n| 14 Mar 2024 | Updated [/bookings/cart/book](#tag/Bookings/operation/bookingsCartBook) response with the following new rejection reasons: `INSUFFICIENT_FUNDS`, `INVALID_PAYMENT_DETAILS`, `TRANSACTION_NOT_ALLOWED`, `CARD_INACTIVE` and `CARD_RESTRICTED`.
Updated [/bookings/status](#tag/Bookings/operation/bookingsStatus) response with `ON_HOLD` status |\n| 13 Feb 2024 | Updated [/suppliers/search/product-codes](#operation/suppliersSearchProductCodes) with the following new attributes: `supplierAgreedToLegalCompliance`, `registrationCountry`, `tradeRegisterName` and `registeredBusinessNumber`. Also updated the `ContactDetails` schema with a new attribute `countryCode`. |\n| 11 Sep 2023 | Added support for PDF vouchers. Made bookerInfo firstName required to match definition. |\n| 5 Jul 2023 | Added [/bookings/cart/hold](#operation/bookingsCartHold) and [/bookings/cart/book](#operation/bookingsCartBook) to [Bookings](#tag/Bookings) section
Added [/v1/checkoutsessions/{sessionToken}/paymentaccounts](#operation/paymentsCreateToken) to [Payments](#tag/Payments) section |\n| 15 May 2023 | Modified [Accept-Language-header-parameter](#section/Localization/Accept-Language-header-parameter) section to accurately reflect currently allowed values |\n| 16 Mar 2023 | Added [/search/freetext](#operation/searchFreeText) and [/suppliers/search/product-codes](#operation/suppliersSearchProductCodes) to [Access to endpoints](#section/Access-to-endpoints) section |\n| 6 Mar 2023 | Added Canadian dollars (CAD) as currency option in request and response to [/bookings/hold](#operation/bookingsHold), [/bookings/book](#operation/bookingsBook) and [/bookings/status](#operation/bookingsStatus) endpoints |\n| 6 Jan 2023 | Added two new COVID-19 safety attributes to `AdditionalInfo` schema (part of product content response; e.g., from [/products/{product-code}](#operation/products) endpoint) |\n| 4 Jan 2023 | Updated or created `ProductSearchFiltering`, `ProductSummary`, `ProductSearchSorting`, `ProductSearchFlag`, `TranslationDetails`, `SearchDurationInfo` and `SearchRatingInfo` schemata for the [/products/search](#operation/productsSearch) endpoint request/response, updated example request and merchant and affiliate response examples, and updated [Postman collections](#section/Testing/Postman-collections-for-testing) in line with these changes |\n| 3 Jan 2023 | Updated example request and response for [/search/freetext](#operation/searchFreeText) endpoint |\n| 12 Dec 2022 | Added [/search/freetext](#operation/searchFreeText) endpoint |\n| 10 Nov 2022 | Updated [/bookings/hold](#tag/Bookings/operation/bookingsHold) and [/bookings/modified-since/acknowledge](#tag/Bookings/operation/bookingsModifiedSinceAcknowledge) descriptions |\n \n\n\n### Update history: \n\n- All significant modifications made to this document since its creation can be found in the [Update history](#section/Appendices/Update-history) section.\n\n# Support\n\n## Onboarding / integration\n\nIf you require help or technical advice while you are carrying out your integration, please contact the onboarding team via email at: affiliateapi@tripadvisor.com\n\n### Integration guides\n\nOur onboarding specialists have put together [in-depth guides](https://partnerresources.viator.com/travel-commerce/implementation/?source=specs) covering various topics to help you during your integration. \n\n### Site certification for merchant partners\n\nIf you are a merchant partner, once your API integration has been completed, it must pass certification prior to going live in order to ensure data integrity and the appropriate use of API services. Please peruse and bear in mind [our certification requirements](https://partnerresources.viator.com/travel-commerce/merchant/certification/?source=specs) prior to and during development.\n\n## Operational support\n\nIf are a merchant partner, have completed your integration and your site is operational, please see the [Partner Help Center - Merchant partner support](https://partnerhelp.viator.com/en/categories/37-merchant-partner-support?source=specs) page for information about what to do if you encounter a problem and require support.\n\n# About\n\n## Viator Partner-API v2\n\n### What is it?\n\nThe Viator Partner API v2 comprises a set of endpoints that can support the operation of a fully-featured tours and experiences booking website or application; or, it can be integrated with your existing travel-booking software.\n\nThe API exposes a variety of services that allow the retrieval of all product details, such as descriptive text and structured metadata, pricing, terms and conditions, photos and reviews. This data can either be ingested and managed on your local system, or calls can be made in real time to retrieve content in response to your users' activity on your systems.\n\nThe API allows product content, pricing and availability data to be retrieved in bulk or queried in real-time, it can perform pricing calculations according to the number and type of traveler and product option combinations available, and it supports availability and pricing holds as part of its booking and booking-cancellation functionality. \n\n### Who is it for?\n\nThe Viator Partner-API is a designed for use by organizations partnered with Viator as [Affiliate partners](https://partnerresources.viator.com/travel-commerce/affiliate/) or [Merchant partners](https://partnerresources.viator.com/travel-commerce/merchant/).\n\n#### Affiliate partners\n\n\nAffiliate partners have full access to the areas of the API relating to content, but sales of Viator products must be carried out on the Viator site itself. \n\nWhen a customer wishes to book a product from an affiliate's site, they are instead redirected to the relevant product page on [viator.com](https://viator.com) via a unique URL in order to complete the purchase. Once on the Viator site, a cookie is set such that all transactions will accrue a commission for that partner until the cookie expires.\n\nPurchases of products originating from the affiliate's site are recorded and a commission on these sales is paid periodically.\n\nFor more information on this partner type, see: [Viator's Affiliate API Solution](https://partnerresources.viator.com/travel-commerce/affiliate/)\n\n#### Merchant partners\n\nThe merchant partner relationship is one in which the partner is the **merchant of record**; i.e., the partner takes full responsibility for all financial records and transactions carried out by their users, as well as providing customer support with regard to providing general assistance, processing cancellations and refunds, and liaising between suppliers and customers when the need to communicate arises.\n\nFor more information on this partner type, see: [Viator's Merchant API Solution](https://partnerresources.viator.com/travel-commerce/merchant/)\n\n\n## New features in this version\n\nThe Viator Partner-API v2.0 is a fully-redesigned system with regard to our previous API products. It includes all key fuctionality available in previous versions, but now provides nearly fully-structured data elements, and a more modern, concise and easily-understandable interface.\n\nIn addition, we have made significant improvements to performance across all functions of the API, and particularly in the area of product content and availability data ingestion.\n\n### Simplified and optimized data ingestion \n\nData ingestion has been greatly improved over previous versions of this API. Now, partners need only perform a single initial ingestion of data; then, only new and updated product content, availability and pricing information is retrieved as a 'delta update' as it becomes available.\n\nIn addition:\n- A single end-point allows both bulk ingestion and delta updates, which can be controlled using a pagination cursor or with a time-stamp parameter to allow for point-in-time ingestion of any new updates and easy recovery from ingestion failure\n- The structure of a product's pricing and availability schedules has been simplified to reduce response size\n\n#### Product content\n\n- All pricing is standardized to the supplier's currency, avoiding the need to update on account of exchange rate fluctuations \n- Structured location, tag, booking question, review and photo data is available from separate endpoints to allow for parallel ingestion, and resusable data can be ingested once and applied globally\n\n#### Availability schedule information\n\nImprovements to availability schedule ingestion performance and usability have been achieved:\n\n- Availability is now communicated by providing an overall schedule season and specifying *unavailable* dates instead of available dates, a significantly more compact format that improves transfer speeds and minimizes storage needs \n\n- Availability and pricing information is given on a days-of-the-week basis, which can help with filtering and improving visibility of product availability for customers.\n\n- Information about special pricing periods that may be running throughout a product's seasons is included and is easy to interpret, allowing partners to surface promotions to customers.\n\n- Accurate pricing and applicability information for products that have 'per unit' (group) pricing is now included in the availability & pricing response; whereas support for this pricing model was limited in previous versions of this API. This allows partners to improve pricing exposure for these products.\n\n### Structure-rich content\n\nProviding structured content is a major focus of this API. Product information that was previously stored as natural-language descriptions in a single, lengthy field is now represented in intuitively-structured, machine-interpretable schemata that empowers partners to apply finely-grained merchandising control, including:\n\n- Tour itineraries with comprehensive location data to allow for graphical display and advanced search\n- Tour details, inclusions and dynamic health & safety information to support changing requirements due to global pandemic response initiatives\n- Machine-parseable booking questions and answers\n\n### Improved real-time availability and pricing checking\n\nThe [real-time availability check endpoint](#operation/availabilityCheck):\n- Allows you to check availability and pricing in real-time for a specific product / [product-option](#section/Key-concepts/Product-options) / date / starting time / pax mix combination\n- Returns the ticket availability status along with a pricing breakdown (by age band) and total price (all age bands) in a simplified format to reduce response size\n- Pricing components are stated explicitly, including the Recommended Retail Price (RRP), partner net price, special-offer pricing and booking fee component details\n\n### Improved booking workflow\n\nThe [booking workflow](#section/Booking-concepts/Making-a-booking) now includes an optional booking-hold step, which allows you greater predictability of a successful booking, thereby increasing conversion rates by decreasing friction in the booking flow.\n\nThe [booking hold](#operation/bookingsCartHold) endpoint supports two kinds of hold:\n- Inventory/availability hold (increased likelihood of receiving a booking confirmation)\n- Pricing hold (mitigates against pricing changes at the time of booking)\n\nThe [real-time availability and pricing endpoint](#operation/availabilityCheck) also delivers \\~5% faster performance than previous versions of this API.\n\n# Access to endpoints\n\nThe API endpoints accessible to you depend on which kind of partner you are; affiliate or merchant. \n\n**Basic-access Affiliate partners** have access to a limited subset of the non-transactional endpoints of the Viator Partner API. The basic-access tier allows affiliates to quickly get started building their site with fewer complexities. The following step-by-step guide explains how to do it: [Golden Path – Basic Access Affiliate Partners](https://partnerresources.viator.com/travel-commerce/affiliate/basic-access/golden-path/?source=specs) \n\n**Full-access Affiliate partners** have access to all non-transactional endpoints; i.e., everything except booking, booking hold and booking cancellation endpoints. This access model applies equally to whitelabel partners.\n\n**Full-access + Booking Affiliate partners** have access to all the same endpoints as **Full-access Affiliate partners** as well as transactional endpoints. i.e., including cart booking, cart booking hold and booking cancellation endpoints.\n\n**Merchant partners** have access to all endpoints.\n\nThe following table describes which partner types have access to which endpoints:\n\n| Endpoint | Basic-access Affiliate | Full-access Affiliate | Full-access + Booking Affiliate | Merchant |\n|-----------------------------------------------------------------------------------------|:-----------------:|:----------------:|:------------:|:------------:|\n| [/products/modified-since](#operation/productsModifiedSince) | ❌ | ✅ | ✅ | ✅ |\n| [/products/bulk](#operation/productsBulk) | ❌ | ✅ | ✅ | ✅ |\n| [/products/{product-code}](#operation/products) | ✅ | ✅ | ✅ | ✅ |\n| [/products/tags](#operation/productsTags) | ✅ | ✅ | ✅ | ✅ |\n| [/products/booking-questions](#operation/productsSearch) | ❌ | ❌ | ✅ | ✅ |\n| [/products/search](#operation/productsSearch) | ✅ | ✅ | ✅ | ✅ |\n| [/products/recommendations](#operation/productsRecommendations) | ❌ | ✅ | ✅ | ✅ |\n| [/attractions/search](#operation/attractionsSearch) | ✅ | ✅ | ✅ | ✅ |\n| [/attractions/{attraction-id}](#operation/attractions) | ✅ | ✅ | ✅ | ✅ |\n| [/availability/check](#operation/checkAvailability) | ❌ | ✅ | ✅ | ✅ |\n| [/availability/schedules/{product-code}](#operation/availabilitySchedules) | ✅ | ✅ | ✅ | ✅ |\n| [/availability/schedules/bulk](#operation/availabilitySchedulesBulk) | ❌ | ✅ | ✅ | ✅ |\n| [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) | ❌ | ✅ | ✅ | ✅ |\n| [/bookings/cart/hold](#operation/bookingsCartHold) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/cart/book](#operation/bookingsCartBook) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/hold](#operation/bookingsHold) | ❌ | ❌ | ❌ | ✅ |\n| [/bookings/book](#operation/bookingsBook) | ❌ | ❌ | ❌ | ✅ |\n| [/bookings/status](#operation/bookingsBook) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/cancel-reasons](#operation/bookingsCancelReasons) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/{booking-reference}/cancel-quote](#operation/bookingsCancelQuote) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/{booking-reference}/cancel](#operation/bookingsCancel) | ❌ | ❌ | ✅ | ✅ |\n| [/bookings/modified-since](#operation/bookingsModifiedSince) | ✅ | ✅ | ✅ | ✅ |\n| [/bookings/modified-since/acknowledge](#operation/bookingsModifiedSinceAcknowledge) | ❌ | ❌ | ✅ | ✅ |\n| [/amendment/check/{booking-reference}](#operation/amendmentCheck) | ❌ | ❌ | ✅ | ✅ |\n| [/amendment/quote](#operation/amendmentQuote) | ❌ | ❌ | ✅ | ✅ |\n| [/amendment/amend/{quote-reference}](#operation/amendmentAmend) | ❌ | ❌ | ✅ | ✅ |\n| [/v1/checkoutsessions/{sessionToken}/paymentaccounts](#operation/paymentsCreateToken) | ❌ | ❌ | ✅ | ❌ |\n| [/search/freetext](#operation/searchFreeText) | ✅ | ✅ | ✅ | ✅ |\n| [/destinations](#operation/destinations) | ✅ | ✅ | ✅ | ✅ |\n| [/locations/bulk](#operation/locationsBulk) | ✅ | ✅ | ✅ | ✅ |\n| [/exchange-rates](#operation/exchangeRates) | ✅ | ✅ | ✅ | ✅ |\n| [/reviews/product](#operation/reviewsProduct) | ❌ | ✅ | ✅ | ✅ |\n| [/suppliers/search/product-codes](#operation/suppliersSearchProductCodes) | ❌ | ✅ | ✅ | ✅ |\n\n\n# Authentication\n\n## API-key\n\nAccess to the API is managed using an **API key** that is included as a **header parameter** to every call made to all API endpoints described in this document.\n\n| Header parameter name | Example value |\n|-----------------------|---------------|\n| exp-api-key | bcac8986-4c33-4fa0-ad3f-75409487026c |\n\nIf you do not know the API key for your organization, please contact your business development account manager for these details.\n\nPlease note that language localization is now controlled on a per-call basis. Previously, localization settings were configured per API-key; whereas, under the present scheme, organizations have a **single API key**. \n\nLanguage localization is accomplished by specifying the desired language as a header parameter (`Accept-Language`). See [Accept-Language header](#section/Localization/Accept-Language-header-parameter) for available language codes.\n\n# Localization\n\n## Accept-Language header parameter\n\nThe `Accept-Language` header parameter specifies into which language the natural language fields in the response from each endpoint will be translated.\n\n**Note:** All partners using the V2 endpoints have access to all supported languages for their partner type.\n\n### Languages available to all partners\n\n| Language | Accept-Language parameter value |\n|----------|-------|\n| English | `en`, `en-US` `en-AU`, `en-CA`, `en-GB`, `en-HK`, `en-IE`, `en-IN`, `en-MY`, `en-NZ`, `en-PH`, `en-SG`, `en-ZA` |\n| Danish | `da` |\n| Dutch | `nl`, `nl-BE` |\n| Norwegian | `no` |\n| Spanish | `es`, `es-AR`, `es-CL`, `es-CO`, `es-MX`, `es-PE`, `es-VE` |\n| Swedish | `sv`|\n| French | `fr`, `fr-BE`, `fr-CA`, `fr-CH` |\n| Italian | `it`, `it-CH` |\n| German | `de`, `de-DE` |\n| Portuguese | `pt`, `pt-BR` |\n| Japanese | `ja` |\n\n### Additional languages available to merchant partners only\n\n| Language | Accept-Language parameter value |\n|----------|-------|\n| Chinese (traditional) | `zh-TW` |\n| Chinese (simplified) | `zh-CN` |\n| Korean | `ko`, `ko-KR` |\n\n## API versioning strategy\n\nIn order to ensure the predictability of the behavior of this software, we have implemented a versioning strategy to handle updates to the API contract, as well as a mechanism to specify which version of the API you wish to access.\n\nWhen we release a new version of this API, partners have the option of continuing to use the existing version or migrating to the updated version when they are ready.\n\n - **Note**: The version of this API that this document pertains to is that indicated in the title of this document.\n\nThe approach to versioning for this API is as follows:\n\n### Global versioning\n\n- Version numbers are global across all endpoints. When a new version of this API is released, **all** endpoints will increment to the latest version. Viator does not support a heterogenous implementation with calls being made to different endpoints with different version numbers.\n\n### Version release and deprecation\n\n- New versions of this software are released on an ad-hoc basis. Breaking changes will always result in a version increment.\n- Viator will inform partners about all version releases, including details about the new features available and any breaking changes that have been introduced.\n- Once a version of the API is deprecated, you will have a minimum of 12 months from the date of receiving notice of the change in which to modify your systems. Requests made to deprecated endpoint versions may result in a **400 Bad Request** response after 12 months.\n\n### Release candidates\n\n- Release candidate (RC) versions of this API may be made available to allow partners to preview changes in a non-production (sandbox) environment. When available, RC versions will be announced in this documentation, however these will not be subject to version control and breaking changes may be introduced prior to official release.\n\n### Release criteria\n\n#### Backward-compatible changes\n\nThe following types of change are considered backward-compatible, and will not result in a version release when introduced. Therefore, partners must ensure their implementation can handle such changes gracefully. \n\nThese changes comprise:\n\n - Introduction of new API endpoints\n - Addition of any properties to an endpoint's response schema\n - Addition of non-required properties to an endpoint's request schema\n - Unexpected receipt of an HTTP redirect response code (**301 Moved Permanently** or **302 Found**)\n - Addition of new HTTP methods (POST, GET, PUT, PATCH, DELETE, etc.)\n - Addition of new key values to existing fields that represent a set, insofar as no operating logic is likely to be affected\n\n#### Breaking changes\n\nThe following types of change are considered breaking changes and will result in the release of an incremented version of this software:\n\n - Addition of required properties to an endpoint's request schema\n - Removal of required properties from an endpoint's request or response schemata\n - Changing the data-type or format (e.g., date format) of an existing field in an endpoint's request or response schemata\n - Adding, removing or changing the meaning of the HTTP status codes in an endpoint's response\n - Removing or modifying the **Content-Type** on existing endpoints\n - Modifying or removing field key values in a set\n - Modifying the **operationId** of an endpoint\n\n### Version specification mechanism\n\nIt is mandatory to specify which version of the API you wish to use via the **'Accept' header parameter** in the **request** to each API endpoint; e.g., `Accept: application/json;version=2.0`. Omitting the version parameter will result in a **400 Bad Request** response.\n\n**Example valid request**:\n\n```bash\ncurl --location --request GET 'https://api.sandbox.viator.com/partner/products/modified-since?cursor=MTU5MjM1NTM0MXwxMTM5ODZQNA==' \\\n--header 'exp-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' \\\n--header 'Accept-Language: en-US' \\\n--header 'Accept: application/json;version=2.0'\n```\n\n**Example error response**:\n\n```json\n{\n \"code\":\"INVALID_HEADER_VALUE\",\n \"message\":\"Accept header is missing or has invalid version information\",\n \"timestamp\":\"2020-09-02T03:43:23.303946Z\",\n \"trackingId\":\"3D45567E:2D25_0A5D03AB:01BB_5F4F14A5_394639:3DB7\"\n}\n```\n\n## Accept-Encoding\n\nThis API supports gzip compression. Therefore, if you include `gzip` in the `Accept-Encoding` header parameter in the request, the API will respond with a gzip-compressed response.\n\n## Endpoint timeout settings\n\nIf you wish to implement internal timeout settings for calls to this API, **we recommend a setting of 120s**.\n\nThis is due to the fact that some of the products in our inventory rely on the operation of external supplier systems, which we do not control. Because of that, it may take up to 120s to receive a response when making a booking. In rare cases, booking response times in excess of 120s can sometimes occur.\n\nThis means that a booking may have actually succeeded even if the [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) endpoints time-out or respond with a HTTP 500 error. \n\nTherefore, it is strongly recommended that you check the status of the booking using the [/bookings/status](#operation/bookingsStatus) endpoint to make sure the booking was not created before you attempt to make the booking again.\n\nFurthermore, you can avoid creating duplicate bookings by making sure that you supply the same value for `partnerBookingRef` in the request to [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) as you did for the booking you believe may have failed. The `partnerBookingRef` value must be unique; therefore, a duplicate booking will not be created.\n\n# Key concepts\n\n## Product content and availability endpoints\n\n### Product content endpoints\n\nYou can retrieve the core product-content details from the following endpoints:\n\n- [/products/{product-code}](#operation/products): Retrieve content for a single product in real time when the product is selected by the customer \n - **Used by**: API partners who do not ingest the product database, but instead get each product's details only when required\n- [/products/modified-since](#operation/productsModifiedSince): Retrieve content for all products with filtering according to modification date \n - **Used by**: API partners who ingest the entire product catalog into a local database and perform regular delta updates via this endpoint to keep their local data in-sync with Viator's\n- [/products/bulk](#operation/productsBulk): Retrieve content for multiple products, as specified in the request. \n - **Please note**: This endpoint **must not** be used for ingestion; rather, it should only be used to retrieve product details for the selected products when needed.\n\n### Availability schedules endpoints\n\nYou can retrieve the availability schedules for products using the following endpoints:\n\n- [/availability/schedules/{product-code}](#operation/availabilitySchedules): Retrieve availability schedules for a single product in real time when the product is selected by the customer.\n - **Used by**: API partners who do not ingest the availability database, but instead get the availability schedules associated with a product at the time that it is required\n- [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince): Retrieve future availability schedules for all products with filtering according to modification date \n - **Used by**: API partners who ingest all availability schedules into a local database and perform regular delta updates via this endpoint to keep their local data in-sync with Viator's\n- [/availability/schedules/bulk](#operation/availabilitySchedulesBulk): Retrieve availability schedules for all products specified in the request.\n - **Please note**: This endpoint **must not** be used for ingestion; rather, it should only be used to retrieve the availability schedules for the selected products when needed.\n\n## Product options\n\nAny particular product may consist of a number of variants, each of which is referred to as a 'product option'. In previous versions of this API, and in the tours and activities sector in general, product options are also referred to as 'tour grades'.\n\nFor example, product options might represent different departure times, tour routes, or packaged extras like additional meals, transport and so forth.\n\nThe product options available for a product can be found in the `productOptions` array in the responses from any of the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints).\n\nWhen a product option includes an optional `logistics` object, use that object for start and end points and traveler pickup behaviour for that option; when it is absent, use the product-level `logistics` object instead.\n \nAn example `productOptions` array for the product **5010SYDNEY** is as follows:\n\n```json\n\"productOptions\": [\n {\n \"productOptionCode\": \"48HOUR\",\n \"description\": \"Duration: 2 days: FREE BONUS ENTRY to Sydney Tower with every Deluxe ticket end 31st March
48 Hour Premium Ticket: Unlimited use on Big Bus Sydney & Bondi Tour for 48 hours from time of first use PLUS a guided walking tour of The Rocks, Syd\",\n \"title\": \"48 Hour Premium Ticket \",\n \"languageGuides\": [...]\n },\n {\n \"productOptionCode\": \"TG1\",\n \"description\": \"Hop-on Hop-Off and Attractions: 48hr Big Bus Tours, 1-day Hop-On Hop-Off Harbour Cruise, 4 Attractions: Tower Eye, Madame Tussauds, Wildlife Zoo, Aquarium
Duration: 2 days
Complimentary Walking Tours: Complimentary English-speaking guided walking tour of “The Rocks” historic and harbourside precinct.\",\n \"title\": \"48Hour Deluxe PLUS Attractions\",\n \"languageGuides\": [...]\n },\n {\n \"productOptionCode\": \"24HOUR\",\n \"description\": \"Unlimited use on Big Bus Sydney & Bondi Hop-on Hop-off Tour for 24 hours from time of first use\",\n \"title\": \"24 Hour Classic Ticket \",\n \"languageGuides\": [...]\n },\n {\n \"productOptionCode\": \"DELUXE\",\n \"description\": \"Big Bus and Habour Cruise: Combine two great Sydney experiences into one with a hop-on hop off Big Bus Tours and a hop-on hop-off Sydney Harbour cruise
Duration: 2 days: FREE BONUS ENTRY to Sydney Tower with every Deluxe ticket end 31st March
Complimentary Walking Tour: Complimentary English-speaking 90-minute guided walking tour of “The Rocks” historic and harbourside precinct.\",\n \"title\": \"48 Hour Deluxe Bus and Cruise\",\n \"languageGuides\": [...]\n }\n]\n```\n\nThis product has four product options, each with an identifying code given in the `productOptionCode` field:\n\n- `\"48HOUR\"`\n- `\"TG1\"`\n- `\"24HOUR\"`\n- `\"DELUXE\"`\n\nProduct options are essentially a subcategory of the tour or activity. You will need to specify the product option you wish to book when making a booking.\n\n\n**Note on `DEFAULT` productOptionCodes:**\n\nPreviously, `DEFAULT` productOptionCodes were treated differently from other tour grades and were omitted from requests/responses when only one “DEFAULT” tour grade was present. This special treatment has been removed. All tour grades can be handled consistently. For backward compatibility, `DEFAULT` codes can still be omitted from some requests, but it is recommended to avoid this practice.\n\n\n## Availability schedules\n\nThe [availability schedules endpoints](#section/Key-concepts/Product-content-and-availability-endpoints) provide information about the availability of a product (along with its various product options and starting times, if they exist) and its pricing in the supplier's currency.\n\nThis section explains how to interpret the response from the [availability schedules endpoints](#section/Key-concepts/Product-content-and-availability-endpoints).\n\nExample response snippet from [/availability/schedules/10212P2](#operation/availabilitySchedules) (some starting times were removed for brevity):\n\n```json\n{\n \"productCode\": \"10212P2\",\n \"bookableItems\": [\n {\n \"productOptionCode\": \"TG45\",\n \"seasons\": [\n {\n \"startDate\": \"2019-05-01\",\n \"endDate\": \"2021-12-31\",\n \"pricingRecords\": [\n {\n \"daysOfWeek\": [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\",\n \"SATURDAY\",\n \"SUNDAY\"\n ],\n \"timedEntries\": [\n {\n \"startTime\": \"11:00\",\n \"unavailableDates\": [\n {\n \"date\": \"2020-09-16\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-23\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-22\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-27\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-29\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-30\",\n \"reason\": \"SOLD_OUT\"\n }\n ]\n },\n {\n \"startTime\": \"10:00\",\n \"unavailableDates\": [\n {\n \"date\": \"2020-09-25\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-26\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-28\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-27\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-30\",\n \"reason\": \"SOLD_OUT\"\n },\n {\n \"date\": \"2020-09-29\",\n \"reason\": \"SOLD_OUT\"\n }\n ]\n },\n {...}\n ],\n \"pricingDetails\": [\n {\n \"pricingPackageType\": \"PER_PERSON\",\n \"minTravelers\": 1,\n \"ageBand\": \"INFANT\",\n \"price\": {\n \"original\": {\n \"recommendedRetailPrice\": 0.00,\n \"partnerNetPrice\": 0.00,\n \"bookingFee\": 0.00,\n \"partnerTotalPrice\": 0.00\n }\n }\n },\n {\n \"pricingPackageType\": \"PER_PERSON\",\n \"minTravelers\": 1,\n \"ageBand\": \"ADULT\",\n \"price\": {\n \"original\": {\n \"recommendedRetailPrice\": 100.02,\n \"partnerNetPrice\": 79.89,\n \"bookingFee\": 4.79,\n \"partnerTotalPrice\": 84.68\n },\n \"special\": {\n \"recommendedRetailPrice\": 90.02,\n \"partnerNetPrice\": 71.90,\n \"bookingFee\": 4.31,\n \"partnerTotalPrice\": 76.21,\n \"offerStartDate\": \"2020-08-28\",\n \"offerEndDate\": \"2020-09-30\"\n }\n }\n }\n ]\n }\n ]\n }\n ]\n }\n ],\n \"currency\": \"USD\",\n \"summary\": {\n \"fromPrice\": 100.02\n }\n}\n```\n\n- Each item in the `bookableItems[]` array contains the availability and pricing data for one of the product's product-options (`productOptionCode`).\n- Each item in the `seasons[]` array describes the availability and pricing for the product-option during the 'season' (period of time) delimited by `startDate` and `endDate`. If `endDate` is not present, this means the season extends 384 days (approximately 12.5 months) into the future from the current date.\n- Each item in the `pricingRecords[]` array describes which days of the week (`daysOfWeek[]`) the availability and pricing data pertains to during the season, as well as which starting times are in operation (`timedEntries[]`) and on which dates (`unavailableDates[]`) each starting time is unavailable (e.g., due to being sold out).\n- Each item in the `pricingDetails[]` array describes the pricing that applies to each age-band during the season.\n\n### Interpreting the availability schedule\n\nWe can thereby interpret the availability schedule snippet above as follows:\n\n- For the product-option code `\"TG45\"` of product `\"10212P2\"`, during the period from `\"2019-05-01\"` to `\"2021-12-31\"`, on **all days of the week**, there are starting times at **10:00** and **11:00**.\n- The **11:00** starting time is unavailable due to being 'sold out' on the following dates:\n - 2020-09-16\n - 2020-09-22\n - 2020-09-23\n - 2020-09-27\n - 2020-09-29\n - 2020-09-30\n- The **10:00** starting time is unavailable due to being 'sold out' on the following dates:\n - 2020-09-25\n - 2020-09-26\n - 2020-09-27\n - 2020-09-28\n - 2020-09-29\n - 2020-09-30\n- Infant tickets are free (USD 0)\n- Adults are charged per-person; the normal recommended retail price (`original`) is USD 100.02\n- A **pricing special** (`special`) is in effect for adults between 2020-08-28 and 2020-09-30; the special recommended retail price is USD 90.02 \n\nUsing this information, a complete schedule – including which product-codes and starting times are available on which dates and the pricing (including special discounts) that applies on each date - can be constructed in your database.\n\n## Itineraries\n\nThe itinerary for a product is used to communicate to customers what to expect with regard to where they will go when participating in the tour or activity. On the [Viator.com website](https://viator.com), this information is displayed in the **What to expect** section on each product's product display page.\n\nItinerary information is available from this API in a machine-interpretable, structured format that facilitates graphical display and advanced search, should you choose to implement it.\n\nThe itinerary information for each product is contained in the `itinerary` object in the response from any of the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints).\n\nThere are five types of itinerary, and the type is specified in the `itinerary.itineraryType` field. They are as follows:\n\n| Itinerary type | `itineraryType` | Meaning |\n|----------------|-----------------------|---------|\n| **Standard** | `\"STANDARD\"` | A tour-based product (focused on visiting and viewing) that occurs at a single location or proceeds through a set of locations on a single day. |\n| **Activity** | `\"ACTIVITY\"` | An activity-based product (focused on the activity rather than the location) that occurs at a single location or proceeds through a set of locations on a single day |\n| **Multi-day tour** | `\"MULTI_DAY_TOUR\"` | A tour or activity that occurs over multiple days, and therefore includes food and accommodation |\n| **Hop-on / hop-off** | `\"HOP_ON_HOP_OFF\"` | A tour that operates continuously, such as a bus tour, wherein passengers can use their ticket to board and alight as they please at any of the stops along the route |\n| **Unstructured** | `\"UNSTRUCTURED\"` | Not all suppliers have upgraded the itinerary information for their products from a text-based description to structured data; therefore, the itinerary information for a small number of products remains unparseable for the time being. | \n\n### Common elements\n\nThe `itinerary` object is polymorphic depending on the `itineraryType`, but all variants contain standard information, as follows:\n\n| Field name | Meaning |\n|------------|---------|\n| `skipTheLine` | `true` if a ticket for this product allows participants to attend a location without having to obtain a separate ticket on the occasion itself |\n| `privateTour` | `true` if only the travelers who have booked this product will be present; `false` if it is a shared tour |\n| `maxTravelersInSharedTour` | If `privateTour` is `false`, this value represents the maximum number of people that will be able to participate in the tour or activity. |\n| `unstructuredDescription` | In the event that structured information is not available, this field will contain a plain-text description of the itinerary. |\n\nAll other elements in the `itinerary` object differ slightly according to the value of `itineraryType`.\n\n### Standard itinerary\n\nProducts with a `\"STANDARD\"` itinerary type are tour-based products (focused on visiting and viewing) that occur at a single location or proceed through a set of locations on a single day.\n\nAn example of a `\"STANDARD\"` itinerary product is [Barossa Valley Highlights from Barossa Valley Including Wine and Cheese Tasting (21381P1)](https://www.viator.com/tours/Barossa-Valley/Barossa-Valley-Highlights-from-Adelaide-or-Barossa-Valley-Including-Wine-and-Cheese-Tasting/d5623-21381P1).\n\nThe `itinerary` object in the product-content response for this tour is as follows (truncated to the first three items for brevity):\n\n```json\n\"itinerary\": {\n \"itineraryType\": \"STANDARD\",\n \"skipTheLine\": false,\n \"duration\": {\n \"fixedDurationInMinutes\": 360\n },\n \"itineraryItems\": [\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-5620ab70-c813-4904-ad13-bcf527540d3e\"\n },\n \"attractionId\": 17873\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 45\n },\n \"passByWithoutStopping\": false,\n \"admissionIncluded\": \"YES\",\n \"description\": \"Guests will experience the majesty of (...) \"\n },\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-7ae41705-fd91-4500-8cde-bbe9b3a00df4\"\n }\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 40\n },\n \"passByWithoutStopping\": false,\n \"admissionIncluded\": \"YES\",\n \"description\": \"Guests will enjoy a truly unique offering (...)\"\n },\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-9494c4cf-f4e4-4e7f-8213-0cf1b9980097\"\n }\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 30\n },\n \"passByWithoutStopping\": false,\n \"admissionIncluded\": \"YES\",\n \"description\": \"No trip to the Barossa would be complete without (...)\"\n }\n (...)\n ]\n}\n```\nThe `itineraryItems[]` array describes the itinerary of locations for this tour and can be used in conjunction with the [/locations/bulk](#operation/locationsBulk) endpoint to contruct a **What to expect** section, similar to what is seen for this product on [viator.com](https://www.viator.com/tours/Barossa-Valley/Barossa-Valley-Highlights-from-Adelaide-or-Barossa-Valley-Including-Wine-and-Cheese-Tasting/d5623-21381P1), as in the following screen-shot:\n\n
\n \"Standard\n
Standard itinerary example from viator.com
\n
\n\nThe elements highlighted in red boxes are sourced as follows:\n\n**\"Stop At: Seppeltsfield\"**\n\nThe name of each location (in the highlighted case, 'Seppeltsfield') is not included in the response and must be determined by submitting the location reference code in the `pointOfInterestLocation.location.ref` field to the [/locations/bulk](#operation/locationsBulk) endpoint.\n\nThe location reference is `\"LOC-5620ab70-c813-4904-ad13-bcf527540d3e\"`:\n\n```json\n\"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-5620ab70-c813-4904-ad13-bcf527540d3e\"\n}\n```\n\nSubmitting this code to the [/locations/bulk](#operation/locationsBulk) endpoint yields the following response:\n\n```json\n{\n \"locations\": [\n {\n \"provider\": \"TRIPADVISOR\",\n \"reference\": \"LOC-5620ab70-c813-4904-ad13-bcf527540d3e\",\n \"name\": \"Seppeltsfield\",\n \"address\": {\n \"street\": \"730 Seppeltsfield Rd\",\n \"administrativeArea\": \"Seppeltsfield\",\n \"state\": \"South Australia\",\n \"country\": \"Australia\",\n \"countryCode\": \"AU\",\n \"postcode\": \"5355\"\n },\n \"center\": {\n \"latitude\": -34.489162,\n \"longitude\": 138.91866\n }\n }\n ]\n}\n```\n\nThe name of the location is in the `name` element; i.e., `\"Seppeltsfield\"`.\n\n**Description**\n\nThe description for each itinerary stop is given in the `description` field; in this case:\n\n```json\n\"description\": \"Guests will experience the majesty of the Seppeltsfield Winery Estate, an historic icon of the Barossa and integral part of its storied history. Learn the story of the Seppelt family, the phenomenal fortified wines upon which they have built their reputation and taste a broad range of their current wine offerings. Don’t forget to ask about the Centennial collection, the only wine collection of wines of its type in the world with more than 120 years of consecutive vintages currently stored in the barrel. \"\n```\n\n**\"Duration: 45 minutes\"**\n\nThe duration spent at an itinerary location is given in the `duration` element. This can be a fixed duration, as in this example and indicated by the `fixedDurationInMinutes` field being filled; i.e.:\n\n```json\n\"duration\": {\n \"fixedDurationInMinutes\": 45\n},\n```\n\nOr, the time spent at the location might be variable, in which case only the `variableDurationFromMinutes` and `variableDurationToMinutes` fields will appear; e.g.:\n\n```json\n\"duration\": {\n \"variableDurationFromMinutes\": 10,\n \"variableDurationToMinutes\": 30\n},\n```\n\n**\"Admission Ticket Included\"**\n\nThis item of information indicates to the traveler whether or not they will be required to pay for admission to a location or whether admission is included in the price of the tour. It is indicated by the `admissionIncluded` field; which in this case is:\n\n```json\n \"admissionIncluded\": \"YES\"\n```\nThe possible values this field can take are:\n- `\"YES\"`\n- `\"NO\"`\n- `\"NOT_APPLICABLE\"`\n\n**Pass by without stopping**\n\nIn this example, the `passByWithoutStopping` element is `false` for all locations. On some tours, however, the vehicle will merely pass by a certain location, without stopping, for viewing purposes. If that is the case, this field will be `true`.\n\n### Activity itinerary\n\nThe \"activity\" itinerary is designed for products where the focus of the experience is the activity itself (e.g., cooking classes), rather than the location(s) at which it occurs.\n\nThe `itinerary` object for this type of product includes the `activityInfo` and `foodMenus` objects, which contain details about the activity and any meals being served (or created), respectively.\n\n**Example activity experience**: [Traditional Cooking Class - 114869P3](https://www.viator.com/tours/Yogyakarta/Traditional-Cooking-Class/d22560-114869P3)\n\n```json\n\"itinerary\": {\n \"itineraryType\": \"ACTIVITY\",\n \"skipTheLine\": false,\n \"privateTour\": true,\n \"duration\": {\n \"fixedDurationInMinutes\": 240\n },\n \"pointsOfInterest\": [\n {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5C7cXoFi13Pb8aiiiEWiVprM1MtQdt/DIeeb7ErQo1SK\"\n }\n ],\n \"activityInfo\": {\n \"location\": {\n \"ref\": \"LOC-dwbUKYXwDvt911EeSQVjwo4itqM47D/JrJBMhEHXctp6Yj8SzOvLCGbeQQ0arbNw8FHTuTEi0SU9RbKNpLx7bw8HP6Pnh1pBwy27irN3vKoTexOgxSlj2+xv9x3k6fZnPrb/zhY5RImUibPpbTET/+atZD8crT0DlPf5hg21QPWNam1RsZKgzF5gb1fPZ6d7WNWIWYsu3m54y2TFqiHaAbo1d2Ps2LFK+DCctmyDmqbgSV7FDpLXv5sL/e0R/Mg+7vLX0lMV8HGW4jisRxqYD5oThATP9j1NRY98SvhXpEI=\"\n },\n \"description\": \"Embark on a culinary adventure unlocking the secrets of authentic Javanese cooking, utilizing traditional ingredients and preparation methods.\\nYour day starts early at the local markets, where you can pick from fresh herbs & spices, crisp vegetables and choice cuts of meat. \\nAfter exploring at the traditional market, you will be warmly welcomed and expertly guided by your host, who will help you to discover how to create your very own delicious authentic Javanese dishes. \\nYour hard work is rewarded when you sit down to have lunch on your tasty creations.\\nAll classes are conducted in English by Javanese chefs fully conversant with Javanese cuisine and culture...and in a relaxed, friendly atmosphere in the beautiful kitchen-garden.\"\n },\n \"foodMenus\": [\n {\n \"course\": \"MAIN\",\n \"dishName\": \"Gado-gado\",\n \"dishDescription\": \"Mixed vegetables with peanut sauce\"\n },\n {\n \"course\": \"MAIN\",\n \"dishName\": \"Opor Ayam\",\n \"dishDescription\": \"Braised Chicken in Coconut Milk\"\n }\n ]\n}\n```\n\nAll information for the 'What to Expect' section on the product display page on Viator.com is can be sourced from this object.\n\n### Multi-day tour itinerary\n\nProducts with a `\"MULTI_DAY_TOUR\"` itinerary type are tours or activities that occur over multiple days, and therefore include a breakdown of the itinerary for each day of the tour, as well as extra information about food and accommodation.\n\n**Example multi-day tour**: [Active Winter Adventure in Yukon | 5 days (7110P7)](https://www.viator.com/tours/Whitehorse/5-Day-Active-Winter-Adventure-in-Yukon/d5420-7110P7)\n\nScreenshot of 'What to expect' section from the viator.com site:\n\n
\n \"Multi-day\n
Multi-day tour itinerary example from viator.com
\n
\n\nSnippet of the `itinerary` object in the product content response for 7110P7 (truncated to first two items of `days[]` array):\n\n```json\n\"itinerary\": {\n \"itineraryType\": \"MULTI_DAY_TOUR\",\n \"skipTheLine\": false,\n \"duration\": {\n \"fixedDurationInMinutes\": 7200\n },\n \"days\": [\n {\n \"title\": \"Arrival Whitehorse\",\n \"dayNumber\": 1,\n \"items\": [\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-99b0f435-fa6a-469f-8f96-f983b82f74c5\"\n }\n },\n \"duration\": {},\n \"admissionIncluded\": \"NOT_APPLICABLE\",\n \"description\": \"From the airport we drive you to your hotel located in the centre of Whitehorse.\"\n }\n ],\n \"accommodations\": [\n {\n \"description\": \"Overnight in downtown Whitehorse Hotel\"\n }\n ]\n },\n {\n \"title\": \"Wildlife and Hot Springs, a Bird's-Eye-View and Northern Lights\",\n \"dayNumber\": 2,\n \"items\": [\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-799e6c90-d0bb-4ec4-9cf6-c40459ff0463\"\n },\n \"attractionId\": 25942\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 90\n },\n \"admissionIncluded\": \"YES\",\n \"description\": \"Later we drive to the Yukon Wildlife Preserve where we can see up close inhabitant game like the Elk, Moose, Caribou, Mountain Goats and Porcupines in their natural surrounding.\"\n },\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-cf8d0f7a-54d6-4cc1-9911-480b4934c752\"\n },\n \"attractionId\": 25951\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 90\n },\n \"admissionIncluded\": \"YES\",\n \"description\": \"Not far from here we will visit the Takhini Hotsprings and endulge ourself in the natural hot waters and relax in a breathtaking winter mountain setting.\"\n },\n {\n \"pointOfInterestLocation\": {\n \"location\": {\n \"ref\": \"LOC-3251a39d-aa69-4229-9ba4-57d5b417e6db\"\n }\n },\n \"duration\": {\n \"fixedDurationInMinutes\": 240\n },\n \"admissionIncluded\": \"YES\",\n \"description\": \"After a relaxed dinner in Whitehorse, you’ll be back on the road again, this time to seek views of the stunning Northern Lights. Relax in sheltered comfort, or under the starry sky beside a warm fire at one of our tailor-made aurora viewing locations. \"\n }\n ],\n \"accommodations\": [\n {\n \"description\": \"Overnight in downtown Whitehorse Hotel\"\n }\n ]\n },\n (...)\n ]\n}\n```\n\nWithin the `days[]` array, each day of the multi-day tour is described. The `items[]` array within each item of the `days[]` array largely follows the structure of the items in the `itineraryItems[]` array of the `\"STANDARD\"` itinerary and can be interpreted for display.\n\nThe `fixedDurationInMinutes` in the `itinerary[]` array represents the total duration of the tour. \n\n**Note**: The example above does not include the `foodAndDrinks[]` element, as it is not relevant to this product.\n\n### Hop-on / hop off itinerary\n\nA hop-on/hop-off product is one that typically operates continuously during its hours of operation, such as a bus tour, and passengers can use their ticket to board and alight as they please at any of the stops along the route.\n\nSuch products may also operate multiple routes simultaneously.\n\n**Example hop-on / hop-off tour**:[Big Bus Sydney and Bondi Hop-on Hop-off Tour (5010SYDNEY)](https://www.viator.com/tours/Sydney/Sydney-and-Bondi-Hop-on-Hop-off-Tour/d357-5010SYDNEY)\n\n
\n \"Hop-on\n
Hop-on / hop-off itinerary example from viator.com
\n
\n\nSnippet of `itinerary` object in the product content response for 5010SYDNEY (`operatingSchedule`, `stops` and `pointsOfInterest` truncated in first route):\n\n```json\n\"itinerary\": {\n \"itineraryType\": \"HOP_ON_HOP_OFF\",\n \"skipTheLine\": false,\n \"privateTour\": false,\n \"duration\": {\n \"fixedDurationInMinutes\": 120\n }, \n \"routes\": [\n {\n \"operatingSchedule\": \"1st bus departs from Stop 1 Circular Quay at 9.00am.. (...)\",\n \"duration\": {\n \"fixedDurationInMinutes\": 120\n },\n \"name\": \"Red Route - Sydney Icons\",\n \"stops\": [...],\n \"pointsOfInterest\": [...]\n ]\n },\n {\n \"operatingSchedule\": \"1st bus departs from Stop 12/24 Central Station at 10.00am.\\nFrequency every 60 minutes\\nLast bus departs from stop 12/24 at 4.00pm\",\n \"duration\": {\n \"fixedDurationInMinutes\": 120\n },\n \"name\": \"Blue Route - Bondi Lifestyle\",\n \"stops\": [\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Psa0O7zv6as2RgNgIaUx0EFjKH/7fL3wV6nAS8iPXkO\"\n },\n \"description\": \"Central Station, Pitt Street, Bus Bay 18\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-RaYlfRSLaIsd0SlazqDQk19G5f6qNrg0gjGUG4TKX09ebeQFQmF/tcZGYdP+hZ8qHiX/vcPkkKKpDcocShqAYEgNFI1CfF3En+N9VrOAxKQUrgoRQ1Va78q0+ItmaNr/WbsMTE8jgepUMa6GSjKvLkRhjHJbm/8KZDt9vri/bomquCnoZMFCjkrjxqrlpEp5m2qWwkCxg5iRffRLuhG/YQ==\"\n },\n \"description\": \"Australian Museum \"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Nh4BzPY4JhOxIuD4/Do8pUJ7t+9MCl62rbq6KVnaek/\"\n },\n \"description\": \"\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5HyrAalNU3M4hS1T1NGhMtCdFsSEh+RkFpJBmFZX9No8\"\n },\n \"description\": \"\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5ADNeEAMR25x+3AtosA/mPk102O66T1JygFmomnS5cve\"\n },\n \"description\": \"\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5DlsAklW6JtKr4LQsnhsvv7JxEYbLQWAsKDqTrCu41p4\"\n },\n \"description\": \"\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5BLsCa3M6INxXNpkE2r1BTHxvB0gY1MP6WB9Yxso16Ot\"\n },\n \"description\": \"\"\n },\n {\n \"stopLocation\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5PrdhQ/J96Gq+dweFD3sOSrkBFH5QSJjP1VJ0a/86OPO\"\n },\n \"description\": \"\"\n }\n ],\n \"pointsOfInterest\": [\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyIiKlXuqcCaUR/8Ng7CZSLI=\"\n },\n \"attractionId\": 14159\n },\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyOEUrjaNrfQuPK4sfYmEGio=\"\n }\n },\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyPTry/4ZvItH2jj+ziZ16zY=\"\n }\n },\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyCs+n26oP6pvXz2mRpQ6QlA=\"\n }\n },\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyI5+u+JgfxCzNB+Yaph1xug=\"\n }\n }\n ]\n }\n ]\n}\n```\n\nBy comparing the response snippet with the screenshot above, you can see that:\n\n- There are two routes – \"Red Route - Sydney Icons\" and \"Blue Route - Bondi Lifestyle\"\n- The Blue Route has 8 stops and 5 points of interest\n- Only the first two stops on the Blue Route have descriptive text entered by the supplier, as seen in the screenshot and in the snippet (`description` field)\n\nAll location details (including the name) must be retrieved by sending the location reference to the [/locations/bulk](#operation/locationsBulk) endpoint. \n\nThe total duration of the tour can be found in the `itinerary[]` array. \nIf all tour routes have the same duration, the `fixedDurationInMinutes` field will be returned. \nWhen tour routes have different duration, only the `variableDurationFromMinutes` and `variableDurationToMinutes` fields will appear.\n\n### Unstructured itinerary\n\nAlthough our systems have been upgraded to support structured itinerary information, this feature is only availabe once the supplier manually updates their product details. A small number of suppliers have not yet made these updates. As such, some products retain their legacy itinerary information, and this case is handled with the `\"UNSTRUCTURED\"` itinerary type.\n\nSnippet of `itinerary` object in the product content response for [5524GOLD - Private Tour: 4-Day Golden Triangle Trip to Agra and Jaipur from Delhi](https://www.viator.com/tours/New-Delhi/Private-Tour-4-Day-Golden-Triangle-Trip-to-Agra-and-Jaipur-from-Delhi/d804-5524GOLD):\n\n```json\n\"itinerary\": {\n \"itineraryType\": \"UNSTRUCTURED\",\n \"skipTheLine\": false,\n \"privateTour\": false,\n \"unstructuredDescription\": \"Please read the Itinerary section for details on your Golden Triangle tour from Delhi to Agra and Jaipur.\",\n \"unstructuredItinerary\": \" Day 1: Delhi – AgraMorning departure from your hotel in Delhi. Traveling in the comfort your own air-conditioned vehicle, accompanied by a driver, the journey to Agra will take approximately four to five hours. Upon arrival in Agra, check in at your hotel. In Agra, your local guide who will take you to visit the famous and majestic Red Agra Fort, followed by the romantic Taj Mahal at sunset. The remainder of the evening is free for your own personal exploration.\\n\\nOvernight: 3- or 4-star hotel in Agra\\n\\nDay 2: Agra – Jaipur (B)After breakfast, travel by road to Fatehpur Sikri, located approximately 40 kilometers from Agra. Fatehpur Sikri was the capital of the Mughal Empire between 1571 and 1585 during the reign of Akbar. Continue to the 'pink city' of Jaipur. The rest of your day is free for your own exploration of Jaipur's action packed streets and magnificent palaces. Jaipur is a shopper's paradise. There is an amazing range of crafts available, and Jaipur is also famous for its precious and semi-precious stones. \\n\\nOvernight: 3- or 4-star hotel in Jaipur\\n\\nDay 3: Jaipur (B)After breakfast, visit Amber Fort located 12 kilometers from Jaipur. The magnificent Amber Fort is a fine blend of Hindu and Muslim architecture. Return to Jaipur and visit the City Palace, situated in the heart of Jaipur's old city. The palace is a blend of Rajput and Mughal architecture; it houses a 7-storied Chandra Mahal in the center. Also visit Hawa Mahal (Palace of Winds), Jaipur's most distinctive landmark. Built in 1799, this is an amazing example of Rajput architecture.\\n\\nOvernight: 3- or 4-star hotel in Jaipur\\n\\nDay 4: Jaipur – Delhi (B)After breakfast, travel back to your Delhi hotel or the airport.\",\n \"duration\": {\n \"fixedDurationInMinutes\": 5760\n },\n \"pointOfInterestLocations\": [\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyJUIMZqLxZiFQx5hWjqMeXg=\"\n }\n }\n ]\n},\n```\n\nUse the `unstructuredDescription` and `unstructuredItinerary` fields to create the section on your site that corresponds to the **What to expect** section on the Viator product display page. Note that the `unstructuredItinerary` field is not always populated – in that case, just use the `unstructuredDescription` field.\n\nAll products with an `\"UNSTRUCTURED\"` itinerary type are in the process of being updated to the appropriate structured type. Eventually, all products will support structured itinerary information.\n\n## Protecting unique content\n\nIn order to prevent our unique content from being utilized by unauthorized third parties, we require that you design your site in such a way that this content will not be indexed by search engines.\n\nThe content that must be protected comprises:\n\n- **Product reviews** – This includes all review text (from any provider) as obtained via the [/reviews/product](#operation/reviewsProduct) endpoint; and, that in the `reviews` element in the product content response. \n- **Viator unique content** – This includes all data in all elements within the `viatorUniqueContent` element in the product content response.\n\n### Guidelines to prevent indexing of unique content\n\nIn order to properly protect reviews and other unique content, you must ensure that the protected content **never** appears directly in the source code of the loaded page. This includes both HTML and Javascript.\n\nIn order to do this correctly, the unique content must be loaded via a call to an **external** Javascript, and that Javascript must be blocked in [robots.txt](https://moz.com/learn/seo/robotstxt) so that search engines can not see or index it.\n\n### How to check\n\nA simple way to check that the unique content does not appear in the source code of the loaded page – and, therefore, cannot be indexed – is to copy a snippet of the unique content text that is displayed when you load the page normally in your browser. Approximately 10 words will suffice.\n\nThen, access the source code of that page using the **View Source** feature in your browser. Use your browser's in-page search feature to search for the text snippet copied in the previous step. If the text is found anywhere in the source code of the page, then your implementation is **not** correctly protecting the content, as it will be able to be indexed by search enginges. \n\n### Example implementations\n\n❌ **Unacceptable implementation**: pure HTML\n\nHere the protected content appears directly in the HTML and can be indexed by search engines:\n\n```html\n\n \n \n \n
”I had a great time at this hotel”
\n \n\n```\n\n❌ **Unacceptable implementation**: Javascript in the page source\n\nHere, the protected content still appears in the page source, even though it is in the 'script' section, and will therefore be indexed by search engines:\n\n\n```html\n\n \n \n \n \n
\n \n\n```\n\n✅ **Acceptable implementation:** protected content is loaded using an **external** Javascript and access to that endpoint is blocked using robots.txt:\n\n```html\n\n \n \n \n \n
\n \n\n```\n\nRobots.txt in the document root for `https://api.hello.xyz`:\n\n```bash\nUser-Agent: *\nDisallow: /getReviewContentForHotel\n```\n\n**Note**: The robots.txt file must be in the root directory for whichever domain or subdomain the call is being made to. Please review the [robots.txt guidelines](https://developers.google.com/search/docs/advanced/robots/create-robots-txt) to determine the correct syntax for your site.\n\n## Review authenticity\n\n### Viator performs checks on reviews\n\nYou can only submit a review or rating of an experience to Viator if you were the person who made the booking through Viator. Before publication, each review goes through an automated tracking system, which collects information for each of the following criteria: who, what, how, and when. \n\nIf the system detects something that contradicts our publication criteria, the review is not published. When the system detects a problem with a review, it may be automatically rejected, sent to the reviewer for validation, or manually reviewed by our team of content specialists who work 24/7 to maintain the quality of the reviews on our site. In some cases, we will also send Viator customers an email asking them to validate their review before it is published.

All Viator customers need to do is to click on the link provided in the email. \n\nAfter publication, our team checks each review reported to it as not meeting our publication criteria. Tripadvisor reviews that appear on the Viator site are subject to the same checks and moderation processes as set out above. It is not necessary to have booked an experience through Viator (or Tripadvisor) to submit a review of an experience to the Tripadvisor site.\n\n# Booking concepts\n\n## Working with age bands\n\n### Why have age bands?\n\nTour and experience product suppliers can set different prices for (and impose different rules on) customers according to how old they are. \n\nFor example, suppliers might choose to charge people 18 years and older ('adults') the full ticket price, while 'children' can book at a lower price. \n\nOr, the tour operator may only allow children to make a group booking for the tour so long as the group contains 'at least one adult'.\n\nViator provides six age-band categories that product suppliers can use to segregate travelers into age groups (the limits of which they also define) in order to set pricing and traveler-count participation rules for their product according to the age band categories.\n\nThe age-bands available for a particular product, such as *adult*, *child*, *infant*, etc., are returned by the [/products/{product-code}](#operation/products) service. Your customer should be able to select a different number of people from each available age-band during the price check and checkout process.\n\nTo learn more about how to implement age bands, see the following guide: [Implementing age bands & pax mix](https://partnerresources.viator.com/travel-commerce/merchant/agebands-pax-mix?source=specs)\n\n### Age-band categories\n\nThe age bands supported by the Viator API are as follows:\n\n| bandId | Description |\n|------:|-------|\n| `\"ADULT\"` | Adult |\n| `\"CHILD\"` | Child |\n| `\"INFANT\"` | Infant |\n| `\"YOUTH\"` | Youth |\n| `\"SENIOR\"` | Senior |\n| `\"TRAVELER`\" | Catch-all age-band for unit-priced products |\n\nNote that the `\"TRAVELER\"` is only used for bookings with [unit pricing](#section/Booking-concepts/Per-person-and-unit-pricing), in which case it will be the only age-band available.\n\nThe exact age range to which each category pertains is defined by the supplier, and the maximum and minimum ages that each age band describes for each product can be found in the product content response; e.g.:\n\n```json\n\"ageBands\": [\n {\n \"ageBand\": \"INFANT\",\n \"startAge\": 0,\n \"endAge\": 2,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 15\n },\n {\n \"ageBand\": \"CHILD\",\n \"startAge\": 3,\n \"endAge\": 11,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 15\n },\n {\n \"ageBand\": \"ADULT\",\n \"startAge\": 12,\n \"endAge\": 80,\n \"minTravelersPerBooking\": 1,\n \"maxTravelersPerBooking\": 15\n }\n]\n\n```\n\nFor this product, the age bands have been defined as follows:\n\n| `ageBand` | `ageFrom` | `ageTo` |\n|:--------:|:-------:|:-----:|\n| ADULT | 13 | 64 |\n| SENIOR | 65 | 99 |\n| CHILD | 4 | 12 |\n\n\nProduct suppliers must define at least one age band for their tour, and there are no 'default' age ranges. Therefore, if the supplier has only specified a single 'adult' age band covering ages 18-99, it must be assumed that only people aged 18-99 are eligible to book the tour, essentially excluding children and centenarians in this case.\n\n### When you will use age-bands\n\nThe age-band of a customer needs to be communicated via the API in the following situations:\n\n1. When placing a booking-hold\n - you will need to supply the age-band of each of the travelers being booked for in the `paxMix` element in the request to [/bookings/hold](#operation/bookingsHold) or [/bookings/cart/hold](#operation/bookingsCartHold).\n2. When making a booking \n - As with the booking hold, age-bands must be supplied in the `paxMix` element \n - If the supplier has specified `\"AGEBAND\"` as a booking question, you must additionally provide these details in the `bookingQuestionAnswers` array in the request to [/bookings/book](#operation/bookingBook) or [/bookings/cart/book](#operation/bookingsCartBook). Note that these details are verified by the booking server and the booking will be rejected if the details do not match. For more information about answering the `\"AGEBAND\"` booking question, see [Booking concepts – Booking questions](#section/Booking-concepts/Booking-questions).\n\n## Cancellation policy\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nAs well as *making* bookings, affiliate and merchant partners are also able to *cancel* bookings through the Viator API using the [/bookings/cancel-reasons](#operation/bookingsCancelReasons), [/bookings/{booking-ref}/cancel-quote](#operation/bookingsCancelQuote) and [/bookings/{booking-ref}/cancel](#operation/bookingsCancel) endpoints. Items cancelled via the [/bookings/{booking-ref}/cancel](#operation/bookingsCancel) endpoint will be cancelled in full, and only one booking can be cancelled at a time.\n\nFor more information about how to perform cancellations using this API, see the [Cancellation API workflow](#section/Booking-concepts/Cancellation-API-workflow) section and our in-depth guide about cancellation policies and how to handle cancellations: [All you need to know about cancellation policies](https://partnerresources.viator.com/travel-commerce/merchant/cancellation-policies?source=specs).\n\n\n### Cancellation policies\n\nAll products can be cancelled by the affiliate or merchant partner; however, the refund granted by the supplier depends on the cancellation policy for the product in question.\n\nThere are three cancellation policy categories, **standard**, **custom** and **all sales final**, indicated by the `type` element of the `cancellationPolicy` object in the responses from the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints).\n\n**Note:** *These policies are those provided by Viator to you, the merchant partner. As the merchant of record, you can choose whether to extend these terms to your customers unchanged; or, set your own cancellation terms. For example, you might choose to make all products non-refundable; or, you might extend the full-refund cancellation window to 72 hours instead of 24 hours, and so forth. However, you will still be invoiced according to Viator's cancellation policies communicated via the API*\n\n### Standard cancellation policy (`\"STANDARD\"`)\nProducts in this category can be cancelled up to 24 hours before the travel time (local supplier time) and a full refund will be granted. However, a 100% cancellation penalty applies for cancellations submitted less than 24 hours before the start time. Most products (about 85%) fall into this category.\n\n#### Example response snippet\n\n- **Source endpoint**: [/products/{product-code}](#operation/products)\n- **Product**: `5010SYDNEY`\n\n```json\n{\n \"cancellationPolicy\": {\n \"type\": \"STANDARD\",\n \"description\": \"For a full refund, cancel at least 24 hours before the scheduled departure time.\",\n \"cancelIfBadWeather\": false,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 1,\n \"percentageRefundable\": 100\n },\n {\n \"dayRangeMin\": 0,\n \"dayRangeMax\": 1,\n \"percentageRefundable\": 0\n }\n ]\n },\n```\n\nThis product has the *standard* cancellation policy; i.e., when a booking is cancelled:\n\n| Policy | `dayRangeMin` | `dayRangeMax` | Logic | `percentageRefundable` |\n|--------|:-----------:|:-----------:|-------|:--------------------------:|\n| *less than* one day (24 hours) before the start time | 0 | 1 | (product_start_time - cancellation_time) >= 0 days && (product_start_time - cancellation_time) < 1 days | 0 |\n| *more than* one day (24 hours) before the start time | 1 | (absent) | (product_start_time - cancellation_time) >= 1 day | 100 |\n\n### Custom cancellation policy (`\"CUSTOM\"`)\nThe refund amount for products in this category varies depending on how long before its start time the product is cancelled. Many products on a custom policy are multi-day tours, which require more sophisticated planning on the supplier’s end. Only a small number of products (around 5%) fall into this category.\n\n - **Note**: the `description` field contains a natural-language (and therefore language-localized) description of the policy described in the `refundEligibility` array. You can use this description for customer-messaging directly, or implement your own natural-language generation techique. With the cancellation policy encoded in a structured way, it would also be possible to display this information graphically.\n\n#### Example response snippet\n\n- **Source endpoint**: [/products/{product-code}](#operation/products)\n- **Product**: `40944P355`\n\n```json\n\"cancellationPolicy\": {\n \"type\": \"CUSTOM\",\n \"description\": \"If you cancel at least 30 day(s) in advance of the scheduled departure, there is no cancellation fee.
If you cancel between 10 and 29 day(s) in advance of the scheduled departure, there is a 50 percent cancellation fee.
If you cancel within 9 day(s) of the scheduled departure, there is a 100 percent cancellation fee.\",\n \"cancelIfBadWeather\": false,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 10,\n \"dayRangeMax\": 30,\n \"percentageRefundable\": 50\n },\n {\n \"dayRangeMin\": 30,\n \"percentageRefundable\": 100\n },\n {\n \"dayRangeMin\": 0,\n \"dayRangeMax\": 10,\n \"percentageRefundable\": 0\n } \n ]\n },\n```\n\nThis product has a complex cancellation policy; where cancellations processed:\n\n| Policy | `dayRangeMin` | `dayRangeMax` | Logic | `percentageRefundable` |\n|--------|:-----------:|:-----------:|-------|:--------------------------:|\n| 30 days or more before the start time | 30 | (absent) | (product_start_time - cancellation_time) >= 30 days | 100 |\n| 10 days and *less than* 30 days (10 to 30 days) *before* the start time or more | 10 | 30 | (product_start_time - cancellation_time) >= 10 days && (product_start_time - cancellation_time) < 30 days | 50 |\n| *less than* 10 days *before* the start time | 0 | 10 | (product_start_time - cancellation_time) < 10 days | 0 |\n\n**Note:** When the `dateRangeMax` field is absent, this means infinity. Therefore, the second element in the `refundEligibility` array above indicates that the time period begins infinitely far in the past *until* 30 days prior to the tour or activity commencing.\n\n### `3` – All sales final (100% cancellation penalty / no refund offered)\n\nProducts in this category cannot be cancelled or amended without incurring a 100% penalty; i.e., the refund amount will be zero. Around 10% of products fall into this category.\n\n#### Example response snippet\n\n- **Source endpoint**: [/products/{product-code}](#operation/products)\n- **Product**: `100014P7`\n\n```json\n{\n \"cancellationPolicy\": {\n \"type\": \"ALL_SALES_FINAL\",\n \"description\": \"All sales are final and incur 100% cancellation penalties\",\n \"cancelIfBadWeather\": false,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 0,\n \"percentageRefundable\": 0\n }\n ]\n },\n```\n\nProducts in this category can be cancelled, but no refund will be granted.\n\n### startTimeStamp and endTimeStamp\n\nWithin the `cancellationPolicy` object in the response from [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook), the `refundEligibility.startTimestamp` and `refundEligibility.endTimestamp` fields contain time-stamps (UTC) that indicate the exact times between which the different cancellation refund rates apply.\n\n**Note**: \n * `refundEligibility.startTimestamp` will always be further in the past than `refundEligibility.endTimestamp`. \n * Please use `startTimestamp` and `endTimestamp`, rather than `dayRangeMin` and `dayRangeMax`, to determine which cancellation policy is in effect.\n\n**Example response snippet from [/bookings/book](#operation/bookingsBook) and [/bookings/cart/book](#operation/bookingsCartBook)**:\n\n```json\n\"cancellationPolicy\": {\n \"type\": \"STANDARD\",\n \"description\": \"For a full refund, cancel at least 24 hours before the scheduled departure time.\",\n \"cancelIfBadWeather\": false,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 1,\n \"percentageRefundable\": 100,\n \"startTimestamp\": \"2020-08-25T00:36:49.69005Z\",\n \"endTimestamp\": \"2020-11-28T13:00:00Z\"\n },\n {\n \"dayRangeMin\": 0,\n \"dayRangeMax\": 1,\n \"percentageRefundable\": 0,\n \"startTimestamp\": \"2020-11-28T13:00:00Z\",\n \"endTimestamp\": \"2020-11-29T13:00:00Z\"\n }\n ]\n}\n```\n\n### Post-travel cancellations\n\nOccasionally, customers seek a refund for a product **after** completing their travels.\n\nThe reason for this might be because they were unable to attend the tour due to the supplier having cancelled the tour due to bad weather or other reasons beyond the customer's control; or, the customer might have been extremely dissatisfied with the tour itself, felt that it was misrepresented in its advertising, or some other serious complaint.\n\nWhen this occurs, you will need to [send a refund request by email to dpsupport](mailto:dpsupport@viator.com) and include both \"CANCEL\" and the booking reference number in the subject line.\n\nFor **all** post-travel cancellation requests, you will need to include a detailed description of the issue. \n\nExcept in cases of known service interruptions (e.g., due to\ \ extreme weather events), we will first verify the issue and seek authorization from the product supplier. \n\nOnce a decision regarding the refund has been made, we will notify your Customer Services Department with this information. You will then need to advise your customer directly and process the refund if granted.\n\n### Partial refunds\n\nWhile we recommend that merchant partners support the processing of partial refunds for their customers, it is ultimately up to the partner whether to implement this functionality. \n\nIf you would prefer to only grant the full (100%) refund that is offered on most products so long as the cancellation is processed more than 24 hours prior to the product's start time, we recommend that you implement logic that checks whether a 100% refund is available for the product at the time the customer wishes to cancel their booking.\n\n| **Type 1: Standard policy** (`cancellationPolicy.type` is `\"STANDARD\"`) |\n|-------------------------------------------------------------|\n| The 100% refund is available so long as the cancellation is performed more than 24 hours prior to the product start time |\n\n| **Type 2: Custom policy** (`cancellationPolicy.type` is `\"CUSTOM\"`) |\n|-----------------------------------------------------------|\n| You will need to check whether any of the canellation policy objects in the `refundEligibility` array have: |\n\n| **Type 3: All sales final** (`cancellationPolicy.type` is `\"ALL_SALES_FINAL\"`)|\n|-------------------------------------------------------------|\n| No refunds are available (except in the case of manual confirmation products that are still in a 'pending' state and special exceptions for post-trip cancellations); therefore, under normal conditions, if you grant a refund to your customer for this kind of product, it will be solely at *your* expense (i.e., you will still be invoiced for the cost of the product by Viator). Therefore, we recommend that you do not allow refunds for products with this policy. |\n\n## Per-person and unit pricing\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nThe products in our catalogue fall into two pricing categories: **per-person** and **unit** pricing.\n\nA product's pricing category is given in the `pricingInfo.type` field of the product content response. Depending on whether the product has per-person or unit pricing, this value will be `\"PER_PERSON\"` or `\"UNIT\"`, respectively.\n\nFor more information, see this article: [Per-person and unit pricing](https://partnerresources.viator.com/travel-commerce/merchant/pricing/?source=specs#per-person-unit-pricing).\n\n### Per-person pricing\n\nIf the pricing is *per-person*, then the total price of the booking will be directly proportional to the number of participants (passengers) of each age-band type that are being booked for the product; i.e., a direct multiple of the per-person price.\n\nFor example:\n\n```json\n\"pricingInfo\": {\n \"type\": \"PER_PERSON\",\n \"ageBands\": [\n {\n \"ageBand\": \"CHILD\",\n \"startAge\": 3,\n \"endAge\": 12,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 6\n },\n {\n \"ageBand\": \"ADULT\",\n \"startAge\": 13,\n \"endAge\": 99,\n \"minTravelersPerBooking\": 2,\n \"maxTravelersPerBooking\": 6\n }\n ]\n},\n```\n\n### Per-unit pricing\n\nIf the product has *unit* pricing, then the total price of the booking will depend on the number of units (groups) and types of unit that ideally accommodate the participant mix. Additionally, the `pricingInfo` object in the response will specify the type of unit in the `unitType` field; e.g., in this case, `\"VEHICLE\"`:\n\n```json\n\"pricingInfo\": {\n \"type\": \"UNIT\",\n \"ageBands\": [\n {\n \"ageBand\": \"TRAVELER\",\n \"startAge\": 0,\n \"endAge\": 99,\n \"minTravelersPerBooking\": 1,\n \"maxTravelersPerBooking\": 8\n }\n ],\n \"unitType\": \"VEHICLE\"\n}\n``` \n\nThe `unitType` will be one of:\n\n\n| `unitType` | Example product | Meaning |\n|-------------|-----------------|---------|\n| `\"GROUP\"` | [10847P42](https://www.viator.com/tours/Berlin/In-Search-of-Jewish-Berlin-3-hour-Private-History-Tour-with-a-Scholar-Guide/d488-10847P42) | **Per-group** pricing – the unit price is calculated according to the number of groups the specified passenger mix will fit into rather than the exact number of participants. `minTravelersPerBooking` and `maxTravelersPerBooking` must be considered as these fields relate to the available group sizes. |\n| `\"ROOM\"` | [16621P2](https://www.viator.com/tours/Maharashtra/Stay-package-with-amusement-park-for-2pax-for-2-nights/d25170-16621P2) | **Per-room** pricing relates the room price, which depends on the number of participants making the booking. |\n| `\"PACKAGE\"` | [186385P1](https://www.viator.com/tours/Slovenia/VIP-wellness-to-rent/d734-186385P1) | **Per-package** pricing refers to products that are sold as part of a package; for example a family package stipulating a passenger mix of two adults and two children. |\n| `\"VEHICLE\"` | [10175P10](https://www.viator.com/tours/Cannes/Private-Departure-Transfer-from-Cannes-to-Nice-Airport/d786-10175P10) | **Per-vehicle** pricing is calculated according to the number of vehicles required for the specified passenger mix rather than the exact number of participants. `minTravelersPerBooking` and `maxTravelersPerBooking` must be considered as these fields relate to the occupancy limitations for each vehicle. The minimum price will depend on the rate for a single vehicle. |\n| `\"BIKE\"` | [153074P3](https://www.viator.com/tours/Adelaide/Adelaide-90-Minute-Pedicab-Tour-Scenic-Green-and-River-Experience/d376-16810P4) | **Per-bike** pricing – identical to \"per vehicle\", but refers specifically to vehicles that are bikes. |\n| `\"BOAT\"` | [35157P2](https://www.viator.com/tours/British-Virgin-Islands/Private-Sunset-Sail/d809-35157P2) | **Per-boat** pricing – identical to \"per vehicle\", but refers specifically to vehicles that are boats. |\n| `\"AIRCRAFT\"` | [14876P5](https://www.viator.com/tours/Niagara-Falls-and-Around/Air-Taxi-Tour-from-Niagara-to-Toronto-including-Ground-Transport-from-Niagara-Hotels/d773-14876P5) | **Per-aircraft** pricing – identical to \"per vehicle\", but refers specifically to vehicles that are aircraft. | \n\n\n## Low-margin products\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nWhen setting the price at which you sell products on your site, it’s important to remember that the `recommendedRetailPrice` is just the price at which the product is currently advertised on the Viator site and is only a recommendation. \n\nHowever, the `recommendedRetailPrice` may be **less than** the `partnerTotalPrice` (i.e., the amount you will be invoiced for the sale).\n\nIf you sell the product for less than the `partnerTotalPrice`, you will make a loss on that sale.\n\nTherefore, to ensure that you sell the product at a price which guarantees that you receive at least as much as you will be invoiced for, as well as any extra profit margin that you desire to generate, we recommend you include logic to check that these requirements are satisfied by comparing `recommendedRetailPrice` and `partnerTotalPrice` and adjusting the price at which you advertise and sell the product accordingly.\n\n**For example:** If the `partnerTotalPrice` for a product is $100, the `recommendedRetailPrice` is $101, and you require a minimum margin of 5%, you should adjust the price at which you advertise the product to $105.\n\nWhile we do recommend that you set your prices according to the value of `recommendedRetailPrice`, it is ultimately up to you what price you set for the product, bearing in mind that the amount Viator will invoice you for the sale will be the value of `partnerTotalPrice`.\n\nFor more information, see this article about how to deal with [Low-margin products](https://partnerresources.viator.com/travel-commerce/merchant/pricing/?source=specs#low-margin-products).\n\n## Supplier communications\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\n### How can suppliers communicate with end customers?\n\nSuppliers occasionally need to reach out to customers for a variety of reasons, such as:\n\n* Requesting pickup locations, flight details or passenger weight information\n* Providing weather alerts, sold-out notifications or general messaging\n\nTo allow suppliers to contact customers directly, Viator provides **Closed-Loop Communication (CLC)**.\n\n### How to set up CLC for a booking\n\nThe recipient(s) of suppliers' CLC messages is set for each booking at the time of booking by supplying the customer’s email address (`email`) as well as their phone number (`phone`) in the `communication` object in the request sent to the [/booking/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) endpoints when making a booking.\n\nThis will direct CLC messages sent by suppliers directly to that customer's email; no action from your support team will be necessary for suppliers to communicate with customers.\n\nPartners choosing this option should mention to their customers that they are purchasing a product from a third-party supplier, and that they may, therefore, receive communications regarding the purchase directly from that supplier.\n\n#### Note:\n\n* To have a CC of each message a supplier sends to their customer sent to *your* (the partner's) customer support email address (in case further assistance is required) you must include your customer support email address in the `email` field, after the customer's email and separated from that address with a comma.\n\n\n#### Example request body snippet to enable direct CLC\n```json\n{\n ...\n \"communication\": {\n \"email\": \"john.smith@tripadvisor.com\",\n \"phone\": \"+61 4121121121\"\n}\n```\n\n#### Example request body snippet to enable direct CLC with a CC of each message sent to your customer support\n```json\n{\n ...\n \"communication\": {\n \"email\": \"john.smith@tripadvisor.com,customersupport@bookatrip4me.com\",\n \"phone\": \"+61 4121121121\"\n}\n```\n\n\n### Supplier communications without CLC\n\nTo have CLCs from the supplier sent only to your (the merchant's) customer support team, supply the email address of your customer support function in the `email` field of the `communication` object in the request to the [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) endpoints when making a booking.\n\n**Note:** Utilizing this option requires you, the merchant, to manage the final loop of communication with the end customer to ensure that their tour/activity can be fulfilled successfully.\n\n#### Example request body snippet to disable CLC\n```json\n{\n ...\n \"communication\": {\n \"email\": \"customersupport@bookatrip4me.com\",\n \"phone\": \"+61 4121121121\"\n}\n```\n\n### Default behavior\n\nIf an email address is not supplied in the communications object, the default behavior will be to use the partner's customer support email address for correspondence regarding this booking. Please contact your account manager to set or change the customer support email address for your organization. \n\n#### Example request body snippet that would trigger the default behavior\n\n```json\n{\n ...\n \"communication\": {\n \"phone\": \"+61 4121121121\"\n}\n```\n\n### More information\n\nFor additional information about all communications sent by Viator, including CLC, see: [All you need to know about cancellation policies – Managing Communications](https://partnerresources.viator.com/travel-commerce/merchant/cancellation-policies?source=specs#managing-communications).\n\n## Booking questions\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nThe booking-questions functionality of this API allows vital information specified by the supplier about the individual travelers or the group as a whole to be sent to the supplier as part of the request when making a booking using the [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) endpoints.\n\nThe booking questions available for a product are specified in the `bookingQuestions` array in the response from any of the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints) for that product. For example, for the product [10212P2 (Taste of Miami Helicopter Tour)](https://www.viator.com/tours/Miami/Taste-of-Miami-Helicopter-Tour/d662-10212P2), the `bookingQuestions` array is as follows:\n\n```json\n\"bookingQuestions\": [\n \"FULL_NAMES_LAST\",\n \"SPECIAL_REQUIREMENTS\",\n \"FULL_NAMES_FIRST\",\n \"WEIGHT\",\n \"AGEBAND\"\n],\n```\nEach key string (`\"FULL_NAMES_LAST\"`, etc.) identifies a booking question, details about which can be found in the response from the [/products/booking-questions](#operation/productsBookingQuestions) endpoint.\n\nRelevant booking question details in example response snippet from [/products/booking-questions](#operation/productsBookingQuestions):\n\n```json\n\"bookingQuestions\": [\n {\n \"legacyBookingQuestionId\": 23,\n \"id\": \"WEIGHT\",\n \"type\": \"NUMBER_AND_UNIT\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"Traveler weight in pounds or kilograms (required for safety reasons)\",\n \"hint\": \"E.g. 130lbs, 60kg\",\n \"units\": [\n \"kg\",\n \"lbs\"\n ],\n \"required\": \"MANDATORY\"\n },\n {\n \"legacyBookingQuestionId\": 24,\n \"id\": \"FULL_NAMES_FIRST\",\n \"type\": \"STRING\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"First name\",\n \"required\": \"MANDATORY\"\n },\n {\n \"legacyBookingQuestionId\": 25,\n \"id\": \"FULL_NAMES_LAST\",\n \"type\": \"STRING\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"Last name\",\n \"required\": \"MANDATORY\"\n },\n {\n \"legacyBookingQuestionId\": 30,\n \"id\": \"AGEBAND\",\n \"type\": \"STRING\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"Age band\",\n \"allowedAnswers\": [\n \"ADULT\",\n \"SENIOR\",\n \"YOUTH\",\n \"CHILD\",\n \"INFANT\",\n \"TRAVELER\"\n ],\n \"required\": \"MANDATORY\"\n },\n {\n \"legacyBookingQuestionId\": 27,\n \"id\": \"SPECIAL_REQUIREMENTS\",\n \"type\": \"STRING\",\n \"group\": \"PER_BOOKING\",\n \"label\": \"Special requirements\",\n \"required\": \"OPTIONAL\"\n },\n ...\n]\n```\n\nThe `required` field indicates whether an answer to the booking question must be provided in the booking request. It is necessary to provide an answer to all specified booking questions for which `required` is `MANDATORY`. \n\nAdditionally, the `group` field indicates whether an answer to the booking question must be answered for each traveler (`\"PER_TRAVELER\"`) or for the booked group as a whole (`\"PER_BOOKING\"`).\n\nIn this case:\n\n| Booking question id | required | group |\n|---------------------|----------|-------|\n| `\"WEIGHT\"` | `\"MANDATORY\"` | `\"PER_TRAVELER\"` |\n| `\"FULL_NAMES_FIRST\"` | `\"MANDATORY\"` | `\"PER_TRAVELER\"` |\n| `\"FULL_NAMES_LAST\"` | `\"MANDATORY\"` | `\"PER_TRAVELER\"` |\n| `\"AGEBAND\"` | `\"MANDATORY\"` | `\"PER_TRAVELER\"` |\n| `\"SPECIAL_REQUIREMENTS\"` | `\"OPTIONAL\"` | `\"PER_BOOKING\"` |\n\nTherefore, to book this product, you must provide an answer to the `\"WEIGHT\"`, `\"FULL_NAMES_FIRST\"`,`\"FULL_NAMES_LAST\"` and `\"AGEBAND\"` questions for each traveler, and, optionally (if specified by the user at the time of booking) `\"SPECIAL_REQUIREMENTS\"` for the booked group.\n\nAnswers to the booking questions are sent in the `bookingQuestionAnswers[]` array in the request to [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook). The following example shows a valid and complete set of booking-question answers for this product.\n\n| Traveler number | First name | Last name | age band |\n|-----------------|------------|-----------|----------|\n| 1 | John | Smith | ADULT |\n| 2 | Mary | Jones | ADULT | \n\n```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"Smith\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"John\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"Jones\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"Mary\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"SPECIAL_REQUIREMENTS\",\n \"answer\": \"NO\"\n }\n]\n```\n\n### When to use `travelerNum`\n\nPlease note that `travelerNum` indicates which traveler the answer pertains to. All `PER_TRAVELER` questions must be answered for all travelers in the booking. `travelerNum` **must** be omitted for `PER_BOOKING` booking questions.\n\n### Booking questions with units\n\nSome booking questions require you to specify the unit type when providing an answer to the questions.\n\n**Example: 'HEIGHT' booking question**\n\n\nDefinition of question from [/products/booking-questions](#operation/productsBookingQuestions):\n```json\n{\n \"legacyBookingQuestionId\": 2,\n \"id\": \"HEIGHT\",\n \"type\": \"NUMBER_AND_UNIT\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"Traveler height in feet or centimeters (required for safety reasons)\",\n \"hint\": \"E.g. 5'2\\\", 158cm\",\n \"units\": [\n \"cm\",\n \"ft\"\n ],\n \"required\": \"MANDATORY\"\n},\n```\n\nA valid answer to this booking question for a traveler who is 193 centimetres tall is as follows:\n\n```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"HEIGHT\",\n \"answer\": \"193\",\n \"unit\": \"cm\",\n \"travelerNum\": 1\n }\n]\n```\n\n**Example: 'WEIGHT' booking question**\n\nDefinition of question from [/products/booking-questions](#operation/productsBookingQuestions):\n\n```json\n{\n \"legacyBookingQuestionId\": 23,\n \"id\": \"WEIGHT\",\n \"type\": \"NUMBER_AND_UNIT\",\n \"group\": \"PER_TRAVELER\",\n \"label\": \"Traveler weight in pounds or kilograms (required for safety reasons)\",\n \"units\": [\n \"kg\",\n \"lbs\"\n ],\n \"required\": \"MANDATORY\",\n \"maxLength\": 50\n},\n```\n\nA valid answer to this booking question for a traveler who weighs 69 kilograms would be as follows:\n\n```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"WEIGHT\",\n \"answer\": \"69\",\n \"unit\": \"kg\",\n \"travelerNum\": 1\n }\n]\n```\n\n\n### Booking questions with allowed answers\n\nSome booking questions must be answered in a specific way. These questions include an `allowedAnswers` array containing the set of valid answers to the question.\n\nExample booking question with allowed answers:\n\n```json\n{\n \"legacyBookingQuestionId\": 31,\n \"id\": \"TRANSFER_ARRIVAL_MODE\",\n \"type\": \"STRING\",\n \"group\": \"PER_BOOKING\",\n \"label\": \"Arrival mode\",\n \"allowedAnswers\": [\n \"AIR\",\n \"RAIL\",\n \"SEA\",\n \"OTHER\"\n ],\n \"required\": \"MANDATORY\"\n}\n```\n\nA valid answer to this booking question would be:\n\n```json\n{\n \"question\": \"TRANSFER_ARRIVAL_MODE\",\n \"answer\": \"AIR\"\n},\n```\n\nNote:\n\n- Not all allowed answers are applicable to all products, so you should not always display all 4 arrival/departure modes for all products. You should validate the arrival/departure modes based on the presence of questions applicable to a specific arrival/departure mode for each product.\n- These questions will help you identify arrival modes available for a product:\n + `\"AIR\"`: `\"TRANSFER_AIR_ARRIVAL_AIRLINE\"`, `\"TRANSFER_AIR_ARRIVAL_FLIGHT_NO\"`\n + `\"SEA\"`: `\"TRANSFER_PORT_ARRIVAL_TIME\"` (`\"TRANSFER_PORT_CRUISE_SHIP\"` applies also to departure mode)\n + `\"RAIL\"`: `\"TRANSFER_RAIL_ARRIVAL_LINE\"`, `\"TRANSFER_RAIL_ARRIVAL_STATION\"`\n- If any of these questions is returned (even just one), the relevant option for arrival mode applies. Once an arrival mode is selected, travellers are required to answer all questions related to the selected arrival mode that are returned for the product in the bookingQuestions array (see the table below).\n- The same applies in case of departure modes, you need to look for these questions specific to each departure mode:\n + `\"AIR\"`: `\"TRANSFER_AIR_DEPARTURE_AIRLINE\"`, `\"TRANSFER_AIR_DEPARTURE_FLIGHT_NO\"`\n + `\"SEA\"`: `\"TRANSFER_PORT_DEPARTURE_TIME\"` (`\"TRANSFER_PORT_CRUISE_SHIP\"` applies also to arrival mode)\n + `\"RAIL\"`: `\"TRANSFER_RAIL_DEPARTURE_LINE\"`, `\"TRANSFER_RAIL_DEPARTURE_STATION\"`\n- If these questions are not returned, the departure mode doesn't apply. Once a departure mode is selected, travellers are required to answer all questions related to the selected departure mode that are returned for the product in the bookingQuestions array (see the table below).\n\nWe recommend partners to translate these answers to natural language on their platforms, see recommendation below:\n\n- `\"AIR\"` - airport\n- `\"RAIL\"` - train station\n- `\"SEA\"` - port\n- `\"OTHER\"` - hotel / specific address\n\n\n### Conditional booking questions\n\nThere are some booking questions that may or may not have to be answered, depending on the presence of – or answer to – another booking question. These questions are 'conditional', as indicated by the `required` field containing `\"CONDITIONAL\"`; e.g.:\n\n```json\n{\n \"legacyBookingQuestionId\": 7,\n \"id\": \"TRANSFER_AIR_ARRIVAL_AIRLINE\",\n \"type\": \"STRING\",\n \"group\": \"PER_BOOKING\",\n \"label\": \"Name of arrival airline\",\n \"hint\": \"E.g. United Airlines\",\n \"required\": \"CONDITIONAL\",\n \"maxLength\": 255\n},\n```\n\nSo, when is an answer to a `\"CONDITIONAL\"` booking question required?\n\nAt present, the logic cannot be inferred from the response from the [/products/booking-questions](#operation/productsBookingQuestions) endpoint, but it can be explained here. You will need to hard-code this logic into your implementation in order to correctly present the required booking questions to the user.\n\nThe logic runs as follows:\n\n| For this booking question | if the user's answer is | these questions must also be answered |\n|--------------------|----------------|-------------------------------|\n| `\"TRANSFER_ARRIVAL_MODE\"` | `\"AIR\"` | `\"TRANSFER_AIR_ARRIVAL_AIRLINE\"`
`\"TRANSFER_AIR_ARRIVAL_FLIGHT_NO\"`
`\"TRANSFER_ARRIVAL_TIME\"`
`\"TRANSFER_ARRIVAL_DROP_OFF\"` (see condition 1)
`\"PICKUP_POINT\"` (see condition 1) |\n| `\"TRANSFER_ARRIVAL_MODE\"` | `\"RAIL\"` | `\"TRANSFER_RAIL_ARRIVAL_LINE\"`
`\"TRANSFER_RAIL_ARRIVAL_STATION\"`
`\"TRANSFER_ARRIVAL_TIME\"`
`\"TRANSFER_ARRIVAL_DROP_OFF\"` |\n| `\"TRANSFER_ARRIVAL_MODE\"` | `\"SEA\"` | `\"TRANSFER_PORT_ARRIVAL_TIME\"`
`\"TRANSFER_PORT_CRUISE_SHIP\"`
`\"TRANSFER_ARRIVAL_DROP_OFF\"` (see condition 2)
`\"PICKUP_POINT\"` (see condition 2)|\n| `\"TRANSFER_ARRIVAL_MODE\"` | `\"OTHER\"` | `\"PICKUP_POINT\"` (see condition 3) |\n| `\"TRANSFER_DEPARTURE_MODE\"` | `\"AIR\"` | `\"TRANSFER_AIR_DEPARTURE_AIRLINE\"`
`\"TRANSFER_AIR_DEPARTURE_FLIGHT_NO\"`
`\"TRANSFER_DEPARTURE_DATE\"`
`\"TRANSFER_DEPARTURE_TIME\"`
`\"TRANSFER_DEPARTURE_PICKUP\"` |\n| `\"TRANSFER_DEPARTURE_MODE\"` | `\"RAIL\"` | `\"TRANSFER_RAIL_DEPARTURE_LINE\"`
`\"TRANSFER_RAIL_DEPARTURE_STATION\"`
`\"TRANSFER_DEPARTURE_DATE\"`
`\"TRANSFER_DEPARTURE_TIME\"`
`\"TRANSFER_DEPARTURE_PICKUP\"` |\n| `\"TRANSFER_DEPARTURE_MODE\"` | `\"SEA\"` | `\"TRANSFER_PORT_CRUISE_SHIP\"`
`\"TRANSFER_DEPARTURE_DATE\"`
`\"TRANSFER_PORT_DEPARTURE_TIME\"`
`\"TRANSFER_DEPARTURE_PICKUP\"`|\n| `\"TRANSFER_DEPARTURE_MODE\"` | `\"OTHER\"` | n/a (see condition 4) |\n\n**Conditions**:\n\n1. Rule applies only if `logistics.travelerPickup.locations[]` includes an item with `pickupType`: `\"AIRPORT\"`; **or**, if `logistics.travelerPickup.allowCustomTravelerPickup` is **true**. `\"PICKUP_POINT\"` answer must be a location for which `pickupType` is `\"AIRPORT\"` if answer to `\"TRANSFER_ARRIVAL_MODE\"` is `\"AIR\"`.\n2. Rule applies only if `logistics.travelerPickup.locations[]` includes an item with `pickupType`: `\"PORT\"`; **or**, if `logistics.travelerPickup.allowCustomTravelerPickup` is **true**. `\"PICKUP_POINT\"` answer must be a location for which `pickupType` is `\"PORT\"` if answer to `\"TRANSFER_ARRIVAL_MODE\"` is `\"SEA\"`.\n3. Rule applies only if `logistics.travelerPickup.locations[]` includes an item with `pickupType`: `\"HOTEL\"` or `pickupType`: `\"LOCATION\"` or `pickupType`: `\"OTHER\"`; **or**, if `logistics.travelerPickup.allowCustomTravelerPickup` is **true**.\n4. This question may only be answered `\"OTHER\"` if `\"OTHER\"` is also an available option for the `\"TRANSFER_ARRIVAL_MODE\"` booking question.\n\n**Extra notes**:\n\n- Not all allowed answers are applicable to all products, so you don’t have to always display all 4 arrival/departure modes. For each prodyct, you must validate if arrival/departure modes apply by checking if questions applicable to a specific arrival/departure are present. Read more about this validation here: [Booking questions with allowed answers](#section/Booking-concepts/Booking-questions).\n- All `\"CONDITIONAL\"` booking questions that depend on the answer given to either `\"TRANSFER_ARRIVAL_MODE\"` or `\"TRANSFER_DEPARTURE_MODE\"` (i.e., those questions in the right-hand column in the table above) should be considered `\"MANDATORY\"` if they are stipulated in the `\"bookingQuestions\"` array of the product content response, and the respective transfer mode question **is not** stipulated. That is to say, for example, if `\"TRANSFER_AIR_ARRIVAL_AIRLINE\"` is present, but `\"TRANSFER_ARRIVAL_MODE\"` is absent from `\"bookingQuestions\"`, then `\"TRANSFER_AIR_ARRIVAL_AIRLINE\"` should be considered `\"MANDATORY\"`.\n- The `\"TRANSFER_PORT_CRUISE_SHIP\"` question is required to be answered when the customer's response to either `\"TRANSFER_ARRIVAL_MODE\"` or `\"TRANSFER_DEPARTURE_MODE\"` is `\"SEA\"`; however, this question must only be answered **once** per booking. I.e., the answer for `\"TRANSFER_PORT_CRUISE_SHIP\"` pertains to both questions. There is no provision for the customer to specify different cruise ships for arrival and departure.\n- Please note that the inclusion of the `\"TRANSFER_ARRIVAL_MODE\"`, `\"TRANSFER_DEPARTURE_MODE\"` or their corollary conditional booking questions **does not necessarily imply that pickup is offered** for the product or product option being booked. It may be that these relate to another aspect of the service being offered; for example, an airport greeting product. When returned for a product, these questions must be answered.\n- The `\"TRANSFER_ARRIVAL_DROP_OFF\"` and `\"TRANSFER_DEPARTURE_PICKUP\"` questions are related to locations (arrival drop off and departure pickup) however there are no specific location references or conditions that apply to these questions (see the table). Therefore, customers should be provided with a freetext input field for these questions and the answers must include the FREETEXT designation if the customer answered freely, via text.\n- Whether or not pickup is available should be determined at the product level by the value of `logistics.travelerPickup.pickupOptionType` being either `\"PICKUP_EVERYONE\"` or `\"PICKUP_AND_MEET_AT_START_POINT\"` and not `\"MEET_EVERYONE_AT_START_POINT\"`; or, the presence of the phrase `\"pickup included\"` in the `productOptions[].description` field for the product option.\n- Pickup must be validated on the product option level. It’s possible that the product has multiple product options with a different setup for each one - i.e. one product option offers pickup, another product option requires to meet at the meeting point. The correct validation must be applied as described here: [How to determine if a product option supports pickup.](#section/Booking-concepts/Booking-questions)\n- `logistics.travelerPickup.pickupOptionType` in the product content response could return `\"PICKUP_AND_MEET_AT_START_POINT\"` for products that don't have product options. In such cases travelers should be allowed to either select a pickup location, or decide to meet at the meeting point.\n- Pickup locations shouldn't be displayed at checkout for product options without pickup (this includes the option to contact the supplier later). Please refer to the 'Pickup point question' section below for further details on how to handle pickups.\n\n### Pickup point question\n\nThe booking question that requests the location for pickup is as follows:\n\n```json\n{\n \"legacyBookingQuestionId\": 6,\n \"id\": \"PICKUP_POINT\",\n \"type\": \"LOCATION_REF_OR_FREE_TEXT\",\n \"group\": \"PER_BOOKING\",\n \"label\": \"Hotel pickup\",\n \"hint\": \"E.g. 1234 Cedar Way, Brooklyn NY 00123\",\n \"units\": [\n \"LOCATION_REFERENCE\",\n \"FREETEXT\"\n ],\n \"required\": \"CONDITIONAL\",\n \"maxLength\": 1000\n}\n```\n\nAs you can see, this question can be answered using a location reference or 'freetext' (i.e., a written address in this context). Whether freetext is allowed for this answer depends on the value of `logistics.travelerPickup.allowCustomTravelerPickup` in the response from any of the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints). If `true`, freetext is allowed. Otherwise, a location reference – in particular, one of the location references included in the `logistics.travelerPickup.locations[]` array – must be supplied.\n\nExample `\"FREETEXT\"` answer:\n\n```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"PICKUP_POINT\",\n \"answer\": \"1234 Cedar Way, Brooklyn NY 00123\",\n \"unit\": \"FREETEXT\"\n }\n]\n```\n\nExample `\"LOCATION_REFERENCE\"` answer:\n\n```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"PICKUP_POINT\",\n \"answer\": \"LOC-6cb31b00-1fb4-4218-9b50-63f66531d735\",\n \"unit\": \"LOCATION_REFERENCE\"\n }\n]\n```\n\n#### Special pickup-point location references\n\nThe `logistics.travelerPickup.locations[]` array in the response from the product content endpoints contains the location references for all available pickup locations for a product.\n\nAs well as standard location reference codes; e.g., \"LOC-6cb31b00-1fb4-4218-9b50-63f66531d735\", there are two special codes that specify **instructions** rather than locations. \n\nThese are:\n\n- `\"MEET_AT_DEPARTURE_POINT\"`\n- `\"CONTACT_SUPPLIER_LATER\"`\n\nWhen selecting available pickup points, our suppliers also have the option of specifying one or both of these pseudo-locations. These instruct the customer to either meet at one of the locations specified in `logistics.start[]`, or to contact the supplier later to arrange a pickup point, respectively.\n\nWhen building a list of available pickup locations for the customer to select at the time of booking, the descriptive text for these locations can be used. This is available from the [/locations/bulk](#operation/locationsBulk) endpoint in the `name` field, as follows:\n\n```json\n{\n \"locations\": [\n {\n \"provider\": \"TRIPADVISOR\",\n \"reference\": \"CONTACT_SUPPLIER_LATER\",\n \"name\": \"I will contact the supplier later\"\n },\n {\n \"provider\": \"TRIPADVISOR\",\n \"reference\": \"MEET_AT_DEPARTURE_POINT\",\n \"name\": \"I will meet at the departure point\"\n }\n ]\n}\n```\n\nOr, you can provide a selection button in your UI, as we have done on the [viator.com](https://viator.com) site:\n\n
\n \"I\n
\"I will select my pickup location later\" example from viator.com
\n
\n\nThis button appears when the `\"CONTACT_SUPPLIER_LATER\"` location reference is included in the `logistics.travelerPickup.locations[]` array.\n\n\n#### How to determine if a product option supports pickup\n\nWhen the value of `logistics.travelerPickup.pickupOptionType` in the product content response is `\"PICKUP_AND_MEET_AT_START_POINT\"`, it means that the product includes both 'hotel pickup' and 'meet at the departure point' variants in its product options. One product option may be for hotel pickup while another is for meeting at the start/departure point, so you must always check each option's logistics details. To determine which product options offer what, it is necessary to inspect each product option's details in the `productOptions[]` array in the product content response.\n\n**Scenario 1, Pickup included:** \nIf pickup is included for a product option, the `productOptions.logistics.travelerPickup.pickupOptionType` returns `\"PICKUP_AND_MEET_AT_START_POINT\"`. \n\nWhen booking a **product option with pickup included**, such as this, you must collect a pickup point from the user that corresponds to one of the entries in the `productOptions.logistics.travelerPickup.locations[]` array in the product option content response. In this scenario you must not use the data returned at product-level.\n\n```json\n{\n \"productOptionCode\": \"TG13\",\n \"description\": \"Guide anglophone : Guide parlant anglais avec prise en charge à l'hôtel.\\nService de prise en charge compris\",\n \"title\": \"Visite Anglaise avec prise en charge\",\n \"logistics\": {\n \"start\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5JOkQupk6XB3ZGmKbXXsO/YJsoMrLjHKBLlR6YXSp+r2\"\n },\n \"description\": \"Rencontre avec le groupe au Samsen Centre Restaurant ( Samsen Soi 2 , près de Nouvo City Hotel ) \"\n },\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5IZzQLYGZXKNHze5ORom1qIr4+647kvt/tTz68opRtEL\"\n },\n \"description\": \"Notre point de rendez-vous à BigCountry Old Town situé à côté du Starbucks Coffee @ The Old Siam Plaza pour le créneau horaire de 8h30, pour les clients séjournant à Khaosan, Pra Nakorn, China Town\"\n },\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5NtB8oYNy1V51j3wDEuW3eLTBY+WpoKX+Etl8hTKccw6\"\n },\n \"description\": \"River City Bangkok, The Anchor of Arts & Antiques est un centre commercial de Bangkok, en Thaïlande. Il se trouve sur la rivière Chao Phraya, sur la jetée de Si Phraya, à proximité de nombreux grands hôtels. Il est accessible en voiture ou en bateau. Le créneau horaire de 9h00 correspond aux clients qui séjournent dans les quartiers de Silom, Sathorn et Bangrak.\"\n }\n ],\n \"end\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5JOkQupk6XB3ZGmKbXXsO/YJsoMrLjHKBLlR6YXSp+r2\"\n },\n \"description\": \"Déposer au restaurant Samsen Centre pour le client qui part de Khaosan Area\"\n },\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5O9X4lT3Avg+rvKxoSJGnTIJr39qTywftTM5SgCNpowi\"\n },\n \"description\": \"Déposer au MBK Center , facile à connecter au BTS (train Sky) pour le client qui part du point de rendez-vous de River City\"\n }\n ],\n \"travelerPickup\": {\n \"pickupOptionType\": \"PICKUP_AND_MEET_AT_START_POINT\",\n \"allowCustomTravelerPickup\": true,\n \"locations\": [\n {\n \"location\": {\n \"ref\": \"MEET_AT_DEPARTURE_POINT\"\n },\n \"pickupType\": \"OTHER\"\n },\n {\n \"location\": {\n \"ref\": \"CONTACT_SUPPLIER_LATER\"\n },\n \"pickupType\": \"OTHER\"\n },\n {\n \"location\": {\n \"ref\": \"LOC-6eKJ+or5y8o99Qw0C8xWyKrhcZh+/RSI01IBRs/OIZo=\"\n },\n \"pickupType\": \"HOTEL\"\n }\n ]\n }\n }\n}\n```\n\nAll booking questions related to arrival/departure must be displayed as normal to allow customers to select the desired arrival/departure mode and provide all relevant information to the supplier before travel. All answers provided by the customer must be captured and submitted in the booking request following the logic for conditional booking questions from the [**table in the API documentation**](https://docs.viator.com/partner-api/technical/#section/Booking-concepts/Booking-questions).\n\n**Scenario 2, No Pickup (Meeting Point Only):** \nIf the productOption doesn't support pickup, the API will now explicitly return `\"MEET_EVERYONE_AT_START_POINT\"` at the Tour Grade level instead and should be considered to follow a `\"MEET_AT_DEPARTURE_POINT\"` arrangement, reducing all ambiguity. \nThe following product option (also from product [**8374P24**](https://www.viator.com/tours/Bangkok/Train-Market-and-Damnoensaduak-Floating-Market-with-small-group/d343-8374P24)) requires meeting at the departure point and does not include pickup:\n\n```json\n{\n \"productOptionCode\": \"TG3\",\n \"description\": \"Point de rencontre : Rendez-vous au River City Bangkok, dépose au MBK Mall. Créneau horaire 9h00.\\nPoint de départ :\\nRiver City Bangkok, 23 Soi Charoen Krung 24, Khwaeng Talat Noi, Khet Samphanthawong, Krung Thep Maha Nakhon 10100, Thaïlande\",\n \"title\": \"Ville fluviale Bangkok\",\n \"logistics\": {\n \"start\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5NtB8oYNy1V51j3wDEuW3eLTBY+WpoKX+Etl8hTKccw6\"\n },\n \"description\": \"River City Bangkok, The Anchor of Arts & Antiques est un centre commercial de Bangkok, en Thaïlande. Il se trouve sur la rivière Chao Phraya, sur la jetée de Si Phraya, à proximité de nombreux grands hôtels. Il est accessible en voiture ou en bateau. Le créneau horaire de 9h00 correspond aux clients qui séjournent dans les quartiers de Silom, Sathorn et Bangrak.\"\n }\n ],\n \"end\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5JOkQupk6XB3ZGmKbXXsO/YJsoMrLjHKBLlR6YXSp+r2\"\n },\n \"description\": \"Déposer au restaurant Samsen Centre pour le client qui part de Khaosan Area\"\n },\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5O9X4lT3Avg+rvKxoSJGnTIJr39qTywftTM5SgCNpowi\"\n },\n \"description\": \"Déposer au MBK Center , facile à connecter au BTS (train Sky) pour le client qui part du point de rendez-vous de River City\"\n }\n ],\n \"travelerPickup\": {\n \"pickupOptionType\": \"MEET_EVERYONE_AT_START_POINT\",\n \"allowCustomTravelerPickup\": false,\n \"locations\": [\n {\n \"location\": {\n \"ref\": \"MEET_AT_DEPARTURE_POINT\"\n },\n \"pickupType\": \"OTHER\"\n }\n ]\n }\n }\n}\n```\n\nIn case of product options without pickup, you shouldn't ask arrival or departure-related questions at checkout (but you will still need to answer the questions returned in the API using values hardcoded into your implementation). If you wish, you can display at checkout the meeting point location(s) for informational purposes (not collecting answers) but not the pickup locations and no questions related to arrival/departure should be displayed in that case.\n\nThe option to contact the supplier later (`\"CONTACT_SUPPLIER_LATER\"`) doesn't apply to this scenario either and should not be present as it applies only to product options with pickup.\n\nIn the answer to the `\"PICKUP_POINT\"` question, you will need to send the location reference `\"MEET_AT_DEPARTURE_POINT\"` (returned under `travelerPickup.locations`). In case the product returns the `\"TRANSFER_ARRIVAL_MODE\"` or `\"TRANSFER_DEPARTURE_MODE\"` questions, these must be answered with `\"OTHER\"`. \n\nProduct examples for testing: [**9025P51**](https://www.viator.com/tours/Belize-City/Private-Cave-Tubing-and-Zipline-Adventure-from-Belize-City/d5094-9025P51), [**62450P1**](https://www.viator.com/tours/Curacao/Guided-paddleboarding-SUP-mangrove-ECO-tour-for-beginners/d725-62450P1).\n\n**When other product options support transfer pickup**: \n\nWhile you might be booking a product option that **does not** support pickup, if the overall product itself supports, for example, pickup from an airport, in one of its *other* product options, it will contain the `\"TRANSFER_ARRIVAL_MODE\"` booking question in the `bookingQuestions[]` array in the product content response. \n\nThis means that this booking question, because it is `\"MANDATORY\"`, **must be answered** in order to make a valid booking, even though such information would be irrelevant in this context.\n\nTransfer arrival mode question details from [/products/booking-questions](#operation/productsBookingQuestions):\n\n```json\n{\n \"legacyBookingQuestionId\": 31,\n \"id\": \"TRANSFER_ARRIVAL_MODE\",\n \"type\": \"STRING\",\n \"group\": \"PER_BOOKING\",\n \"label\": \"Arrival mode\",\n \"allowedAnswers\": [\n \"AIR\",\n \"RAIL\",\n \"SEA\",\n \"OTHER\"\n ],\n \"required\": \"MANDATORY\"\n}\n```\n\nAs you can see, one of the allowed answers to this question is `\"OTHER\"`.\n\nTherefore, in the case that you must answer this booking question because it is stipulated at the product level, but it does not pertain to the product option being booked, **please do not prompt the user to provide an answer to this question**, rather, have your internal logic send the value `\"OTHER\"` as the answer; i.e.:\n\n ```json\n\"bookingQuestionAnswers\": [ \n {\n \"question\": \"TRANSFER_ARRIVAL_MODE\",\n \"answer\": \"OTHER\"\n },\n ...\n]\n```\n\nThe same applies for the `\"TRANSFER_DEPARTURE_MODE\"` booking question, as it is also mandatory and can be validly answered as `\"OTHER\"`. \n\nThe only `\"CONDITIONAL\"` booking question that must be answered for a product option without pickup (in addition to `\"MANDATORY\"` questions) is `\"PICKUP_POINT\"` (answer: `\"MEET_AT_DEPARTURE_POINT\"`)\n\n**Examples of booking requests**\n\nProduct: 9025P51\n\nProduct option details returned in the product content response:\n\n ```json\n\"productOptions\": [\n {\n \"productOptionCode\": \"TG1\",\n \"description\": \"share Group\",\n \"title\": \"Share Group Tour\",\n \"languageGuides\": [\n {\n \"type\": \"GUIDE\",\n \"language\": \"en\",\n \"legacyGuide\": \"en/SERVICE_GUIDE\"\n },\n {\n \"type\": \"GUIDE\",\n \"language\": \"es\",\n \"legacyGuide\": \"es/SERVICE_GUIDE\"\n }\n ]\n },\n {\n \"productOptionCode\": \"TG2\",\n \"description\": \"From 2 to 25 people traveling together on a private tour
Pickup included\",\n \"title\": \"Private Tour\",\n \"languageGuides\": [\n {\n \"type\": \"GUIDE\",\n \"language\": \"en\",\n \"legacyGuide\": \"en/SERVICE_GUIDE\"\n },\n {\n \"type\": \"GUIDE\",\n \"language\": \"es\",\n \"legacyGuide\": \"es/SERVICE_GUIDE\"\n }\n ]\n }\n],\n```\n\nExample booking request for product option with pickup (TG2):\n\n ```json\n{\n \"productCode\": \"9025P51\",\n \"productOptionCode\": \"TG2\",\n \"startTime\": \"08:00\",\n \"currency\": \"USD\",\n \"travelDate\": \"2024-11-27\",\n \"paxMix\": [\n {\n \"ageBand\": \"ADULT\",\n \"numberOfTravelers\": 2\n }\n ],\n \"partnerBookingRef\": \"test123456\",\n \"languageGuide\": {\n \"type\": \"GUIDE\",\n \"language\": \"en\"\n },\n \"bookerInfo\": {\n \"firstName\": \"XXXX\",\n \"lastName\": \"XXXX\"\n },\n \"bookingQuestionAnswers\": [\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"TRANSFER_ARRIVAL_MODE\",\n \"answer\": \"OTHER\"\n },\n {\n \"question\": \"TRANSFER_DEPARTURE_MODE\",\n \"answer\": \"OTHER\"\n },\n {\n \"question\": \"PICKUP_POINT\",\n \"answer\": \"LOC-6eKJ+or5y8o99Qw0C8xWyGStvfcGJMWF/jrN0iaZD8s=\",\n \"unit\": \"LOCATION_REFERENCE\"\n }\n ],\n \"communication\": {\n \"phone\": \"+44 987667889\",\n \"email\": \"noreply@test.com\"\n },\n \"additionalBookingDetails\": {\n \"voucherDetails\": {\n \"companyName\": \"Test\",\n \"email\": \"customerservice@test.com\",\n \"phone\": \"+44 876778998\",\n \"voucherText\": \"Thank you for booking with us!\"\n }\n }\n}\n```\n\nExample booking request for product option without pickup (TG1):\n\n ```json\n{\n \"productCode\": \"9025P51\",\n \"productOptionCode\": \"TG1\",\n \"startTime\": \"08:00\",\n \"currency\": \"USD\",\n \"travelDate\": \"2024-11-27\",\n \"paxMix\": [\n {\n \"ageBand\": \"ADULT\",\n \"numberOfTravelers\": 2\n }\n ],\n \"partnerBookingRef\": \"test12345\",\n \"languageGuide\": {\n \"type\": \"GUIDE\",\n \"language\": \"en\"\n },\n \"bookerInfo\": {\n \"firstName\": \"XXXX\",\n \"lastName\": \"XXXX\"\n },\n \"bookingQuestionAnswers\": [\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 1\n },\n {\n \"question\": \"AGEBAND\",\n \"answer\": \"ADULT\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_FIRST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"FULL_NAMES_LAST\",\n \"answer\": \"XXXX\",\n \"travelerNum\": 2\n },\n {\n \"question\": \"TRANSFER_ARRIVAL_MODE\",\n \"answer\": \"OTHER\"\n },\n {\n \"question\": \"TRANSFER_DEPARTURE_MODE\",\n \"answer\": \"OTHER\"\n },\n {\n \"question\": \"PICKUP_POINT\",\n \"answer\": \"MEET_AT_DEPARTURE_POINT\",\n \"unit\": \"LOCATION_REFERENCE\"\n }\n ],\n \"communication\": {\n \"phone\": \"+44 987667889\",\n \"email\": \"noreply@test.com\"\n },\n \"additionalBookingDetails\": {\n \"voucherDetails\": {\n \"companyName\": \"Test\",\n \"email\": \"customerservice@test.com\",\n \"phone\": \"+44 876778998\",\n \"voucherText\": \"Thank you for booking with us!\"\n }\n }\n}\n```\n\nTo learn more about booking questions and get a step-by-step guide on how to implement conditional booking questions, see this guide: Implementing Booking Questions.\n\n### Age-bands\n\nIf `\"AGEBAND\"` is specified as a booking question in the `bookingQuestions` array in the product content response, you must supply the age-band for each traveler in `bookingQuestionAnswers` when making the booking using [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook). \n\nFurthermore, the answer(s) to the `\"AGEBAND\"` booking question that you submit in the request to [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) must match the age-bands given in the `paxMix` element in the request to [/bookings/hold](#operation/bookingsHold) or [/bookings/cart/hold](#operation/bookingsCartHold). Otherwise, the booking server will reject the booking on account of the booking and booking-hold not matching.\n\nThe valid age-bands for the product are given in the `pricingInfo` array in the product content response; e.g.:\n\n```json\n\"pricingInfo\": {\n \"type\": \"PER_PERSON\",\n \"ageBands\": [\n {\n \"ageBand\": \"INFANT\",\n \"startAge\": 0,\n \"endAge\": 4,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 9\n },\n {\n \"ageBand\": \"CHILD\",\n \"startAge\": 5,\n \"endAge\": 15,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 9\n },\n {\n \"ageBand\": \"ADULT\",\n \"startAge\": 16,\n \"endAge\": 99,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 9\n }\n ]\n},\n```\n\nNote that if `bookingRequirements.requiresAdultForBooking` is `true` in the product content response, at least one traveler must have an `\"ADULT\"` or `\"SENIOR\"` age-band.\n\nTo learn more about how age-bands are used during the booking process, see the following guide: [Implementing age bands & pax mix](https://partnerresources.viator.com/travel-commerce/merchant/agebands-pax-mix?source=specs).\n\n#### Age-bands with unit pricing\n\nIn the case that the product uses unit pricing; i.e., pricing based on the number of groups of travelers, then the product will have a single available age-band: `\"TRAVELER\"`, as given in the `pricingInfo` array in the product content response; e.g.:\n\n```json\n\"pricingInfo\": {\n \"type\": \"UNIT\",\n \"ageBands\": [\n {\n \"ageBand\": \"TRAVELER\",\n \"startAge\": 0,\n \"endAge\": 99,\n \"minTravelersPerBooking\": 1,\n \"maxTravelersPerBooking\": 10\n }\n ],\n \"unitType\": \"GROUP\"\n}\n```\n\nFor such products, even if `\"AGEBAND\"` is specified as a booking question, the only applicable age-band is `\"TRAVELER\"`. However, you must still supply this value for the age-band booking question for each traveler when making the booking using [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook). Even if `bookingRequirements.requiresAdultForBooking` is `true` for such products, you must still supply the `\"TRAVELER\"` value.\n\n## Booking cutoff times\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nThis section describes how the booking cutoff time information given by the product supplier, which may affect a product's availability (and therefore its ability to be booked) is communicated via this API. While you are welcome to develop logic to support the display and utilisation of this information, **it is not necessary to do so**. Indeed, as most implementations are unlikely to benefit, we recommend simply using the real-time [/availability/check](#operation/availabilityCheck) endpoint as the primary means to determine and communicate a product's availability in your product booking workflow.\n\nMany products in our inventory are subject to a booking cutoff time. Tickets for such products may only be purchased up until a certain time. This information is given in the `bookingConfirmationSettings` object in the [product content response](#section/Key-concepts/Product-content-and-availability-endpoints).\n\nExample `bookingConfirmationSettings` object:\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"START_TIME\",\n \"bookingCutoffInMinutes\": 0,\n \"confirmationType\": \"INSTANT\"\n},\n```\n\nThere are four booking cutoff types, indicated by the value of the `bookingCutoffType` element; they are:\n - `\"START_TIME\"` – booking cutoff is relative to the product's start time\n - `\"OPENING_TIME\"` – booking cutoff is relative to the product's opening time\n - `\"CLOSING_TIME\"` – booking cutoff is relative to the product's closing time\n - `\"FIXED_TIME\"` – booking cutoff is relative to the time given in the `bookingCutoffFixedTime` element\n\nIn addition, the booking cutoff time may be offset by the number of minutes given in `bookingCutoffInMinutes`; for example, product 57377P9's booking cutoff is 120 minutes prior to its start time:\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"START_TIME\",\n \"bookingCutoffInMinutes\": 120,\n \"confirmationType\": \"INSTANT\"\n}\n```\n\nThe availability of products that have a `bookingCutoffType` of `\"START_TIME\"` can be determined by inspecting the `pricingRecords[].timedEntries[].startTime` field in the response from [/availability/schedules/{product-code}](#operation/availabilitySchedules). This type of product can be booked up until `bookingCutoffInMinutes` prior to its starting time in the time-zone in which the product operates, which is given in the `timeZone` field in the [product content response](#section/Key-concepts/Product-content-and-availability-endpoints).\n\nThe booking cutoff time for products with a `\"FIXED_TIME\"` type is that given in the `bookingCutoffFixedTime` element, offset by the number of minutes given in `bookingCutoffInMinutes`. In the fixed time scenario, `bookingCutoffInMinutes` can only be 0, 1440 (24 hours) or 2880 (48 hours). This means that the booking cutoff time is at a certain time on the day on which the product operates; or, at that same time but one or two days before the tour date, respectively.\n\nIn the following example, the booking cutoff is 10:00am on the day before the tour or activity operates:\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"FIXED_TIME\",\n \"bookingCutoffInMinutes\": 1440,\n \"confirmationType\": \"INSTANT\",\n \"bookingCutoffFixedTime\": \"10:00:00\"\n}\n```\n\nYou may not be able to book a product (using [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook)) or place a booking hold on a product using [/bookings/hold](#operation/bookingsHold) or [/bookings/cart/hold](#operation/bookingsCartHold) after it is past the booking cutoff time. However, this is not always the case. Always check real-time availability using the [/availability/check](#operation/availabilityCheck) endpoint.\n\nNonetheless, in displaying the availability of a product on your site, you may wish to mark products as 'unavailable' for a particular day or starting time if it is presently past the booking cutoff time if you feel that doing so will improve your site's UX.\n\nHowever, because the availability schedule data in general can rapidly fall out of date, **we again encourage you to always utilise the real-time [/availability/check](#operation/availabilityCheck) endpoint as the primary means to determine and communicate a product's availability in your product booking workflow.**\n\n## Booking confirmation types\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nA product's booking confirmation type indicates whether the booking will be confirmed or rejected immediately and automatically; or, whether it will remain in a 'pending' state until actioned manually by the supplier.\n\nThe product's booking confirmation type can be identified by the value of `bookingConfirmationSettings.confirmationType` in the product content response. There are three confirmation types: **instant**, **manual** and **instant-then-manual**, represented by the `confirmationType` values `\"INSTANT\"`, `\"MANUAL\"` and `\"INSTANT_THEN_MANUAL\"`, respectively.\n\n### Booking confirmation type in the API\n\n#### Instant confirmation:\n\nInstant confirmation products are confirmed automatically at the time of booking, and the customer should be charged immediately.\n\nE.g. (product-code: 5010SYDNEY):\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"CLOSING_TIME\",\n \"bookingCutoffInMinutes\": 0,\n \"confirmationType\": \"INSTANT\"\n}\n```\n\n#### Manual confirmation\n\nManual confirmation products are those that only operate at the discretion of the supplier, who must confirm or reject each booking request manually. Once the booking is requested, it will remain in a 'pending' state until actioned by the supplier; or, if no action is taken by the supplier, the time-out period (72 hours) is exceeded. The customer should only be charged once confirmation is received.\n\nE.g. (product-code: 161500P1):\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"START_TIME\",\n \"bookingCutoffInMinutes\": 1440,\n \"confirmationType\": \"MANUAL\"\n}\n```\n\n#### Instant-then-manual confirmation\n\nInstant-then-manual confirmation products behave like instant confirmation products up until a certain time prior to the product's starting time. From that point on, the product will require manual confirmation by the supplier.\n\nE.g. (product-code: 100035P1):\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"START_TIME\",\n \"bookingCutoffInMinutes\": 720,\n \"confirmationType\": \"INSTANT_THEN_MANUAL\",\n \"manualConfirmationPeriod\": 2880\n}\n```\n\nThe `manualConfirmationPeriod` indicates when the product changes from instant to manual confirmation. In the example above, this period is 2880 minutes (48 hours or 2 days). Therefore, this product will be confirmed instantly if the booking is made more than 2 days in advance of the start time (in the time zone in which the product operates); if the booking is made less than 2 days in advance, it will require manual confirmation from the supplier.\n\n### How to support manual confirmation products\n\nIn order to support manual confirmation products on your site, you will need to introduce support for an asynchronous flow that monitors the booking's status, determines when its status changes and notifies the customer when their booking has been confirmed or rejected by the supplier.\n\nYou will need to:\n\n- Create back-end logic that periodically checks the status of pending bookings using the [/bookings/status](#operation/bookingsStatus) endpoint (we recommend polling no more than once every 3 minutes)\n- Establish and support an extra, email-based communications channel with your customers\n- Create email templates for the various scenarios that may arise\n- Ensure that your platform's front end accommodates the extra steps required in the booking process\n- Ensure that customers clearly understand that they are booking a product that will not be confirmed or charged immediately\n\n#### Product detail page\n\nManaging customer expectations is a key factor in supporting manual confirmation products on your booking platform. \n\nMake clear mention on the product detail page that confirmation will not be received immediately, but rather within 72 hours of making the booking.\n\nYou are free to include this note in the **Additional Info** section, or elsewhere on your product display page; for example:\n\n
\n \"Manual\n
Manual confirmation info displayed on a product page on the Viator site\n
\n
\n\n#### Check-out\n\nAs you will only charge the customer's credit card once the booking is confirmed by the product's supplier, it's best to display a message to this effect at a prominent point of the check-out flow for all manual confirmation products.\n\n
\n \"Example\n
Example checkout-flow instruction on the Viator site
\n
\n\nIn this way, customers can be reassured that they are not being charged for a booking that may never be confirmed, thereby helping to reduce the number of calls to your customer service team.\n\n#### Combination purchases\n\nIf your customer has both instant and manual booking confirmation products in their shopping cart, only the amount for the confirmed booking(s) should be charged immediately; the portion corresponding to the pending bookings should be held as a pre-authorization against the customer’s credit card, and the transaction completed only once confirmation is received. \n\nIt is important that you clearly differentiate between bookings that have been confirmed and those that are pending confirmation and communicate the status of each item. Also, be sure to make clear that the pre-authorization will only finalize once the manual confirmation bookings are confirmed.\n\n#### Confirmation page\n\nChanges will need to be made to your confirmation page because it will not be possible for your customer to download their voucher immediately after completing a manual confirmation booking. Rather, the voucher will be made available after the booking is confirmed.\n\nVouchers for instant confirmation products, however, must be made available immediately following the completion of the booking process.\n\n#### Customer communications\n\nConfirmation message (e.g., email) templates for manual confirmation bookings should indicate that the item is pending confirmation from the supplier; and, that confirmation for this activity will take up to 72 hours, depending on availability.\n\nYou will also need to create templates for the following scenarios:\n\n- When the manual confirmation booking is confirmed by the supplier (this time including the voucher details)\n- If the manual confirmation booking is rejected\n- If multiple manual confirmation products have been booked:\n + When all items have been accepted/confirmed\n + When there are mixed statuses; i.e., 'pending' + 'rejected' + 'canceled'\n + If all items were rejected\n- If a mixture of instant and manual confirmation products are booked at the same time; i.e., in the same cart\n\n**Note**: When a booking is declined, it is useful to mention that the customer's card was not charged.\n\n##### Example email for a manual confirmation booking pending confirmation:\n\n
\n \"Viator\n \"Viator\n \"Viator\n
\n\n### Confirmation time-outs resulting in rejection\n\nAs mentioned above, when a booking request for a manual confirmation product is made, it will have a status of 'pending' until it is confirmed by the supplier. The supplier has the option of confirming or rejecting the booking.\n\nIf the supplier does not confirm the booking within 72 hours – or, if they have not confirmed the booking by the time it reaches `bookingCutoffInMinutes` from the product's start time or whichever is specified in the `bookingCutoffType` – our systems will automatically reject the booking, and this will be reflected in the response from the [/bookings/status](#operation/bookingsStatus) endpoint.\n\n### Building in the sandbox environment\n\nUpgrading your booking platform to support manual confirmation products will require you to build and test this functionality in the sandbox environment.\n\nThe testing workflow depends on which endpoint you’re using to perform bookings:\n\n\n#### [/bookings/book](#operation/bookingsBook) Endpoint\nIn the sandbox environment, booking requests are not sent to the supplier’s system.\n\nBy default, manual-confirmation products behave like instant-confirmation products and return:\n\n- `bookingStatus = CONFIRMED`\n\nTo simulate the correct manual-confirmation behavior, you must set the request header:\n\n- `exp-demo: false`\n\nWhen `exp-demo` is set to `false, the response will return:\n\n- `bookingStatus = PENDING` (expected behavior for manual-confirmation products)\n\n#### [/bookings/cart/book](#operation/bookingsCartBook) Endpoint\nFor manual-confirmation products, you must set the following request header:\n\n- `exp-demo: false`\n\nThe response will return:\n\n- `bookingStatus = PENDING` (expected manual-confirmation behavior)\n\n#### Completing the Test Flow\n\nTo simulate the final supplier decision, contact API Tech Support at apitechsupport@viator.com and provide the bookingRef to request a status update to:\n\n- `CONFIRMED`, or\n- `REJECTED`\n\n## Making a booking\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nBroadly speaking, to book a product via this API, you must do the following:\n\n1. **Check availability and pricing**: Determine that a ticket for the desired tour or activity is available for a specific date, time and passenger mix combination using the [/availability/check](#operation/availabilityCheck) endpoint. Accurate pricing details in the currency that you wish to be invoiced in (one of GBP, EUR, USD, CAD or AUD) are also returned in the response from this endpoint. This includes `recommendedRetailPrice` and `partnerNetPrice`.

\n2. **Request a booking hold**: If a ticket is available, request a pricing/availability hold for the booking using the [/bookings/hold](#operation/bookingsHold) or [/bookings/cart/hold](#operation/bookingsCartHold) endpoints.

\n3. **Collect payment**: With a booking hold requested and suitable to proceed, collect payment using the iframe solution or via your own payment details form and submit using the API solution. Note: These payment options are only available to affiliate partners with API access level \"Full Access + Booking\".

\n4. **Confirm the booking**: Confirm/finalize the held booking using the [/bookings/book](#operation/bookingsBook) or [/bookings/cart/book](#operation/bookingsCartBook) endpoints.\n\nSee Getting availability and pricing for products and Creating a seamless booking experience for more information.\n\n\n\n## Cancellation API workflow\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nAll booking cancellations (except for those requested after the date of travel) must now be performed via the API. Viator no longer offers ordinary cancellation services via our customer support function. To cancel a booking after the tour or activity has occurred, please contact [Viator Partner Support](mailto:dpsupport@viator.com) \n\nSee our in-depth guide about cancellation policies and how to handle cancellations: [All you need to know about cancellation policies](https://partnerresources.viator.com/travel-commerce/merchant/cancellation-policies/?source=specs).\n\n### Getting cancellation reasons\n\n\nWhen canceling a booking, you are required to submit a valid 'reason for the cancellation' to assist with Viator's internal processes. This is accomplished via the inclusion of a valid reason code in the body of the request. The reason codes can be retrieved from the [/bookings/cancel-reasons](#operation/bookingsCancelReasons) endpoint.\n\nAs the acceptable reasons for cancellation may be altered at any point, we recommend retrieving an up-to-date list from this endpoint at least weekly.\n\nThe output from the [/bookings/cancel-reasons](#operation/bookingsCancelReasons) endpoint at the time of writing is as follows:\n\n```json\n{\n \"reasons\": [\n {\n \"cancellationReasonText\": \"Supplier No Show\",\n \"cancellationReasonCode\": \"Customer_Service.Supplier_no_show\"\n },\n {\n \"cancellationReasonText\": \"Chose a different/cheaper tour\",\n \"cancellationReasonCode\": \"Customer_Service.Chose_a_different_cheaper_tour\"\n },\n {\n \"cancellationReasonText\": \"Unexpected medical circumstances\",\n \"cancellationReasonCode\": \"Customer_Service.Unexpected_medical_circumstances\"\n },\n {\n \"cancellationReasonText\": \"Weather\",\n \"cancellationReasonCode\": \"Customer_Service.Weather\"\n },\n {\n \"cancellationReasonText\": \"Booked wrong tour date\",\n \"cancellationReasonCode\": \"Customer_Service.Booked_wrong_tour_date\"\n },\n {\n \"cancellationReasonText\": \"Duplicate Booking\",\n \"cancellationReasonCode\": \"Customer_Service.Duplicate_Booking\"\n },\n {\n \"cancellationReasonText\": \"Significant global event\",\n \"cancellationReasonCode\": \"Customer_Service.Significant_global_event\"\n },\n {\n \"cancellationReasonText\": \"I canceled my entire trip\",\n \"cancellationReasonCode\": \"Customer_Service.I_canceled_my_entire_trip\"\n }\n ]\n}\n```\n\n### Canceling a booking\n\n#### Getting a cancellation quote\n\nBefore canceling the booking, call the [/bookings/{booking-reference}/cancel-quote](#operation/bookingsCancelQuote) endpoint to get information about whether the booking can be canceled using this endpoint and what the refund will be, for example:\n\n```\nGET https://api.viator.com/partner/bookings/BR-580254558/cancel-quote\n```\n\n- **Note**: For bookings made with v1 of this API, this code corresponds to `data.itemSummaries[].itemId` (in the response from v1's [/booking/book](https://docs.viator.com/partner-api/merchant/technical/#tag/Booking-services/paths/~1booking~1book/post) endpoint) but prepended with `BR-`. For example, if the `itemId` is `580254558`, this field should be `BR-580254558`.\n\nYou will receive a cancellation quote object, e.g.:\n\n```json\n{\n \"bookingId\": \"BR-580254558\",\n \"status\": \"CANCELLABLE\",\n \"refundDetails\": {\n \"itemPrice\": 109.77,\n \"refundAmount\": 109.77,\n \"currencyCode\": \"USD\",\n \"refundPercentage\": 100.00\n }\n}\n```\n\n **Note**: Bookings that have not been confirmed by the supplier and have a status of `\"PENDING\"` will report an `itemPrice`, `refundAmount` and `refundPercentage` of `0`, as no fees are charged until the booking's status is `\"CONFIRMED\"`.\n \n\nThe data elements in this object have meanings as follows:\n\n| Element | Meaning | Example |\n|---------|---------|---------|\n| `bookingId` | the booking reference number prepended with `BR-` | `BR-580254556` |\n| `status` | One of the following: | `CANCELLABLE` |\n| `refundDetails` | object containing information about the refund | |\n| `itemPrice` | the **merchant net price** + **transaction fee** for this product at the time of booking in the currency specified by `currencyCode` | `109.77` |\n| `refundAmount` | the amount that will be deducted from your invoice if the booking is cancelled now | `109.77` |\n| `currencyCode` | the currency code for the currency in which pricing information is displayed | `USD` |\n| `refundPercentage` | the refund amount expressed as a percentage of the `itemPrice` | `100.00` |\n\n\n**Will there ever be a discrepancy between the amount charged for a tour and the amount refunded due to currency exchange-rate fluctuations?**\n\n- In short: no. I.e., if the cost of the booking was USD 100 and the refund percentage is 100% (full refund, as per the response from [/bookings/{booking-reference}/cancel-quote](#operation/bookingsCancelQuote)), Viator will simply **not invoice you** for that USD 100 that we would have if the booking had not been canceled. Furthermore, we do not invoice you for the cost of a booking prior to its departure date.\n\n\n\n#### Requesting the cancellation\n\nIf the `status` field has a value of `CANCELLABLE` and you are happy with the `refundAmount`, call the [/bookings/{booking-reference}/cancel](#operation/bookingsCancel) endpoint to cancel the booking, e.g.:\n\n```\nPOST https://api.viator.com/partner/bookings/BR-580254558/cancel\n```\n\nA reason code corresponding to the reason for cancellation must be included in the request body; e.g.:\n\n```json\n{\n \"reasonCode\":\"Customer_Service.Chose_a_different_cheaper_tour\"\n}\n```\n\nYou should receive a response indicating that the cancellation was successful, e.g.:\n\n```json\n{\n \"bookingId\": \"BR-580254558\",\n \"status\": \"ACCEPTED\"\n}\n```\n\nA `status` of `ACCEPTED` indicates that the booking was successfully canceled.\n\n\n## Checking booking status\n\n**Note**: This section applies to affiliate partners with API access level \"Full Access + Booking\" and merchant partners only.\n\nOnce a booking has been made, you can check on its status using the [/bookings/status](#operation/bookingsStatus) endpoint.\n\nYou can use **either** the `bookingRef` **or** `partnerBookingRef` in the request to this service.\n\n- If the booking was made using v1 of the Viator Partner API, you will receive a HTTP 400 Bad Request response. Only bookings made using v2 or later of this API are compatible with this endpoint.\n- If the booking is the subject of a booking hold (via [/bookings/hold](#operation/bookingsHold) or [/bookings/cart/hold](#operation/bookingsCartHold)) but the booking has not yet been confirmed using [/bookings/book](#operation/bookingsBook), you will receive a HTTP 404 Not Found response.\n- If the booking was confirmed but later canceled, you will receive a HTTP 200 Success response that indicates the canceled status.\n- If the booking has been confirmed and has not been canceled, you will receive a response with the same structure as the response from [/bookings/book](#operation/bookingsBook)\n\n### Confirmed booking\n\n**Example request**: Get the status of the booking with the booking reference `\"BR-791143912\"`\n\n```json\n{\n \"bookingRef\": \"BR-791143912\"\n}\n```\n\n**Example response**: The status of this booking is `\"CONFIRMED\"`\n\n```json\n{\n \"status\": \"CONFIRMED\",\n \"bookingRef\": \"BR-791143912\",\n \"partnerBookingRef\": \"BR-791143912\",\n \"currency\": \"USD\",\n \"lineItems\": [\n {\n \"ageBand\": \"ADULT\",\n \"numberOfTravelers\": 2,\n \"subtotalPrice\": {\n \"price\": {\n \"recommendedRetailPrice\": 21.4,\n \"partnerNetPrice\": 20.52\n }\n }\n }\n ],\n \"totalPrice\": {\n \"price\": {\n \"recommendedRetailPrice\": 21.4,\n \"partnerNetPrice\": 20.52,\n \"bookingFee\": 1.23,\n \"partnerTotalPrice\": 21.75\n }\n },\n \"cancellationPolicy\": {\n \"type\": \"STANDARD\",\n \"description\": \"For a full refund, cancel at least 24 hours before the scheduled departure time.\",\n \"cancelIfBadWeather\": false,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 2,\n \"percentageRefundable\": 100,\n \"startTimestamp\": \"2020-11-10T02:04:15Z\",\n \"endTimestamp\": \"2021-03-30T23:00:00Z\"\n },\n {\n \"dayRangeMin\": 0,\n \"dayRangeMax\": 1,\n \"percentageRefundable\": 0,\n \"startTimestamp\": \"2021-03-31T23:00:00Z\",\n \"endTimestamp\": \"2021-04-01T23:00:00Z\"\n }\n ]\n },\n \"voucherInfo\": {\n \"url\": \"https://www.viator.com/ticket?code=1187186744:8ac3e6308555ab632fe89e8a6b83c41620e840a3bc485f6e0d836192eae1ffc4\",\n \"format\": \"HTML\",\n \"type\": \"STANDARD\"\n }\n}\n```\n\n\n### Canceled booking\n\n**Example request**: Get the status of the booking with the partner booking reference `\"test-partner-ref-aejsmont-num-1604985575\"`\n\n```json\n{\n \"partnerBookingRef\": \"test-partner-ref-aejsmont-num-1604985575\"\n}\n```\n\n**Example response**: The status of this booking is `\"CANCELED\"`\n\n```json\n{\n \"bookingRef\": \"BR-582323272\",\n \"status\": \"CANCELED\",\n \"partnerBookingRef\": \"test-partner-ref-aejsmont-num-1604985575\"\n}\n```\n\n# Testing\n\n## Postman collections for testing\n\nPlease use one of the following [Postman](https://www.getpostman.com/) collections, depending on which type of partner you are. The collections are configured for the **sandbox** base URL (`api.sandbox.viator.com`).\n\n - [Viator Basic-access Affiliate API Postman collection](Viator-Basic-Access-Affiliate-API-v2.postman_collection.json)\n - [Viator Full-access Affiliate API Postman collection](Viator-Affiliate-API-v2.postman_collection.json)\n - [Viator Full-access + Booking Affiliate API Postman collection](Viator-Affiliate-Booking-API-v2.postman_collection.json)\n - [Viator Merchant API Postman collection](Viator-Merchant-API-v2.postman_collection.json)\n\nTo access the **production** environment, replace `api.sandbox.viator.com` with `api.viator.com` in the endpoint URLs provided in the Postman collections for testing.\n\n**All testing must be done in Sandbox.** Production endpoints are for live bookings only and must not be used for testing under any circumstances. Sandbox provides access to the same products and functionality as Production unless stated otherwise.\n\n### Set up the `your-api-key` environment variable\n\nAs all services in this API require that your API-key be passed as a header parameter in every request made to this API, this value has been set to reference a Postman environment variable called `your-api-key`.\n\nOnce you import the collection into Postman, [set this variable](https://learning.getpostman.com/docs/postman/environments_and_globals/variables#defining-collection-variables) to your organization's API-key and save the collection.\n\n# Workflows\n\n## Ingesting and updating the product catalogue\n\nThe recommended way to initialize and keep your local copy of our products database up-to-date is by using the [/products/modified-since](#operation/productsModifiedSince) endpoint in the following way:\n\n### Initialize your local copy of our products database by ingesting all product records\n\nMake a request to [/products/modified-since](#operation/productsModifiedSince), but only include the `count` parameter. Do not supply values for `modified-since` or `cursor`. This instructs the system to return any products modified since the beginning of time; i.e., all of them.\n\n**Note**: This is the only occasion on which you will need to call [/products/modified-since](#operation/productsModifiedSince) without the `modified-since` or `cursor` parameter.\n\n`count` specifies how many product records will be returned per page. For practical purposes, setting `count` to its maximum value (500) is advised. However, for the purposes of brevity, I am using a `count` of `5` in this example; i.e.:\n\n```\nGET https://api.sandbox.viator.com/partner/products/modified-since?count=5\n```\n\nYou will receive a response similar to the following:\n\n```json\n{\n \"products\": [\n {\n \"status\": \"ACTIVE\",\n \"productCode\": \"92457P4\",\n \"language\": \"en-US\",\n \"createdAt\": \"2020-06-16T12:49:29.519174Z\",\n \"lastUpdatedAt\": \"2020-11-08T16:26:16Z\",\n \"title\": \"Ecuador Parapente Quito\",\n \"ticketInfo\": {\n \"ticketTypes\": [\n \"MOBILE_ONLY\"\n ],\n \"ticketTypeDescription\": \"Mobile or paper ticket accepted\",\n \"ticketsPerBooking\": \"ONE_PER_BOOKING\",\n \"ticketsPerBookingDescription\": \"One per booking\"\n },\n \"pricingInfo\": {\n \"type\": \"PER_PERSON\",\n \"ageBands\": [\n {\n \"ageBand\": \"INFANT\",\n \"startAge\": 6,\n \"endAge\": 17,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 4\n },\n {\n \"ageBand\": \"ADULT\",\n \"startAge\": 18,\n \"endAge\": 60,\n \"minTravelersPerBooking\": 0,\n \"maxTravelersPerBooking\": 4\n }\n ]\n },\n \"images\": [\n {\n \"imageSource\": \"SUPPLIER_PROVIDED\",\n \"caption\": \"\",\n \"isCover\": true,\n \"variants\": [...\n ],\n \"logistics\": {\n \"start\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\"\n },\n \"description\": \"The meeting point is on the way to Lumbisí km 1 at the entrance to La Primavera at 8:30 am.\"\n }\n ],\n \"end\": [\n {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\"\n },\n \"description\": \"The meeting point is on the way to Lumbisí km 1 at the entrance to La Primavera at 8:30 am.\"\n }\n ],\n \"redemption\": {\n \"redemptionType\": \"NONE\",\n \"specialInstructions\": \"\"\n },\n \"travelerPickup\": {\n \"pickupOptionType\": \"MEET_EVERYONE_AT_START_POINT\",\n \"\ allowCustomTravelerPickup\": true\n }\n },\n \"timeZone\": \"America/Guayaquil\",\n \"description\": \"the only legal paragliding operator in ecuador. See an amazing view of Quito and its surroundings from above.\",\n \"inclusions\": [\n {\n \"category\": \"OTHER\",\n \"categoryDescription\": \"Other\",\n \"type\": \"OTHER\",\n \"typeDescription\": \"Other\",\n \"otherDescription\": \"Paragliding Kit\"\n },\n {\n \"category\": \"OTHER\",\n \"categoryDescription\": \"Other\",\n \"type\": \"OTHER\",\n \"typeDescription\": \"Other\",\n \"otherDescription\": \"Air-conditioned vehicle\"\n }\n ],\n \"additionalInfo\": [\n {\n \"type\": \"STROLLER_ACCESSIBLE\",\n \"description\": \"Infants and small children can ride in a pram or stroller\"\n },\n {\n \"type\": \"NO_PREGNANT\",\n \"description\": \"Not recommended for pregnant travelers\"\n },\n {\n \"type\": \"NO_HEART_PROBLEMS\",\n \"description\": \"Not recommended for travelers with poor cardiovascular health\"\n },\n {\n \"type\": \"PHYSICAL_EASY\",\n \"description\": \"Suitable for all physical fitness levels\"\n }\n ],\n \"cancellationPolicy\": {\n \"type\": \"STANDARD\",\n \"description\": \"For a full refund, cancel at least 24 hours before the scheduled departure time.\",\n \"cancelIfBadWeather\": true,\n \"cancelIfInsufficientTravelers\": false,\n \"refundEligibility\": [\n {\n \"dayRangeMin\": 1,\n \"percentageRefundable\": 100\n },\n {\n \"dayRangeMin\": 0,\n \"dayRangeMax\": 1,\n \"percentageRefundable\": 0\n }\n ]\n },\n \"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"FIXED_TIME\",\n \"bookingCutoffInMinutes\": 1440,\n \"confirmationType\": \"INSTANT\",\n \"bookingCutoffFixedTime\": \"16:00:00\"\n },\n \"bookingRequirements\": {\n \"minTravelersPerBooking\": 1,\n \"maxTravelersPerBooking\": 4,\n \"requiresAdultForBooking\": false\n },\n \"bookingQuestions\": [\n \"FULL_NAMES_LAST\",\n \"PASSPORT_EXPIRY\",\n \"PASSPORT_PASSPORT_NO\",\n \"SPECIAL_REQUIREMENTS\",\n \"FULL_NAMES_FIRST\",\n \"WEIGHT\",\n \"AGEBAND\",\n \"HEIGHT\",\n \"PASSPORT_NATIONALITY\"\n ],\n \"tags\": [\n 20234\n ],\n \"destinations\": [\n {\n \"ref\": \"735\",\n \"primary\": true\n }\n ],\n \"itinerary\": {\n \"itineraryType\": \"ACTIVITY\",\n \"skipTheLine\": false,\n \"privateTour\": true,\n \"duration\": {\n \"fixedDurationInMinutes\": 15\n },\n \"activityInfo\": {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\"\n },\n \"description\": \"We take off from the hill of Lumbisi towards the City, we observe the landscape of the city of Quito you can observe the mountains. We landed at the foot of the hill.\\n\\nThe meeting point is on the way to Lumbisí km 1 at the entrance to La Primavera at 8:30 am. From there we got on a vehicle to the mountain. \"\n }\n },\n \"productOptions\": [\n {\n \"productOptionCode\": \"TG1\",\n \"description\": \"\",\n \"title\": \"Ecuador Parapente Quito\"\n }\n ],\n \"translationInfo\": {\n \"containsMachineTranslatedText\": false\n },\n \"supplier\": {\n \"name\": \"Opeturmo - Parapente Montanita\"\n }\n },\n {\n \"status\": \"INACTIVE\",\n \"productCode\": \"141567P21\",\n \"language\": \"en-US\",\n \"createdAt\": \"2019-10-08T13:12:21.535614Z\",\n \"lastUpdatedAt\": \"2020-11-13T13:41:18Z\"\n },\n {\n \"status\": \"INACTIVE\",\n \"productCode\": \"8932P17\",\n \"language\": \"en-US\",\n \"createdAt\": \"2019-06-03T13:29:09.131851Z\",\n \"lastUpdatedAt\": \"2020-11-13T13:42:38Z\"\n },\n {\n \"status\": \"INACTIVE\",\n \"productCode\": \"58593P53\",\n \"language\": \"en-US\",\n \"createdAt\": \"2020-11-13T13:46:39.927509Z\",\n \"lastUpdatedAt\": \"2020-11-13T13:51:43Z\"\n },\n {\n \"status\": \"INACTIVE\",\n \"productCode\": \"164413P1\",\n \"language\": \"en-US\",\n \"createdAt\": \"2019-06-14T00:29:29.039245Z\",\n \"lastUpdatedAt\": \"2020-11-13T14:22:08Z\"\n }\n ],\n \"nextCursor\": \"MTYwNTI3NzMyOHwxNjQ0MTNQMXxJTkFDVElWRQ==\"\n}\n```\n\nThe example above gives the first five product records in the catalogue, with modification dates in chronological order. Note that products with a `\"status\"` of `\"INACTIVE\"` are products that have been temporarily disabled by the supplier and are therefore unavailable – when this is the case, all other requests for this product should be avoided. \n\nIncluded in the response is the `nextCursor` element, which contains an identification code that points to the next page of product records; i.e.:\n\n```json\n\"nextCursor\": \"MTYwNTI3NzMyOHwxNjQ0MTNQMXxJTkFDVElWRQ==\"\n```\n\nIn your next call to [/products/modified-since](#operation/productsModifiedSince), provide the value of `nextCursor` in the `cursor` parameter to get the next page of results:\n\n```\nGET https://api.sandbox.viator.com/partner/products/modified-since?count=500&cursor=MTYwNTI3NzMyOHwxNjQ0MTNQMXxJTkFDVElWRQ==\n```\n\nThe response will be similar to the initial response shown above, except it will contain the **next** 500 product records and a new `nextCursor` that points to the following page, and so on.\n\nContinue calling [/products/modified-since](#operation/productsModifiedSince) using the `nextCursor` value in the `cursor` parameter to retrieve all pages of results. You will eventually receive a response that contains an empty `products` array and does not contain a `nextCursor` element. The absence of the `nextCursor` element indicates that you have, for the time being, reached the end of the list and have received all product records from our catalogue.\n\n**Example final page response**\n\n```json\n{\n \"products\": []\n}\n```\n\n### Periodically update your product records\n\nNow that you have all product records from our catalogue, you can keep it up-to-date by periodically polling the service using the most-recent `nextCursor` code you received. Regardless of how frequently you call [/products/modified-since](#operation/productsModifiedSince), you will always receive all product update information so long as you keep track of the last cursor you received and use that in your subsequent call.\n\nYou should never need to re-ingest the entire product catalogue unless you need to re-initialize your database. This may happen frequently during development, but never (or rarely) in production. Due to the large volume of data, we strongly recommend keeping it to a minimum.\n\nProducts are considered updated when the supplier makes any changes to the product's details, excluding pricing and availability changes, which are retrieved from the [availability schedules](#section/Key-concepts/Product-content-and-availability-endpoints) endpoints. \n\nWhen the supplier publishes their product detail updates, the modified product [/products/modified-since](#operation/productsModifiedSince) service will respond to this same call with newly-modified products in the `products` array and a new `nextCursor` element with which to poll the service for future updates in the same way.\n\nIt would be reasonable to poll this service on an hourly basis, updating those records in your local copy of the product catalogue as they become available.\n\nNote that the `nextCursor` code is valid indefinitely; it will not expire.\n\n### Filtering out products\n\nYou are free to choose which products to store on your system and sell. As the product content endpoints return all available products, you will need to perform the filtering step yourself at the time of ingestion. If a product contains attributes that you do not desire; e.g., the type of product, where it operates, etc., simply discard the update and do not add it to your database.\n\n#### Filtering out manual-confirmation products\n\nUnless you have established the required functionality on your site to sell [manual confirmation products](#section/Booking-concepts/Booking-confirmation-types) you will need to **exclude** all non-instant confirmation products from your catalogue.\n\nInstant confirmation products can be identified by the value of `bookingConfirmationSettings.confirmationType` being `\"INSTANT\"` in the response [product content response](#section/Key-concepts/Product-content-and-availability-endpoints); e.g.:\n\n```json\n\"bookingConfirmationSettings\": {\n \"bookingCutoffType\": \"CLOSING_TIME\",\n \"bookingCutoffInMinutes\": 0,\n \"confirmationType\": \"INSTANT\"\n}\n```\n\nProducts wih a `confirmationType` of `\"MANUAL\"` or `\"INSTANT_THEN_MANUAL\"` should be excluded if you do not wish to sell manual confirmation products.\n\n**Please note**:\n\n- The product catalog must be ingested and updated using the [/products/modified-since](#operation/productsModifiedSince) endpoint, unless you are only selling a relatively small subset of the products available in the Viator catalog. If that is the case, you may prefer to use the [/products/bulk](#operation/productsBulk) endpoint to ingest your selected products. \n\n- **Important**: the [/products/{product-code}](#operation/products) endpoint should not be used for bulk ingestion purposes. Your product ingestion/update strategy is one of our certification requirements and must be verified by us prior to your accessing the production server. To find out what our certification requirements are, see: [Viator Merchant API Certification](https://partnerresources.viator.com/travel-commerce/merchant/certification/?source=specs).\n\n\n## Resolving references\n\nSome information in the product content response is not communicated explicity; but rather, by reference, and therefore requires an extra de-referencing step to acquire the full details of the element.\n\nThese data types comprise:\n\n- locations\n- destinations\n- tags\n\nThe following sections describe how to de-reference these elements using the API.\n\n### Location references\n\nAll locations within the product content response are given as a location reference; e.g.:\n\n```json\n \"activityInfo\": {\n \"location\": {\n \"ref\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\"\n },\n```\n\nThese location references can be resolved using the [/locations/bulk](#operation/locationsBulk) endpoint; for example:\n\n**Request**:\n\n```json\n{\n \"locations\": [\n \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\",\n \"LOC-6eKJ+or5y8o99Qw0C8xWyK8Z2imHSU8Ozi+NYupJVyI=\"\n ]\n}\n```\n\n**Response**:\n\n```json\n{\n \"locations\": [\n {\n \"provider\": \"GOOGLE\",\n \"reference\": \"LOC-o0AXGEKPN4wJ9sIG0RAn5Cdd0Y9TkTxkcosDq0rJgjR12IzpogNi5POX+yGLXEoq\",\n \"providerReference\": \"ChIJS1UFbTyX1ZER0vTgCLKWCEQ\"\n },\n {\n \"provider\": \"TRIPADVISOR\",\n \"reference\": \"LOC-6eKJ+or5y8o99Qw0C8xWyK8Z2imHSU8Ozi+NYupJVyI=\",\n \"name\": \"Valley of the Roses\",\n \"address\": {\n \"street\": \"Dades Valley, near Bouteghrar\",\n \"administrativeArea\": \"El Kelaa M'gouna\",\n \"country\": \"Morocco\",\n \"countryCode\": \"MA\",\n \"postcode\": \"43000\"\n },\n \"center\": {\n \"latitude\": 34.00061,\n \"longitude\": -6.84494\n }\n }\n ]\n}\n```\n\nNote that there are two different location information providers, `\"TRIPADVISOR\"` and `\"GOOGLE\"`, referring to locations in the Tripadvisor location database or locations provided by the [Google Maps platform](https://cloud.google.com/maps-platform/) via the [Google Places API](https://developers.google.com/maps/documentation/places/web-service/overview), respectively. \n\nTripadvisor locations include full details of the location in the response from [/locations/bulk](#operation/locationsBulk), including address and geolocation information. However, you will need to use the [Google Places API](https://developers.google.com/maps/documentation/places/web-service/overview) to retrieve details for Google Maps locations.\n\nThe purpose of referring to locations by reference is to avoid the unnecessary transmission of duplicate data, as multiple products may include the same location reference. Therefore, we recommend caching the data received from this endpoint, checking this first to see if a particular location's details have been retrieved by your system in the past before making a request to [/locations/bulk](#operation/locationsBulk).\n\nRequests can be made to [/locations/bulk](#operation/locationsBulk) asynchronously; e.g., during the content ingestion process.\n\n\n### Destination references\n\nEvery product in the Viator catalogue is categorized according to the destination/locale in which it operates. \n\nThere are multiple kinds of destination, which includes cities, regions, countries and others\n\n**Example destinations***:\n\n| type | destinationId | destinationName |\n|-----------------|---------------|----------------------------|\n| AREA | 51912 | Machame |\n| CITY | 343 | Bangkok |\n| COUNTRY | 749 | Panama |\n| COUNTY | 51632 | Xiahe County |\n| DISTRICT | 51921 | Hunza |\n| HAMLET | | |\n| ISLAND | 51220 | Syros |\n| NATIONAL PARK | 51196 | Death Valley National Park |\n| NEIGHBORHOOD | 60465 | Kensington |\n| PENINSULA | 51769 | Michamwi |\n| PROVINCE | 51255 | Mendoza Province |\n| REGION | 4431 | Northern China |\n| STATE | | |\n| TOWN | 50971 | Swansea |\n| UNION TERRITORY | 51542 | Daman and Diu |\n| VILLAGE | 51011 | Pyrgos |\n| WARD | 52140 | Shibuya |\n\n* Notes:\n The examples above are subject to change.\n These are all currently supported destination types, though for some there are no live examples at the moment\n\n\nEvery product has one or more destinations associated with it by way of its destination reference. This is given in the `destinations` object in the response from any of the product content endpoints; e.g.:\n\n```json\n\"destinations\": [\n {\n \"ref\": \"34198\",\n \"primary\": true\n }\n],\n```\n\nTo de-reference destination identifiers, you must use our destination taxonomy, which can be retrieved from the [/destinations](#operation/destinations) endpoint.\n\nYou may wish to filter products according to destination.\n\nA call to [/destinations](#operation/destinations) will return data for **all** available destinations. \nYou must store a local copy of this mapping information, as destination data does not change frequently – i.e., new destinations are rarely added. \nOn-demand updates can be done in the event you encounter a product associated to a destination reference for which you do not have the details.\n\n\n**Example snippet of destination taxonomy**:\n\n```json\n{\n \"destinationId\": 34198,\n \"name\": \"Seminyak\",\n \"type\": \"CITY\",\n \"parentDestinationId\": 98,\n \"lookupId\": \"2.15.98.34198\",\n \"defaultCurrencyCode\": \"IDR\",\n \"timeZone\": \"Asia/Makassar\",\n \"center\": {\n \"latitude\": -8.68877,\n \"longitude\": 115.161267\n }\n},\n{\n \"destinationId\": 901,\n \"name\": \"Buenos Aires\",\n \"type\": \"CITY\",\n \"parentDestinationId\": 22280,\n \"lookupId\": \"9.78.22280.901\",\n \"destinationUrl\": \"https://shop.live.rc.viator.com/x/d901-ttd?mcid=42383&pid=P00108950&medium=api&api_version=2.0\",\n \"defaultCurrencyCode\": \"ARS\",\n \"timeZone\": \"America/Argentina/Buenos_Aires\",\n \"iataCode\": \"BUE\",\n \"center\": {\n \"latitude\": -34.6084175,\n \"longitude\": -58.3731613\n }\n},\n...\n```\n\nNote that destinations are organized into a hierarchy. The destination's position in the hierarchy can be determined according to the `parentDestinationId` and `lookupId` fields.\n\nIn the second example above, Buenos-Aires is a `\"CITY\"`, and it has a `parentDestinationId` of `22280`, which is the `destinationId` of \"The Pampas\" – the `\"REGION\"` in South America where Buenos-Aires is located.\n\nThe destination's full lineage with respect to the hierarchy is given in `lookupId`, which is a series of destination ids separated by periods - in this case:\n\n```json\n \"lookupId\": \"9.78.22280.901\"\n```\n\n| Component | Destination name | Destination type |\n|-----------|------------------|------------------|\n| 9 | (unnamed) | (broad continental designation) | \n| 78 | Argentina | \"COUNTRY\" |\n| 22280 | The Pampas | \"REGION\" |\n| 901 | Buenos-Aires | \"CITY\" |\n\nUsing this information, you are able to categorize each product into its geographical location for display and search purposes.\n\n### Tag references\n\nEach product is also categorized according to its content, features or theme. Each attribute has a corresponding identifier called a 'tag'. The tag references for each product are contained in the `tags` array, in the response from any of the product content endpoints.\n\n**Example tags array** (product [250380P1 – Surf lessons Bali, Canggu](https://www.viator.com/tours/Seminyak/Surf-lessons-Bali-Canggu/d34198-250380P1)): \n\n```json\n\n\"tags\": [\n 20246,\n 21946,\n 20244\n],\n```\n\nThese numeric tag identifiers can be de-referenced using information available from the [/products/tags](#operation/productsTags) endpoint. This service takes no parameters and retrieves information for **all** available tags.\n\nTo learn more about tags, see this article: [Viator tags, explained](https://partnerresources.viator.com/travel-commerce/tags?source=specs)\n\nWe recommend you store a local copy of this information, as tags do not change frequently. It is only necessary to re-ingest from this endpoint in the event you encounter a product that references a tag for which you do not have the details.\n\nAs with destinations, tags are organized into a hierarchy. A tag's relative position within that hierarchy can be determined by tracing back through its parent tag ids, which (if the tag has any) are listed in its `parentTagIds` element. Each tag can have multiple parent tags, and each tag can eventually be traced back to its parent. Parent tags are tags that have no parents; i.e., they are at the top of the hierachy.\n\nFor example, tag: **20244 (Sports Lessons)** in [/products/tags](#operation/productsTags) response:\n\n```json\n{\n \"tagId\": 20244,\n \"parentTagIds\": [\n 21478,\n 21909,\n 21915\n ],\n \"allNamesByLocale\": {\n \"de\": \"Sportkurse\",\n \"no\": \"Treningskurs\",\n \"sv\": \"Idrottslektioner\",\n \"pt\": \"Aulas de esportes\",\n \"en_AU\": \"Sports Lessons\",\n \"en\": \"Sports Lessons\",\n \"it\": \"Lezioni di sport\",\n \"fr\": \"Cours de sport\",\n \"en_UK\": \"Sports Lessons\",\n \"es\": \"Sesiones deportivas\",\n \"zh\": \"运动课\",\n \"zh_HK\": \"體育課程\",\n \"zh_TW\": \"運動課程\",\n \"ja\": \"スポーツ教室\",\n \"zh_CN\": \"运动课\",\n \"da\": \"Sportsundervisning\",\n \"nl\": \"Sportlessen\"\n }\n},\n\n```\n\nThe `parentTagIds` for 20244 - Sports lessons are:\n\n- **21478** – \"Active & Outdoor Classes\"\n- **21909** – \"Outdoor Activities\"\n- **21915** – \"Classes & Workshops\"\n\nThese three tags have no parent tags, and are therefore at the top of the hierarchy. Applying this same process to the other tags in the `tags` array, we can determine the full set of tags for this product, in this case:\n\n- **21909** – \"Outdoor Activities\"\n - **21478** – \"Active & Outdoor Classes\"\n - **20244** - \"Sports lessons\"\n- **21915** – \"Classes & Workshops\" \n- **21946** – \"Good for avoiding crowds\"\n- **21442** – \"On the water\"\n - **20246** – \"Surfing lessons\"\n\nBy traversing the hierarchy in this way, we have surfaced seven tags that pertain to this product with different levels of generality; i.e. it is an 'active and outdoor class', and it is a 'sports lesson'. More generally, it is an 'outdoor activity', a class or workshop, and is 'good for avoiding crowds':\n\nIn this way, you can categorize products for search and recommendation purposes, or to create category display and search buttons as seen on [viator.com 'things to do' pages](https://www.viator.com/Adelaide/d363-ttd); e.g.:\n\n![tag categories on viator.com](img/ttd-tags.png)\n\n\n## Ingesting and updating availability schedules\n\nAvailability schedule information for all products is available to be ingested and updated via the [/availablity/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) endpoint. This endpoint functions in a similar manner to the [/products/modified-since](#operation/productsModifiedSince) endpoint; i.e., an initial call is made that returns all availability data in bulk, and then calls are made periodically to that same endpoint, which will return a delta update.\n\nTherefore, to initialize your local copy of our availability schedule information, make a call to [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince), including only the `count` query parameter, which we recommend setting to `500`. \n\nFor the sake of brevity, in the following example, `count` is set to `5`\n\n**Example request**\n\n```\nGET https://api.viator.com/partner/availability/schedules/modified-since?count=5\n```\n\nYou will receive a response similar to the following:\n\n```json\n{\n \"availabilitySchedules\": [\n {\n \"productCode\": \"3320STOLZadvaft\",\n \"bookableItems\": [\n {\n \"seasons\": [\n {\n \"startDate\": \"2020-11-23\",\n \"endDate\": \"2020-12-22\",\n \"pricingRecords\": [\n {\n \"daysOfWeek\": [\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\",\n \"SATURDAY\",\n \"SUNDAY\"\n ],\n \"timedEntries\": [\n {\n \"startTime\": \"15:30\"\n }\n ],\n \"pricingDetails\": [\n {\n \"pricingPackageType\": \"PER_PERSON\",\n \"minTravelers\": 1,\n \"ageBand\": \"INFANT\",\n \"price\": {\n \"original\": {\n \"recommendedRetailPrice\": 0.00,\n \"partnerNetPrice\": 0.00,\n \"bookingFee\": 0.00,\n \"partnerTotalPrice\": 0.00\n }\n }\n },\n {\n \"pricingPackageType\": \"PER_PERSON\",\n \"minTravelers\": 1,\n \"ageBand\": \"ADULT\",\n \"price\": {\n \"original\": {\n \"recommendedRetailPrice\": 17.20,\n \"partnerNetPrice\": 11.50,\n \"bookingFee\": 0.69,\n \"partnerTotalPrice\": 12.19\n }\n }\n }\n ]\n }\n ]\n }\n ]\n }\n ],\n \"currency\": \"EUR\"\n },\n {\n \"productCode\": \"14093P1\",\n \"bookableItems\": [],\n \"currency\": \"EUR\"\n },\n {\n \"productCode\": \"3567AKL_SAF\",\n \"bookableItems\": [],\n \"currency\": \"NZD\"\n },\n {\n \"productCode\": \"5855RIPLEYS\",\n \"bookableItems\": [],\n \"currency\": \"USD\"\n },\n {\n \"productCode\": \"3033ENTRY_TR\",\n \"bookableItems\": [],\n \"currency\": \"USD\"\n }\n ],\n \"nextCursor\": \"MTU3ODA2Njc4NnwzMDMzRU5UUllfVFI=\"\n}\n```\n\nThe endpoint returns an array (`availabilitySchedules`) where each item contains all availabilty schedule information for a single product, and a cursor (`nextCursor`) that is to be used in subsequent calls to this endpoint to retrieve the next page of results.\n\nFor details on how to interpret the availability schedule object, see [Availability schedules](#section/Key-concepts/Availability-schedules).\n\n**Note**: An empty `bookableItems` array means that the product indicated by `productCode` is not active, has no availability, and therefore cannot be booked. This fact will be reflected if the product details are requested from the [/products/{product-code}](#operation/products) endpoint; e.g., for product `3033ENTRY_TR`:\n\n```json\n{\n \"status\": \"INACTIVE\",\n \"productCode\": \"3033ENTRY_TR\",\n \"language\": \"en\",\n \"createdAt\": \"2006-05-01T07:00:00Z\"\n}\n```\n\n### Pagination\n\nAs with the [/products/modified-since](#operation/productsModifiedSince) endpoint, you will receive as many records as requested via the `count` request parameter. Included in the response is the `nextCursor` element, which contains a code that points to the next page of availability records.\n\nAfter receiving this first response, your next request to the [/availablity/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) service should include the value of `nextCursor` in the `cursor` request parameter; i.e.:\n\n```\nGET https://api.sandbox.viator.com/partner/availability/schedules/modified-since?count=5&cursor=MTU3ODA2Njc4NnwzMDMzRU5UUllfVFI=\n```\n\nThe response will be similar to the initial response shown above, except it will contain the next `count` number of availability schedule records and a new `nextCursor` that points to the following page.\n\nLoop through this process until you receive a response that contains an empty `availabilitySchedules` array and does not contain a `nextCursor` element. The absence of the `nextCursor` element indicates that you have, for the time being, reached the end of the list and your availability information is fully up-to-date.\n\n**Example final page response**\n\n```json\n{\n \"availabilitySchedules\": []\n}\n```\n\n### Periodically update your availability information\n\nOnce your availability schedule information ingestion is complete, you can keep it up-to-date by periodically polling the service using the latest `nextCursor` code you received; i.e., from the page prior to the final, empty page. \n\nIf new availability schedule information is available, the service will respond with new availability information in the `availabilitySchedules` array and a new `nextCursor` element with which to poll the service for future updates in the same way. Note that the `nextCursor` code is valid indefinitely; it will not expire.\n\nAs with the [/products/modified-since](#operation/productsModifiedSince) endpoint, we recommend polling this service on an hourly basis. The longer the interval between updates, the more likely your availability information will be out of date, raising the likelihood of availability differences when you make a real-time availability check using the [/availability/check](#operation/availabilityCheck) service.\n\nAgain, you should only need to call [/availablity/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) without a `cursor` parameter **once**, for the first call of the initial ingestion. All future calls should include the `cursor` parameter and the results used to update your database.\n\n### Filtering out availability schedules\n\nAs you may not be offering Viator's full product catalogue for sale on your site, you are only required to store availability information for the products you support. Therefore, if you are filtering out products from our catalogue, you should also perform a check with regard to the availability schedule information received from the [/availablity/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) to ensure that it pertains to a product in your catalogue.\n\nThis can be done by checking the `productCode` field in the ProductAvailabilitySchedule object response.\n\n**Please note**:\n\n- The availability and pricing schedules must be ingested and updated using the [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) endpoint, unless you are only selling a relatively small subset of the products available in the Viator catalog. If that is the case, you may prefer to use the [/availability/schedules/bulk](#operation/availabilitySchedulesBulk) endpoint to ingest your selected product availability schedules. \n\n- **Important**: the [/availability/schedules/{product-code}](#operation/availabilitySchedules) endpoint should not be used for bulk ingestion purposes. Your availability schedule ingestion/update strategy is one of our certification requirements and must be verified by us prior to your accessing the production server. To find out what our certification requirements are, see: [Viator Merchant API Certification](https://partnerresources.viator.com/travel-commerce/merchant/certification/?source=specs).\n\n\n## Update frequency\n\nWe expect that your update frequency will not be more frequent than the following guidelines. More frequent updates will place an excessive burden on our systems and may result in your integration being shut off.\n\nSee section on [Rate Limiting](#section/Workflows/Rate-limiting) for more information.\n\n### Fixed-cadence delta updates\n\nIn order to keep your local databases up-to-date without placing an excessive burden on our servers, we expect you use the following fixed cadences at which you should poll the content-ingestion endpoints:\n\n| Endpoint | Update cadence |\n|-----------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [/products/modified-since](#operation/productsModifiedSince) | Every 15-30 minutes following initial ingestion |\n| [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) | Every 15-30 minutes following initial ingestion |\n| [/bookings/modified-since](#operation/bookingsModifiedSince) | Every 5-10 minutes following initial ingestion to stop notification emails sent by Viator for supplier cancellations of bookings made through the API (merchant partners only).

Hourly for all other scenarios |\n| [/bookings/modified-since/acknowledge](#operation/bookingsModifiedSinceAcknowledge) | Right after ingesting the booking modifications |\n\n### Fixed-cadence full updates\n\nTo ensure your systems reflect any removals of or changes to existing destinations, locations or booking questions, we expect that you retrieve full updates from these endpoints as follows:\n\n| Endpoint | Update cadence |\n|---------------------------------------------------------------------------|----------------|\n| [/destinations](#operation/destinations) | Weekly |\n| [/attractions/search](#operation/attractionsSearch) | Weekly |\n| [/products/booking-questions](#operation/productsBookingQuestions) | Monthly |\n| [/products/tags](#operation/productsTags) | Weekly | \n| [/products/recommendations](#operation/productsRecommendations) | Weekly | \n| [/locations/bulk](#operation/locationsBulk) | Monthly |\n| [/reviews/product](#operation/reviewsProduct) | Weekly |\n| [/bookings/cancel-reasons](#operation/bookingsCancelReasons) | Monthly |\n| [/suppliers/search/product-codes](#operation/suppliersSearchProductCodes) | Weekly |\n| [/bookings/status](#operation/bookingsStatus) | Hourly |\n| [/exchange-rates](#operation/exchangeRates) | Daily |\n\n### On-demand updates\n\nWhen ingesting product content, in the event that you encounter an unknown reference – i.e., a new location reference, booking question, tag or destination id – or, if you need to perform a currency conversion for which the last exchange rate you retrieved has expired, we expect you to call the relevant endpoint to resolve the new reference immediately or just after completing the product content update.\n\n| Endpoint | When to update |\n|--------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [/exchange-rates](#operation/exchangeRates) | Whenever you encounter a currency that you need to convert, but the last-retrieved exchange-rate for that currency-pair is no longer valid due to having expired (according to the `expiry` value in the response from this endpoint) |\n| [/locations/bulk](#operation/locationsBulk) | Whenever you encounter a location reference code that you do not yet have the details for (we recommend retrieving location details in batches using this endpoint; therefore, the retrieval of new location data can commence after all new product content is retrieved) |\n| [/products/tags](#operation/productsTags) | Whenever you encounter a tag reference code that you do not yet have the details for |\n| [/destinations](#operation/destinations) | Whenever you encounter a destination id that you do not yet have the details for |\n| [/products/booking-questions](#operation/productsBookingQuestions) | Whenever you encounter a booking question identifier that you do not yet have the details for |\n| [/attractions/{attraction-id}](#operation/attractions) | Whenever you encounter an attraction identifier that you do not yet have the details for |\n| [/reviews/product](#operation/reviewsProduct) | If the number of reviews available for a product, which is reported in the `reviews.totalReviews` element in the [product content response](#section/Key-concepts/Product-content-and-availability-endpoints), has changed compared with its previous value, the reviews for that product should also be refreshed by calling the [/reviews/product](#operation/reviewsProduct) endpoint. We request that you rate-limit your use of this service to 30 requests per minute. |\n| [/bookings/status](#operation/bookingsStatus) | Whenever you encounter a booking waiting for manual confirmation. Must not be called more than once every 3 minutes. |\n\n## Rate limiting\n\nWe impose rate limits on the usage of this API to prevent excessive demands being made of our system that might otherwise affect its availability for all users.\n\nOur methodology involves applying a rate-limit on a per-endpoint / per-PUID (Partner Unique ID) basis; therefore, reaching the rate-limit with respect to your usage of one endpoint will only affect the availability of that endpoint, not the others.\n\nIn addition, we apply an additional security layer of rate limiting based on client IP address. This limits bursts of consecutive requests from the same IP over a short period of time and may trigger temporary request rejection even when per-endpoint / per-PUID limits have not been reached.\n\nWe do not have a universal rate limit that applies to all users. The rate limit you are required to operate within is based on a standard commensurate with the scale of your operation.\n\nThis is to say that if the volume of traffic to your site is such that under normal conditions your operations are causing you to frequently receive HTTP 429 (Too Many Requests) responses, you can ask for your rate-limit to be increased. If that is the case, please speak to your account manager to discuss whether increasing your rate limit would be the appropriate solution.\n\n### Interpreting the HTTP 429 response\n\nIf a request to an endpoint yields an HTTP 429 (Too Many Requests) response, information regarding your present usage status can be located in the following four header fields:\n\n- `RateLimit-Limit` \n - Total limit of requests for this endpoint per rolling 10s time window\n- `RateLimit-Remaining`:\n - The number of requests that remain available to you in the present 10s period \n- `RateLimit-Reset`:\n - How long (in seconds) from the present moment it would take for the number of available requests to reach its maximum value\n- `Retry-After`:\n - A recommendation regarding how long (in seconds) it would be optimal to wait before making a subsequent call to that endpoint\n\n**Example HTTP 429 response:**\n\n```json\nHTTP/1.1 429\n...\n..\nRateLimit-Limit: 16\nRateLimit-Remaining: 0\nRateLimit-Reset: 10\nRetry-After: 10\n...\n..\n \n{ \n \"code\":\"TOO_MANY_REQUESTS\",\n \"message\":\"Too many requests, please try again\",\n \"timestamp\":\"2022-09-13T13:25:26.179433Z\",\n \"trackingId\":\"4badb933-ad65-4464-ae9c-c20e4a70c0d2\"\n}\n```\n\nThis can interpreted as:\n\n`RateLimit-Limit: 16`\n- You can make 16 requests to this endpoint per 10s rolling time window\n\n`RateLimit-Remaining: 0`\n- You have no remaining requests available in the current 10s epoch (as you would expect, since it is for this reason that you are receiving this response in the first place)\n\n`RateLimit-Reset: 10`\n- If you were to wait 10s, your `RateLimit-Remaining` value would reach its maximum; which, in this case, is 16 requests\n\n`Retry-After: 10`\n- It is recommended you pause for 10s before re-attempting to call this endpoint\n\nNote that these rate-limit-related values will also be returned in the HTTP 200 (success) response. Inspect these values if you wish to estimate whether your method of implementing this API will remain sustainable at scale.\n\n### Concurrency-based rate limiting\n\nWhile rate-limiting is imposed per API key, if our system reaches its capacity on account of high demand overall, you may be rate limited even though you have not personally exceeded your individual rate limit.\n\nIn this case, you will receive a HTTP 503 (Service Unavailable) response. The header of this response will include the `Retry-After` field. In the example below, the recommendation is to pause for 60s before retrying the request:\n e.g.:\n\n```json\nHTTP/1.1 503\n...\n..\nRetry-After: 60\n...\n..\n \n{\"code\":\"SERVICE_UNAVAILABLE\",\"message\":\"Service is currently unavailable, please try again\",\"timestamp\":\"2022-09-13T08:52:48.693734Z\",\"trackingId\":\"fc342644-e48f-4fd9-96e3-a6860607d405\"}\n```\n\n# Appendices\n\n## Inclusions & exclusions\n\nThe `inclusions` and `exclusions` arrays are returned for active products in the response from the [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints). The array items for both `inclusions` and `exclusions` are objects defined by the same schema, `InclusionExclusionItem`.\n\nThe following table describes the mapping of the possible combinations of `category`, `categoryDescription`, `type`, and `typeDescription` elements of the object in the response that you may encounter. \n\nNew Categories and types can be added over time, allowing flexibility for different use cases.\n\nNote: Changes on the table below become effective by the end of April 2025, see Notes column for details.\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n\n\n \n \n \n \n \n\n
categorycategoryDescriptiontypetypeDescriptionnotes
\"FEES_AND_TAXES\"Fees\"AIRPORT_AND_DEPARTURE_TAX\"Airport/Departure Tax
\"ALL_FEES_AND_TAXES\"All Fees and TaxesDeprecated - April 2025
\"FUEL_SURCHARGE\"Fuel surcharge
\"GRATUITIES\"Gratuities
\"GST\"GST (Goods and Services Tax)Deprecated - April 2025
\"LANDING_AND_FACILITY_FEES\"Landing and facility fees
\"PARKING_FEES\"Parking Fees
\"ADMISSION_FEES\"Admission FeesNew - start April 2025
\"ENTRANCE_FEES\"Entrance FeesNew - start April 2025
\"GOVERNMENT_FEES\"Government FeesNew - start April 2025
\"FOOD_AND_DRINK\"Food and drink\"ALCOHOLIC_BEVRAGES\"
\"ALCOHOLIC_BEVERAGES\"
Alcoholic Beverages
\"BOTTLED_WATER\"Bottled water
\"BREAKFAST\"Breakfast
\"BRUNCH\"Brunch
\"COFFEE_AND_TEA\"Coffee and/or Tea
\"DINNER\"Dinner
\"LUNCH\"Lunch
\"REFRESHMENTS\"RefreshmentsDeprecated - April 2025
\"SNACKS\"Snacks
\"SODA_POP\"Soda/Pop
\"MEALS\"MealsNew - start April 2025
\"SOUVENIRS\"Souvenirs\"CERTIFICATE\"CertificateDeprecated - April 2025
\"RECIPE_BOOKLET\"Recipe bookletDeprecated - April 2025
\"TRANSPORT_AMENITIES\"Transportation amenities\"AIR_CONDITIONED_VEHICLE\"Air-conditioned vehicle
\"PRIVATE_TRANSPORTATION\"Private transportation
\"RESTROOM_ON_BOARD\"Restroom on board
\"WIFI_ONBOARD\"WiFi on board
\"PUBLIC_TRANSPORTATION\"Public transportation (bus, subway, cable car, etc.)New - start April 2025
\"EQUIPMENT\"Use of Equipment\"ALL_INGREDIENTS\"All ingredientsDeprecated - April 2025
\"USE_OF_OTHER_EQUIPMENT\"OtherDeprecated - April 2025
\"USE_OF_BICYCLE\"Use of bicycle
\"USE_OF_COOKING_UTENSILS\"Use of cooking utensilsDeprecated - April 2025
\"USE_OF_SCUBA_EQUIPMENT\"Use of SCUBA equipment
\"USE_OF_SEGWAY\"Use of Segway
\"USE_OF_SNORKELING_EQUIPMENT\"Use of snorkelling equipment
\"USE_OF_TRIKKE\"Trikke
\"BOOSTER_SEAT\"Booster seatNew - start April 2025
\"LOCKER\"LockerNew - start April 2025
\"EXCESS_CHARGES\"Excess charges\"EXCESS_BAGGAGE\"Excess baggageNew - start April 2025
\"OVER_WEIGHT_LIMIT\"Over weight limitNew - start April 2025
\"OTHER\"Other\"OTHER\"Other
\n\n## Update history\n\n| Date | Description |\n|------|-------------|\n| 31 Oct 2022 | Removed v1-v2 migration reference section |\n| 14 Sep 2022 | Revised [Workflows – Rate limiting](#section/Workflows/Rate-limiting) and HTTP 429 response description with respect to new rate-limiting policy |\n| 23 Aug 2022 | Clarified new standard rate-limiting policy that applies to all endpoints in new section: [Workflows – Rate limiting](#section/Workflows/Rate-limiting) |\n| 15 Aug 2022 | Altered advice regarding the recommended frequency for fixed cadence full updates for various endpoints in [Workflows – Update frequency](#section/Workflows/Update-frequency) section | \n| 3 Aug 2022 | Updated descriptions of [/products/modified-since](#operation/productsModifiedSince), [/products/bulk](#operation/productsBulk) and [/products/{product-code}](#operation/products) to highlight the polymorphism in the response / discriminator drop-down on `status` element |\n| 1 Aug 2022 | Renamed **Key Concepts – Content ingestion endpoints** to [Key Concepts – Product Content and availability endpoints](#section/Key-concepts/Product-content-and-availability-endpoints) and updated this section with usage recommendations |\n| 27 July 2022 | Updated [conditonal booking questions logic table](#section/Booking-concepts/Booking-questions) to include advice about `TRANSFER_DEPARTURE_MODE` booking question |\n| 18 July 2022 | Modifed [/bookings/cancel-reasons](#operation/bookingsCancelReasons) endpoint to accept a query parameter to specify customer or supplier-initiated cancellation reasons |\n| 18 July 2022 | Added two new endpoints to allow merchant partners to manage supplier-initiated booking cancellations: [/bookings/modified-since](#operation/bookingsModifiedSince) and [/bookings/modified-since/acknowledge](#operation/bookingsModifiedSinceAcknowledge) |\n| 6 July 2022 | Improved descriptions of `lineItems` and `totalPrice` elements of `bookableItems[]` object array in [/availability/check](#operation/availabilityCheck) endpoint response |\n| 30 June 2022 | Clarified conditions in conditional booking questions section of [Booking concepts - Booking questions](#section/Booking-concepts/Booking-questions) section |\n| 29 June 2022 | Added `target-lander` query parameter to [/products/{product-code}](#operation/products), [/products/modified-since](#operation/productsModifiedSince), [/products/bulk](#operation/productsBulk) and [/products/search](#operation/productsSearch) endpoints |\n| 23 June 2022 | Added `attractionId` to filtering options in [/products/search](#operation/productsSearch) endpoint |\n| 22 June 2022 | Updated string length specifications in VoucherInfo schema and `partnerBookingRef` in [/bookings/book](#operation/bookingsBook) request object |\n| 20 June 2022 | Updated maximum string length specifications for [/bookings/book](#operation/bookingsBook) request object (BookerInfo and CommunicationInfo schemata) |\n| 3 June 2022 | Added new supplier search endpoint: [/suppliers/search/product-codes](#operation/suppliersSearchProductCodes) |\n| 1 June 2022 | Added links to various articles on the [Viator Partner Resource Center](https://partnerresources.viator.com/) throughout document |\n| 26 May 2022 | Added advice about review authenticity: [Key concepts - Review authenticity](#section/Key-concepts/Review-authenticity) |\n| 23 May 2022 | Added `partnerNetFromPrice` property to `ProductSearchPricing` schema spec in response from [/products/search](#operation/productsSearch) endpoint |\n| 20 May 2022 | Added advice regarding whether or not an endpoint should be used to ingest details about the entire product catalog to [/products/{product-code}](#operation/products), [/products/bulk](#operation/productsBulk), [/availability/schedules/{product-code}](#operation/availabilitySchedules) and [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince) endpoint descriptions. |\n| 17 May 2022 | Added note about extra validation requirements for `communication.phone` field in request to [/bookings/book](#operation/bookingsBook) endpoint |\n| 11 May 2022 | Modified [update frequency recommendation](#section/Workflows/Update-frequency) for [/locations/bulk](#operation/locationsBulk) endpoint from 'weekly' to 'monthly' due to the relatively changeless nature of locations data. |\n| 10 May 2022 | Modified description of [/exchange-rates](#operation/exchangeRates) endpoint to include additional currencies (ARS, CLP, COP, ILS, PEN, PHP) available for conversion |\n| 1 Apr 2022 | Modified note to [Booking questions – Conditional booking questions](#section/Booking-concepts/Booking-questions) (third bullet in 'Extra notes') |\n| 22 Mar 2022 | Added note to [Booking questions – Conditional booking questions](#section/Booking-concepts/Booking-questions) (third bullet in 'Extra notes') |\n| 8 Mar 2022 | Corrected `\"OTHER_HEALTH\"` to `\"HEALTH_OTHER\"` in `AdditionalInfo` schema used in the product response |\n| 11 Feb 2022 | Removed note about no-index policy from [/v1/attraction/products](#operation/v1AttractionProducts) endpoint |\n| 9 Feb 2022 | Added [Booking concepts – Low-margin products](/#section/Booking-concepts/Low-margin-products) section | \n| 1 Feb 2022 | Added [Conventions - Endpoint timeout settings](#section/Conventions/Endpoint-timeout-settings) section |\n| 5 Jan 2022 | Corrected response schema details in [/bookings/{booking-reference}/cancel](#operation/bookingsCancel) and [/bookings/{booking-reference}/cancel-quote](#operation/bookingsCancelQuote) to indicate that `status` and `bookingId` are required properties |\n| 15 Nov 2021 | Added Basic-access Affiliate postman collection to [Testing section](#section/Testing) |\n| 5 Nov 2021 | Clarified description of exp-demo header parameter |\n| 2 Nov 2021 | Added `\"LOCATION\"` as option for `logistics.travelerPickup.locations[].pickupType` in product content response |\n| 5 Jan 2022 | Corrected response schema details in [/bookings/{booking-reference}/cancel](#operation/bookingsCancel) and [/bookings/{booking-reference}/cancel-quote](#operation/bookingsCancelQuote) to indicate that `status` and `bookingId` are required properties |\n| 15 Nov 2021 | Added Basic-access Affiliate postman collection to [Testing section](#section/Testing) |\n| 5 Nov 2021 | Clarified description of exp-demo header parameter |\n| 2 Nov 2021 | Added `\"LOCATION\"` as option for `logistics.travelerPickup.locations[].pickupType` in product content response |\n| 28 Oct 2021 | Updated [Booking Concepts – Booking questions – Conditional booking questions](#conditional-booking-questions) table |\n| 15 Oct 2021 | Modified PriceObject schema in response from /availabililty/* endpoints to include provision for commission-payment-model merchants. See [/availability/check](#operation/availabilityCheck) for example |\n| 13 Oct 2021 | Added section: [How to determine if a product option supports pickup](#product-option-pickup) |\n| 7 Oct 2021 | Added `\"TRANSFER_ARRIVAL_DROP_OFF\"` booking question details in [Booking details – conditional booking concepts](#section/Booking-concepts/Booking-questions) section |\n| 1 Oct 2021 | Changed 'standard access' to 'full access' in [Access to endpoints](#section/Access-to-endpoints) section |\n| 1 Oct 2021 | Added note about `\"TRANSFER_PORT_CRUISE_SHIP\"` booking question to [Booking concepts – Booking questions section](#section/Booking-concepts/Booking-questions) |\n| 27 Sep 2021 | Added note about time-out recommendation to [/bookings/book](#operation/bookingsBook) |\n| 16 Sep 2021 | Removed `topX` and modified options for `sortOrder` request parameters in [/attraction/reviews/](#operation/v1AttractionReviews) endpoint |\n| 13 Sep 2021 | Added `reference` element to `Supplier` schema of `ActiveProduct` | \n| 6 Sep 2021 | Modified available options for `sortOrder` request parameter in [/v1/taxonomy/attractions](#operation/v1TaxonomyAttractions) and [/v1/search/attractions](#operation/v1SearchAttractions) endpoints |\n| 27 Aug 2021 | Added basic and full-access affiliate types to [Access to endpoints](#section/Access-to-endpoints) section |\n| 26 Aug 2021 | Added [Key concepts – Protecting unique content](#section/Key-concepts/Protecting-unique-content) section |\n| 23 Aug 2021 | Added [Key concepts – v1 to v2 migration reference – Mapping categories to tags](#section/Key-concepts/V1-to-V2-migration-reference) section |\n| 19 Aug 2021 | Added Tripadvisor as an additional reviews provider in [/reviews/product](#operation/reviewsProduct) endpoint | \n| 12 Aug 2021 | Updated [Access to endpoints](#section/Access-to-endpoints) section to include [/products/booking-questions](#operation/productsBookingQuestions) and [/bookings/status](#operation/bookingsStatus) |\n| 10 Aug 2021 | Bugfix – `provider` element in request to [/reviews/product](#operation/reviewsProduct) now listed as 'required' |\n| 5 Aug 2021 | Added new sorting options to [/reviews/product](#operation/reviewsProduct) endpoint |\n| 1 Jul 2021 | Added [Workflows - Update frequency](#section/Workflows/Update-frequency) section |\n| 22 Jun 2021 | Deprecated [/v1/product/reviews](#operation/v1ProductReviews) endpoint |\n| 21 Jun 2021 | Added [/reviews/product](#operation/reviewsProduct) endpoint |\n| 18 Jun 2021 | Added [/products/search](#operation/productsSearch) endpoint |\n| 9 Jun 2021 | Added [Booking concepts – supplier communications](#section/Booking-concepts/Supplier-communications)\n| 9 Jun 2021 | Added [Booking concepts – working with age bands](#section/Booking-concepts/Working-with-age-bands) section |\n| 4 Jun 2021 | Added premium `viatorUniqueContent` element to ActiveProduct |\n| 27 May 2021 | Added [Booking-concepts – Per-person and unit pricing](#section/Booking-concepts/Per-person-and-unit-pricing) section | \n| 21 May 2021 | Added `reviews` element to responses of [product content endpoints](#section/Key-concepts/Product-content-and-availability-endpoints) |\n| 14 May 2021 | Added **Age-bands** section to [Booking concepts - Booking questions](#section/Booking-concepts/Booking-questions) section |\n| 5 May 2021 | Updated Conditional booking questions table in [Booking concepts - Booking questions](#section/Booking-concepts/Booking-questions) section |\n| 25 Mar 2021 | Added v1 endpoints for affiliate partners |\n| 23 Mar 2021 | Added [Resolving references](#section/Workflows/Resolving-references) section |\n| 11 Mar 2021 | Added `campaign-value` parameter to [/products/modified-since](#operation/productsModifiedSince), [/products/bulk](#operation/productsBulk) and [/products/{product-code}](#operation/products) endpoints; added AvailabilityScheduleSummary `summary` schema to /availability/schedules/* endpoint responses |\n| 16 Feb 2021 | Added [Determining ratings](#section/Workflows/Determining-ratings) section; added [Conventions - Accept-Encoding](#section/Conventions/Accept-Encoding) section |\n| 21 Jan 2021 | Extended BookingBookRequest schema (used in [/bookings/book](#operation/bookingsBook)) to include new AdditionalBookingDetails schema to allow custom voucher text |\n| 18 Jan 2021 | Modified `rejectionReasonCode` in responses from [/bookings/book](#operation/bookingsBook) and [/bookings/status](#operation/bookingsStatus) endpoints |\n| 12 Jan 2021 | Added [Key concepts – Booking confirmation types](#section/Booking-concepts/Booking-confirmation-types) section as sale of manual confirmation products has now been enabled. |\n| 7 Dec 2020 | Added DayOperatingHours schema array to BookableItemSeason schema in availability-schedules endpoints | \n| 24 Nov 2020 | Added [Key concepts – Booking cutoff times](#section/Booking-concepts/Booking-cutoff-times) section |\n| 12 Nov 2020 | Added [Workflows – Checking booking status](#section/Booking-concepts/Checking-booking-status) section |\n| 6 Nov 2020 | Added [/bookings/status](#operation/bookingsStatus) endpoint specification |\n| 5 Nov 2020 | Added [Workflows – Ingesting and updating availability schedules](#section/Workflows/Ingesting-and-updating-availability-schedules) section |\n| 4 Nov 2020 | Updated `id` values in [/products/booking-questions](#operation/productsBookingQuestions) endpoint |\n| 3 Nov 2020 | Added [Key concepts – V1 to V2 migration reference](#section/Key-concepts/V1-to-V2-migration-reference) section |\n| 28 Oct 2020 | Added sections for [Activity](#activity-itinerary), [Hop-on hop-off](#hop-on--hop-off-itinerary) and [Unstructured](#unstructured-itinerary) itinerary types |\n| 13 Oct 2020 | - Added `maxLength` field to BookingQuestion schema in response from [/products/booking-questions](#operation/productsBookingQuestions)
- Updated AdditionalInfo schema |\n| 6 Oct 2020 | - Added [Appendices - Inclusions and exclusions](#section/Appendices/Inclusions-and-exclusions)
- Modified ActiveProduct schema to include new required `Supplier` element |\n| 1 Oct 2020 | Added [About](#section/About) section |\n| 29 Sep 2020 | Added [Key concepts - Availability Schedules](#section/Key-concepts/Availability-schedules) section
Added legacy helper endpoints [/v1/taxonomy/destinations](#operation/v1TaxonomyDestinations), [/v1/taxonomy/attractions](#operation/v1TaxonomyAttractions), [v1/product/reviews](#operation/v1ProductReviews), [/v1/product/photos](#operation/v1ProductPhotos) |\n| 28 Sep 2020 | Updated response schema for [/products/tags](#operation/productsTags) |\n| 23 Sep 2020 | Added [Key concepts – Booking questions](#section/Booking-concepts/Booking-questions) section |\n| 22 Sep 2020 | Added [Versioning](#section/Versioning) section |\n| 22 Sep 2020 | Fixed typo in StandardItineraryItem schema (`pointsOfInterestLocation` -> `pointOfIterestLocation`); added explanation of policy window time-stamps & updated response samples in [Workflows - Cancellation policy](#section/Booking-concepts/Cancellation-policy) section | \n| 21 Sep 2020 | Added [Making a booking](#section/Booking-concepts/Making-a-booking) section under Workflows |\n| 20 Sep 2020 | Added `currency` element to [/bookings/hold](#operation/bookingsHold) response schema |\n| 17 Sep 2020 | Breaking change: [/exchange-rates](/#operation/exchangeRates) endpoint refactored |\n| 16 Sep 2020 | **Note**: ONLY freesale products (those with a confirmation type of \"INSTANT\") are presently able to be booked. See [Ingesting and updating the product catalogue](#section/Workflows/Ingesting-and-updating-the-product-catalogue) (Filtering-out on-request products) for instructions on how to filter-out on-request products from your catalogue |\n| 16 Sep 2020 | Breaking change: `languageGuideDetails` element in ActiveProduct schema changed to `languageGuides` (array of LanguageGuide schema) |\n| 15 Sep 2020 | Breaking change: removed `travelerPickup` element from [/booking/book](#operation/bookingsBook) request |\n| 10 Sep 2020 | Added [/bookings/book](#operation/bookingsBook) endpoint specification |\n| 1 Sep 2020 | Added `description` element to `MultiDayTourFoodAndDrinks` and `InclusionExclusionItem` schemata; added `version=2.0` to `Accept` request header parameter across all endpoints |\n| 26 Aug 2020 | `CancellationConditionType` schema key strings updated (now \"STANDARD\", \"MODERATE\", \"STRICT\" & \"ALL_SALES_FINAL\"; `PricingLineItem` updated (affects /availability/check and /bookings/hold-confirm responses); /availability/* endpoints moved to separate 'Availability' section |\n| 25 Aug 2020 | **Breaking changes**: see below |\n| 25 Aug 2020 | Regenerated response samples |\n| 11 Aug 2020 | Updated `paxMix` schema in [/availability/check](#operation/checkAvailability) |\n| 6 Aug 2020 | Added COVID-safety-measure keys to `additionalInfo` schema |\n| 4 Aug 2020 | Added [/bookings/hold](#operation/bookingsHold) endpoint |\n| 28 July 2020 | Added [Ingesting and updating the product catalogue](#section/Workflows/Ingesting-and-updating-the-product-catalogue) section |\n| 23 July 2020 | Added [Product options](), [Cancellation policy](#section/Booking-concepts/Cancellation-policy) sections | \n| 16 Jul 2020 | Added [/bookings/hold](#operation/bookingsHold) endpoint |\n| 3 Jul 2020 | Modified availability endpoint schema and regenerated examples |\n| 1 Jul 2020 | Removed internal-only markup for release |\n| 16 Jun 2020 | Added [Workflows->Cancellation API workflow](#section/Booking-concepts/Cancellation-API-workflow) section\n| 15 Jun 2020 | Removed enum data type specification from `UnavailableDate`, `ageBand`, `CancellationQuoteBookingStatus`, `CancellationResultItemReason` and `CancellationBookingStatus` schemata |\n| 18 May 2020 | Refactored LHS nav to use 'summary' name instead of operationId name |\n| 28 April 2020 | Added `legacyGuide` field to `LanguageGuide` object specification |\n\n### 25 August breaking changes\n\nThe following breaking changes have been made. Please update your OpenAPI specification by downloading from the link at the top of the page.\n\n#### Endpoint URL changes\n\n- /availability-schedule/{product-code} -> [/availability/schedules/{product-code}](#operation/availabilitySchedules)\n- /availability-schedule/bulk -> [/availability/schedules/bulk](/#operation/availabilitySchedulesBulk)\n- /availability-schedule/modified-since -> [/availability/schedules/modified-since](#operation/availabilitySchedulesModifiedSince)\n\n#### Element name changes\n\nA number of name changes have been made to the `Product` schema. This affects the following endpoints:\n\n- [/products/modified-since](#operation/productsModifiedSince)\n- [/products/bulk](#operation/productsBulk)\n- [/products/{product-code}](#operation/products)\n\n| Element | Old name | New name |\n|----------|---------|----------|\n| `cancellationPolicy.badWeather` | `badWeather` | `cancelIfBadWeather` | \n| `cancellationPolicy.insufficientTravelers` | `insufficientTravelers` | `cancelIfInsufficientTravelers` |\n| `translationInfo.translationAttributions` | `translationAttributions` | `translationAttribution` | \n| `destinations.isPrimary` | `isPrimary` | `primary` |\n| `inclusions[].otherText` | `otherText` | `otherDescription` | \n| `itinerary.routes[].pois` | `pois` | `pointsOfInterest` |\n| `itinerary.itineraryItems[].poiLocation` | `poiLocation` | `pointsOfInterestLocation` |\n| `itinerary.routes[].duration.fixedValueinMinutes` | `fixedValueInMinutes` | `fixedDurationInMinutes` |\n| `itinerary.routes[].duration.fromMinutes` | `fromMinutes` | `variableDurationFromMinutes` |\n| `itinerary.routes[].duration.toMinutes` | `toMinutes` | `variableDurationToMinutes` |" version: '2.0' license: name: CC BY 4.0 url: https://creativecommons.org/licenses/by/4.0/au/ servers: - url: https://api.viator.com/partner description: Production server (uses live data) - url: https://api.sandbox.viator.com/partner description: Sandbox server (uses test data) security: - API-key: [] tags: - name: Payments paths: /v1/checkoutsessions/{sessionToken}/paymentaccounts: post: tags: - Payments operationId: paymentsCreateToken summary: /v1/checkoutsessions/{sessionToken}/paymentaccounts description: 'Creates a payment token from raw credit card details for use with the [/bookings/cart/book](#operation/bookingsCartBook) endpoint. The URL should not be constructed manually, instead use the `paymentDataSubmissionUrl` value returned from the [/bookings/cart/hold](#operation/bookingsCartHold) endpoint. When using the API payment solution, it is a requirement that you implement our fraud prevention solution. See Implementing the API Solution for more details. **Note**: - This endpoint utilises a different domain to other endpoints referenced in the API. - This endpoint is only available to affiliate partners with API access level "Full Access + Booking". ' servers: - url: https://api.tapayments.com description: Production server (uses live data) - url: https://api.staging.tapayments.com description: Sandbox server (uses test data) security: [] parameters: - name: Content-Type in: header description: Identifies the payload as application/json. required: true schema: type: string example: application/json - name: x-trip-clientid in: header description: 'This is your unique partner identifier, which you can find in the Viator Partner Program: https://partners.viator.com/login' required: true schema: type: string example: P0123456789 - name: x-trip-requestid in: header description: Any client-side generated request identifier, unique per request. required: true schema: type: string example: 9dbb490a-d953-4a9b-875a-728b5f335b29 - name: User-Agent in: header description: value should be appropriate to the client you are using, e.g. "curl/8.8.0" required: true schema: type: string example: curl/8.8.0 - name: sessionToken in: path description: 'The `sessionToken` is obtained from calling the [/bookings/cart/hold](#operation/bookingsCartHold) endpoint and embedded in the `paymentDataSubmissionUrl`. **Note:** The `paymentDataSubmissionUrl` value should be used instead of contructing the URL manually. ' required: true schema: type: string example: CSI-P-kwftrgmrbfbglkaw4espjdr52e requestBody: content: application/json: schema: $ref: '#/components/schemas/VaultCardRequest' example: paymentAccounts: creditCards: - number: '4111111111111111' cvv: '234' expMonth: '03' expYear: '2026' name: Jane Doe address: country: US postalCode: 02494 required: true responses: '200': description: Card successfully stored. content: application/json: schema: $ref: '#/components/schemas/VaultPaymentResponse' example: paymentAccounts: creditCards: - persistAccount: false cardType: Visa name: Jane Doe number: '' accountHead: '411111' accountTail: '1111' expMonth: '03' expYear: '2026' cvv: '' address: street: '' street2: '' city: '' state: '' country: US postalCode: 02494 phoneNumber: '' accountMetaData: sessionAccountToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c accountFingerprint: '' bankAccounts: [] cvvs: [] bankMandates: [] responseHeader: apiVersion: 1 responseId: RES-rciyl2b2q5gidlusbsq3ofht44 responseCode: 2000 responseMessage: ok errors: [] '404': description: Checkout session expired or not found. content: application/json: example: paymentAccounts: creditCards: [] responseHeader: apiVersion: 1 responseId: RES-sa2lfnzy7rdixep2vhte4bjbzq responseCode: 4004 responseMessage: Checkout session has expired. errors: - responseStatus: NOT_FOUND responseCode: 4004 responseMessage: Checkout session has expired. isExpectedError: true requestFieldPath: param.checkoutsessionid responseDetail: '' components: schemas: VaultCardRequest: required: - paymentAccounts type: object properties: paymentAccounts: $ref: '#/components/schemas/PaymentAccountsRequest' description: The card submission payload. CreditCardRequest: required: - cvv - expMonth - expYear - name - number - address type: object properties: number: type: string description: The full card number, without spaces. example: '4111111111111111' cvv: type: string description: The three or four digit CVV. example: '234' expMonth: type: string description: Two digit representation of expiry month. example: '03' expYear: type: string description: Four digit representation of expiry year. example: '2026' name: type: string description: The cardholder's full name. example: Jane Doe address: $ref: '#/components/schemas/Address' description: PCI sensitive details for a debit or credit card and relevant metadata. PaymentAccounts: type: object properties: creditCards: uniqueItems: true type: array items: $ref: '#/components/schemas/CreditCard' AccountMetaData: type: object properties: sessionAccountToken: type: string description: Token for the submitted card, to be supplied when payment is requested. example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c VaultPaymentResponse: required: - paymentAccounts type: object properties: paymentAccounts: $ref: '#/components/schemas/PaymentAccounts' Address: required: - country - postalCode type: object properties: country: type: string description: The country of the registered billing address, in two character ISO_3166-1 alpha-2 format. example: US postalCode: type: string description: The post code of the registered billing address. 4-9 alphanumeric characters, optionally separated space. example: 02494 description: Minimal billing address details for cardholder PaymentAccountsRequest: required: - creditCards type: object properties: creditCards: type: array description: Array of card data, normal use is single item. items: $ref: '#/components/schemas/CreditCardRequest' description: Wrapper element around payment data. CreditCard: required: - accountHead - accountTail - expMonth - expYear - name type: object properties: cardType: type: string description: The name of card network for the card submitted. example: Visa expMonth: type: string description: Two digit representation of expiry month. example: '03' expYear: type: string description: Four digit representation of expiry year. example: '2026' name: type: string description: The cardholder's full name. example: Jane Doe accountHead: type: string description: The first six numbers of the card, the BIN portion. example: '411111' accountTail: type: string description: The last four numbers of the card. example: '1111' address: $ref: '#/components/schemas/Address' accountMetaData: $ref: '#/components/schemas/AccountMetaData' securitySchemes: API-key: type: apiKey in: header name: exp-api-key