diff --git a/.github/workflows/generate-and-publish-sdk-sources.yaml b/.github/workflows/generate-and-publish-sdk-sources.yaml index 745ac51ece..c4fa46afe6 100644 --- a/.github/workflows/generate-and-publish-sdk-sources.yaml +++ b/.github/workflows/generate-and-publish-sdk-sources.yaml @@ -23,6 +23,6 @@ jobs: with: name: rapid version: ${{ inputs.version }} - transformations: "-th -te /v3 --operationIdsToTags" + transformations: "-th --operationIdsToTags" repository: 'ExpediaGroup/rapid-java-sdk' sdk_repo_ref: ${{ inputs.sdk_repo_ref || 'v20250203' }} diff --git a/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkDemoApplication.java b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkDemoApplication.java index 269e5998f8..5108778099 100644 --- a/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkDemoApplication.java +++ b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkDemoApplication.java @@ -1,19 +1,12 @@ package com.expediagroup.sdk.rapid.examples; import com.expediagroup.sdk.rapid.examples.salesprofiles.DefaultRapidPartnerProfile; +import com.expediagroup.sdk.rapid.examples.scenarios.addelivery.GetAdsScenario; import com.expediagroup.sdk.rapid.examples.scenarios.booking.AsyncSingleRoomBookScenario; import com.expediagroup.sdk.rapid.examples.scenarios.booking.MultiRoomHoldAndResumeBookScenario; import com.expediagroup.sdk.rapid.examples.scenarios.booking.SingleRoomBookScenario; import com.expediagroup.sdk.rapid.examples.scenarios.content.GetPropertyContentInAdditionalLanguageScenario; import com.expediagroup.sdk.rapid.examples.scenarios.content.GetPropertyContentScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetListOfRegionNamesScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetRegionByAncestorIdScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetRegionDetailsAndPropertyIdsScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionAncestorsScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionCategoriesScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionCoordinatesScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionDescendantsScenario; -import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionWithMultiPolygonCoordinatesScenario; import com.expediagroup.sdk.rapid.examples.scenarios.managebooking.CancelHeldBookingScenario; import com.expediagroup.sdk.rapid.examples.scenarios.managebooking.ChangeRoomDetailsScenario; import com.expediagroup.sdk.rapid.examples.scenarios.managebooking.DeleteRoomScenario; @@ -159,82 +152,19 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc logger.info("=============================== End of Property Content Scenarios ==========================="); - logger.info("=============================== Running Geography Scenarios ==========================="); + logger.info("============================ Running Ad Delivery Scenarios ============================="); - /* Run Get List of Region Names Scenario using the default profile + /* Run Get Ads Scenario using the default profile This scenario demonstrates the following: - 1. Getting all regions with details in a paginated manner - 2. Filtering region names - */ - GetListOfRegionNamesScenario getListOfRegionNamesScenario = new GetListOfRegionNamesScenario(); - getListOfRegionNamesScenario.setProfile(new DefaultRapidPartnerProfile()); - getListOfRegionNamesScenario.run(); - - /* Run Get Region Name of Region Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details by region id - 2. Accessing region details - */ - GetRegionDetailsAndPropertyIdsScenario getRegionNameOfRegionScenario = new GetRegionDetailsAndPropertyIdsScenario(); - getRegionNameOfRegionScenario.setProfile(new DefaultRapidPartnerProfile()); - getRegionNameOfRegionScenario.run(); - - /* Run Get Region By Ancestor Id Scenario using the default profile - This scenario demonstrates the following: - 1. Getting paginated regions details by ancestor id - 2. Accessing region details - */ - GetRegionByAncestorIdScenario getRegionByAncestorIdScenario = new GetRegionByAncestorIdScenario(); - getRegionByAncestorIdScenario.setProfile(new DefaultRapidPartnerProfile()); - getRegionByAncestorIdScenario.run(); - - /* Run Get Region With MultiPolygon Coordinates Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details with multipolygon coordinates by region id - 2. Accessing region coordinates of type multipolygon - 3. Accessing every polygon list of coordinates. - */ - ParseRegionWithMultiPolygonCoordinatesScenario parseRegionWithMultiPolygonCoordinatesScenario = new ParseRegionWithMultiPolygonCoordinatesScenario(); - parseRegionWithMultiPolygonCoordinatesScenario.setProfile(new DefaultRapidPartnerProfile()); - parseRegionWithMultiPolygonCoordinatesScenario.run(); - - /* Run Parse Region Ancestors Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details with ancestors by region id - 2. Parsing region ancestors - */ - ParseRegionAncestorsScenario parseRegionAncestorsScenario = new ParseRegionAncestorsScenario(); - parseRegionAncestorsScenario.setProfile(new DefaultRapidPartnerProfile()); - parseRegionAncestorsScenario.run(); - - /* Run Parse Region Descendants Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details with descendants by region id - 2. Parsing region descendants - */ - ParseRegionDescendantsScenario parseRegionDescendantsScenario = new ParseRegionDescendantsScenario(); - parseRegionDescendantsScenario.setProfile(new DefaultRapidPartnerProfile()); - parseRegionDescendantsScenario.run(); - - /* Run Parse Region Coordinates Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details with coordinates by region id - 2. Parsing region coordinates - */ - ParseRegionCoordinatesScenario parseRegionCoordinatesScenario = new ParseRegionCoordinatesScenario(); - parseRegionCoordinatesScenario.setProfile(new DefaultRapidPartnerProfile()); - parseRegionCoordinatesScenario.run(); - - /* Run Parse Region Categories Scenario using the default profile - This scenario demonstrates the following: - 1. Getting region details with property ids by region id - 2. Parsing region categories + 1. Shopping for properties + 2. Getting property availability for test property + 3. Getting sponsored listings for the property */ - ParseRegionCategoriesScenario parseRegionCategoriesScenario = new ParseRegionCategoriesScenario(); - parseRegionCategoriesScenario.setProfile(new DefaultRapidPartnerProfile()); - parseRegionCategoriesScenario.run(); + GetAdsScenario getAdsScenario = new GetAdsScenario(); + getAdsScenario.setProfile(new DefaultRapidPartnerProfile()); + getAdsScenario.run(); - logger.info("=============================== End of Geography Scenarios ==========================="); + logger.info("=========================== End of Ad Delivery Scenarios ============================"); logger.info("======================================================================================="); diff --git a/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkGeographyDemoApp.java b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkGeographyDemoApp.java new file mode 100644 index 0000000000..eabe3ee05c --- /dev/null +++ b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/RapidSdkGeographyDemoApp.java @@ -0,0 +1,118 @@ +package com.expediagroup.sdk.rapid.examples; + +import com.expediagroup.sdk.rapid.examples.salesprofiles.DefaultRapidPartnerProfile; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetListOfRegionNamesScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetRegionByAncestorIdScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.GetRegionDetailsAndPropertyIdsScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionAncestorsScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionCategoriesScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionCoordinatesScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionDescendantsScenario; +import com.expediagroup.sdk.rapid.examples.scenarios.geography.ParseRegionWithMultiPolygonCoordinatesScenario; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutionException; + + +public class RapidSdkGeographyDemoApp { + + private static final Logger logger = LoggerFactory.getLogger(RapidSdkGeographyDemoApp.class); + + public static void main(String[] args) throws ExecutionException, InterruptedException { + + logger.info("======================================================================================="); + logger.info("======================================================================================="); + logger.info("== =="); + logger.info("== Howdy! This is a demonstration of Expedia Group RAPID SDK Geography, Enjoy! =="); + logger.info("== =="); + logger.info("======================================================================================="); + logger.info("======================================================================================="); + + logger.info("=============================== Running Geography Scenarios ==========================="); + + /* Run Get List of Region Names Scenario using the default profile + This scenario demonstrates the following: + 1. Getting all regions with details in a paginated manner + 2. Filtering region names + */ + GetListOfRegionNamesScenario getListOfRegionNamesScenario = new GetListOfRegionNamesScenario(); + getListOfRegionNamesScenario.setProfile(new DefaultRapidPartnerProfile()); + getListOfRegionNamesScenario.run(); + + /* Run Get Region Name of Region Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details by region id + 2. Accessing region details + */ + GetRegionDetailsAndPropertyIdsScenario getRegionNameOfRegionScenario = new GetRegionDetailsAndPropertyIdsScenario(); + getRegionNameOfRegionScenario.setProfile(new DefaultRapidPartnerProfile()); + getRegionNameOfRegionScenario.run(); + + /* Run Get Region By Ancestor Id Scenario using the default profile + This scenario demonstrates the following: + 1. Getting paginated regions details by ancestor id + 2. Accessing region details + */ + GetRegionByAncestorIdScenario getRegionByAncestorIdScenario = new GetRegionByAncestorIdScenario(); + getRegionByAncestorIdScenario.setProfile(new DefaultRapidPartnerProfile()); + getRegionByAncestorIdScenario.run(); + + /* Run Get Region With MultiPolygon Coordinates Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details with multipolygon coordinates by region id + 2. Accessing region coordinates of type multipolygon + 3. Accessing every polygon list of coordinates. + */ + ParseRegionWithMultiPolygonCoordinatesScenario parseRegionWithMultiPolygonCoordinatesScenario = new ParseRegionWithMultiPolygonCoordinatesScenario(); + parseRegionWithMultiPolygonCoordinatesScenario.setProfile(new DefaultRapidPartnerProfile()); + parseRegionWithMultiPolygonCoordinatesScenario.run(); + + /* Run Parse Region Ancestors Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details with ancestors by region id + 2. Parsing region ancestors + */ + ParseRegionAncestorsScenario parseRegionAncestorsScenario = new ParseRegionAncestorsScenario(); + parseRegionAncestorsScenario.setProfile(new DefaultRapidPartnerProfile()); + parseRegionAncestorsScenario.run(); + + /* Run Parse Region Descendants Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details with descendants by region id + 2. Parsing region descendants + */ + ParseRegionDescendantsScenario parseRegionDescendantsScenario = new ParseRegionDescendantsScenario(); + parseRegionDescendantsScenario.setProfile(new DefaultRapidPartnerProfile()); + parseRegionDescendantsScenario.run(); + + /* Run Parse Region Coordinates Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details with coordinates by region id + 2. Parsing region coordinates + */ + ParseRegionCoordinatesScenario parseRegionCoordinatesScenario = new ParseRegionCoordinatesScenario(); + parseRegionCoordinatesScenario.setProfile(new DefaultRapidPartnerProfile()); + parseRegionCoordinatesScenario.run(); + + /* Run Parse Region Categories Scenario using the default profile + This scenario demonstrates the following: + 1. Getting region details with property ids by region id + 2. Parsing region categories + */ + ParseRegionCategoriesScenario parseRegionCategoriesScenario = new ParseRegionCategoriesScenario(); + parseRegionCategoriesScenario.setProfile(new DefaultRapidPartnerProfile()); + parseRegionCategoriesScenario.run(); + + logger.info("=============================== End of Geography Scenarios ==========================="); + + logger.info("======================================================================================="); + logger.info("======================================================================================="); + logger.info("== =="); + logger.info("== That's all folks! That was the demonstration of RAPID SDK Geography. =="); + logger.info("== =="); + logger.info("======================================================================================="); + logger.info("======================================================================================="); + System.exit(0); + } +} diff --git a/examples/src/main/java/com/expediagroup/sdk/rapid/examples/scenarios/addelivery/GetAdsScenario.java b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/scenarios/addelivery/GetAdsScenario.java new file mode 100644 index 0000000000..68f74d4388 --- /dev/null +++ b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/scenarios/addelivery/GetAdsScenario.java @@ -0,0 +1,57 @@ +package com.expediagroup.sdk.rapid.examples.scenarios.addelivery; + +import com.expediagroup.sdk.core.model.Response; +import com.expediagroup.sdk.rapid.examples.Constants; +import com.expediagroup.sdk.rapid.examples.salesprofiles.RapidPartnerSalesProfile; +import com.expediagroup.sdk.rapid.examples.scenarios.RapidScenario; +import com.expediagroup.sdk.rapid.examples.services.ShopService; +import com.expediagroup.sdk.rapid.examples.services.AdDeliveryService; +import com.expediagroup.sdk.rapid.models.AdsResponse; +import com.expediagroup.sdk.rapid.models.Property; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class GetAdsScenario implements RapidScenario { + + private static final Logger logger = LoggerFactory.getLogger(GetAdsScenario.class); + private AdDeliveryService adDeliveryService = new AdDeliveryService(); + private ShopService shopService = new ShopService(); + private RapidPartnerSalesProfile rapidPartnerSalesProfile; + + @Override + public void setProfile(RapidPartnerSalesProfile rapidPartnerSalesProfile) { + this.rapidPartnerSalesProfile = rapidPartnerSalesProfile; + } + + @Override + public void run() { + + logger.info("Running Get Lodging Ads..."); + + // Shopping for properties + logger.info("Getting property availability for test property: {}", Constants.TEST_PROPERTY_ID); + + List propertyAvailabilityList = shopService.getPropertiesAvailability(Arrays.asList("2"), this.rapidPartnerSalesProfile).getData(); + + if (propertyAvailabilityList == null || propertyAvailabilityList.isEmpty()) { + throw new IllegalStateException("No property availability found for the test property."); + } + + // Get the property ids from response + ArrayList propertyIds = new ArrayList<>(); + propertyAvailabilityList.forEach(property -> propertyIds.add(property.getPropertyId())); + + // call Ad Delivery API + logger.info("Calling GetAdsOperation for property ids:"); + propertyIds.forEach(propertyId -> logger.info("Property Id: [{}]", propertyId)); + + Response adsResponse = adDeliveryService.getAds(propertyIds); + logger.info("Get ads response status: [{}]", adsResponse.getStatusCode()); + logger.info("Get ads response, number of sponsored listings: {}", adsResponse.getData() + .getSponsoredListings().size()); + } +} diff --git a/examples/src/main/java/com/expediagroup/sdk/rapid/examples/services/AdDeliveryService.java b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/services/AdDeliveryService.java new file mode 100644 index 0000000000..3fcb23c548 --- /dev/null +++ b/examples/src/main/java/com/expediagroup/sdk/rapid/examples/services/AdDeliveryService.java @@ -0,0 +1,54 @@ +package com.expediagroup.sdk.rapid.examples.services; + +import com.expediagroup.sdk.core.model.Response; +import com.expediagroup.sdk.rapid.examples.Constants; +import com.expediagroup.sdk.rapid.models.AdsRequest; +import com.expediagroup.sdk.rapid.models.AdsResponse; +import com.expediagroup.sdk.rapid.models.Coordinates1; +import com.expediagroup.sdk.rapid.models.GuestCounts; +import com.expediagroup.sdk.rapid.models.PageType; +import com.expediagroup.sdk.rapid.models.ProductLine; +import com.expediagroup.sdk.rapid.models.SalesChannel; +import com.expediagroup.sdk.rapid.operations.GetAdsOperation; +import com.expediagroup.sdk.rapid.operations.GetAdsOperationParams; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; + +public class AdDeliveryService extends RapidService { + + public Response getAds(List propertyIds) { + GetAdsOperationParams getAdsOperationParams = getAdsOperationParams(); + + AdsRequest adsRequest = AdsRequest.builder() + .checkin(LocalDate.now().plusDays(20).toString()) + .checkout(LocalDate.now().plusDays(23).toString()) + .occupancies(Arrays.asList(GuestCounts.builder().adultCount(2).childCount(0).build())) + .searchProductLines(Arrays.asList(ProductLine.LODGING)) + .propertyIds(propertyIds) + .pageType(PageType.SEARCH_RESULTS) + .salesChannel(SalesChannel.WEBSITE) + .countryCode("US") + .experimentIds(Arrays.asList("1234")) + .language("en-US") + .travelerLocation(Coordinates1.builder() + .latitude(BigDecimal.valueOf(37.7749)) + .longitude(BigDecimal.valueOf(-122.4194)) + .build()) + .build(); + + GetAdsOperation getAdsOperation = + new GetAdsOperation(getAdsOperationParams, adsRequest); + + return rapidClient.execute(getAdsOperation); + } + + private GetAdsOperationParams getAdsOperationParams() { + return GetAdsOperationParams + .builder() + .customerIp(Constants.CUSTOMER_IP) + .build(); + } +} diff --git a/specs/ad-delivery-specs.yaml b/specs/ad-delivery-specs.yaml new file mode 100644 index 0000000000..98891c9394 --- /dev/null +++ b/specs/ad-delivery-specs.yaml @@ -0,0 +1,497 @@ +openapi: 3.0.1 +info: + title: Ad Delivery API + version: v1 + description: Retrieves ads. + contact: + name: 'Media Solutions' + email: 'MediaSolutionsAPI1@expedia.com' + url: 'https://test.developers.expediagroup.com/docs/' +tags: + - name: Ad Delivery + description: API to retrieve ads +servers: + - url: https://test.ean.com/v1 + - url: https://api.ean.com/v1 +paths: + /ads: + post: + tags: + - Ad Delivery + description: Returns relevant ads. + operationId: getAds + parameters: + - name: Accept + in: header + description: Specifies the response format that the client would like to receive back. This must be application/json + required: true + schema: + type: string + example: 'application/json' + - name: Accept-Encoding + in: header + description: Specifies the response encoding that the client would like to receive back. This must be gzip. + required: true + schema: + type: string + example: 'gzip' + - name: User-Agent + in: header + description: The User-Agent header string from the customer's request, as captured by your integration. + required: true + schema: + type: string + example: 'Mozilla/5.0 (Linux; Android 13; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36' + - name: Customer-Ip + in: header + description: IP address of the customer, as captured by your integration. + Ensure your integration passes the customer's IP, not your own. This value helps determine their location for ad relevancy. + Also used for fraud recovery and other important analytics. + required: false + schema: + type: string + example: '192.168.123.132' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AdsRequest' + responses: + '200': + description: OK + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/AdsResponse' + '400': + description: Bad Request + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'invalid_input' + message: 'An invalid request was sent in, please check the nested errors for details.' + errors: + - type: 'language.required' + message: 'A language is required. Supported languages are: + [ar-SA, cs-CZ, da-DK, de-DE, el-GR, en-US, es-ES, es-MX, fi-FI, fr-CA, fr-FR, hr-HR, hu-HU, id-ID, + is-IS, it-IT, ja-JP, lt-LT, ko-KR, ms-MY, nb-NO, nl-NL, pl-PL, pt-BR, pt-PT, ru-RU, sk-SK, sv-SE, + th-TH, tr-TR, uk-UA, vi-VN, zh-CN, zh-TW]' + fields: + - name: 'language' + type: 'request' + '401': + description: Unauthorized + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'request_unauthenticated' + mesage: 'Data required to authenticate your request is missing or inaccurate. + Ensure that your request follows the guidelines in our documentation.' + fields: + - name: 'apikey' + type: 'header' + value: 'jaj3982k239dka328e' + - name: 'signature' + type: 'header' + value: '129d75332614a5bdbe0c7eb540e95a65f9d85a5b53dabb38d19b37fad6312a2bd25c12ee5a82831d55112087e1b' + - name: 'timestamp' + type: 'header' + value: '198284729' + - name: 'servertimestamp' + type: 'server' + value: '198284729' + '403': + description: Forbidden + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'request_unauthorized' + message: 'Your request could not be authorized.' + '426': + description: Upgrade Required + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'upgrade_required' + message: 'This service requires the use of TLS.' + '429': + description: Too Many Requests + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'too_many_requests' + message: 'You have reached your capacity for this type of request.' + '500': + description: Unknown Internal Error + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'unknown_internal_error' + message: 'An internal server error has occurred.' + '503': + description: Service Unavailable + headers: + Transaction-Id: + description: This is vital for deep dive investigations. + schema: + type: string + format: uuid + example: '8946d668-673c-4e98-95b4-258801ecf20c' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + type: 'service_unavailable' + message: 'This service is currently unavailable.' +components: + schemas: + PageType: + type: string + enum: + - other + - search_results + - details + - confirmation + example: 'search_results' + description: The type of page the ads will be rendered on. + Coordinates: + type: object + properties: + latitude: + type: number + example: 37.774929 + minimum: -90.0 + maximum: 90.0 + longitude: + type: number + example: -122.419418 + minimum: -180.0 + maximum: 180.0 + additionalProperties: false + SortType: + type: string + enum: + - default + example: default + description: The sort type selected for the organic results. + ProductLine: + type: string + enum: + - car + - flight + - lodging + example: lodging + description: The different types of travel product lines a traveler can search for. + SalesChannel: + type: string + enum: + - website + - mobile_app + - mobile_web + example: 'mobile_app' + description: The sales channel for the request. + GuestCounts: + type: object + required: + - adult_count + properties: + adult_count: + type: integer + format: int32 + example: 2 + child_count: + type: integer + format: int32 + example: 1 + AdsRequest: + type: object + required: + - sales_channel + - traveler_location + - language + - country_code + - page_type + - search_product_lines + - checkin + - checkout + - occupancies + - ad_candidates + properties: + country_code: + type: string + example: 'US' + pattern: '^[A-Z]{2}$' + description: "The country code of the traveler's point of sale, in ISO 3166-1 alpha-2 format. + This should represent the country where the shopping transaction is taking place. + For more information see: https://www.iso.org/obp/ui/#search/code/" + language: + type: string + example: 'en-US' + pattern: '^[a-z]{2}-[A-Z]{2}$' + description: 'Desired language for the response as a subset of BCP47 format that only uses hyphenated pairs of two-digit language and country codes. + Use only ISO 639-1 alpha-2 language codes and ISO 3166-1 alpha-2 country codes. + See https://www.w3.org/International/articles/language-tags/ + Language Options: https://developers.expediagroup.com/docs/rapid/resources/reference/language-options' + sales_channel: + $ref: '#/components/schemas/SalesChannel' + page_type: + $ref: '#/components/schemas/PageType' + sort_type: + $ref: '#/components/schemas/SortType' + traveler_location: + $ref: '#/components/schemas/Coordinates' + search_product_lines: + example: [ 'lodging', 'flight' ] + description: The product lines the traveler is searching for. lodging indicates hotel_standalone. lodging and + flight would indicate a lodging_package. + type: array + items: + $ref: '#/components/schemas/ProductLine' + checkin: + type: string + description: Check-in date, in ISO 8601 format (YYYY-MM-DD). + pattern: '^\d{4}-\d{2}-\d{2}$' + example: '2025-01-01' + checkout: + type: string + description: Check-out date, in ISO 8601 format (YYYY-MM-DD). + pattern: '^\d{4}-\d{2}-\d{2}$' + example: '2025-01-05' + occupancies: + type: array + items: + $ref: '#/components/schemas/GuestCounts' + description: Each array item represents guests of one room. + focused_property_id: + type: string + description: The property id the ranking of ads should be based on. Examples of a focused property are a + customer searching for a specific property and it being pinned to the top of a page or the property + recommendation carousel based on the currently or previously viewed property. The focused_property_id itself + will be excluded from the ranking. + example: '23433' + property_ids: + type: array + items: + type: string + example: [ '2717582', '16159546', '2025453' ] + description: The list of property ids eligible for returning sponsored listings. These are the potential + candidates that could be included in the auction. + experiment_ids: + description: A list of experiment ids that can be used for testing different behavior. The ids can be associated + with different tests ran by the publisher and are completely arbitrary. The experiment ids will + be included reports back to the publisher. + type: array + items: + type: string + example: [ '324324.1', '2423423.3', '3242343.5' ] + additionalProperties: false + Image: + type: object + properties: + caption: + type: string + description: The image caption. + example: 'Hotel Lobby' + link: + type: object + additionalProperties: + $ref: '#/components/schemas/Link' + description: The url to retrieve the image. + example: + "70px": + method: GET + href: https://i.travelapi.com/hotels/1000000/20000/15300/15237/bef1b976_t.jpg + description: An individual image. + Creative: + type: object + properties: + headline: + type: string + description: The headline of the sponsored listing. + example: 'Come see our new pool!' + description: + type: string + description: The description of the sponsored listing. + example: 'Come see our new remodeled rooms and enjoy our free buffett!' + image: + $ref: '#/components/schemas/Image' + description: The headline, description, and image to be rendered for the sponsored listing. + additionalProperties: false + Link: + type: object + properties: + method: + type: string + description: The request method used to access the link. + example: 'GET' + href: + type: string + description: The URL for the link. This can be absolute or relative. Placeholders will be need to be populated by the client. + example: 'https://advertising.expedia.com/sponsoredcontent/v1/View?position=[position]&data=AAAAAQAAAAEAAA' + expires: + type: string + description: If the link expires, this will be the UTC date the link will expire, in ISO 8601 format. + example: '2025-07-10 15:00:00.000' + description: An individual link. + Beacons: + type: object + required: + - view + - render + - click + - conversion + properties: + view: + $ref: '#/components/schemas/Link' + render: + $ref: '#/components/schemas/Link' + click: + $ref: '#/components/schemas/Link' + conversion: + $ref: '#/components/schemas/Link' + description: The view, render, click, and conversion beacons associated with the ad. + additionalProperties: false + SponsoredListing: + description: The sponsored listing which advertisers a specific property. + type: object + required: + - rank + - property_id + - beacons + properties: + rank: + type: integer + pattern: int32 + minimum: 0 + example: 1 + description: The sponsored listing should adhere to the rank and not be re-ranked. This field is 0-based. + property_id: + type: string + example: '13243534' + creative: + $ref: '#/components/schemas/Creative' + beacons: + $ref: '#/components/schemas/Beacons' + ad_transparency_url: + type: string + example: 'https://advertising.expedia.com/sponsoredcontent/dsa/id=123' + description: The url used to retrieve digital services act information regarding why the ad was selected. + additionalProperties: false + AdsResponse: + type: object + properties: + sponsored_listings: + type: array + items: + $ref: '#/components/schemas/SponsoredListing' + additionalProperties: false + Error: + type: object + properties: + type: + type: string + description: The error type. + message: + type: string + description: A human readable message giving details about this error. + fields: + type: array + description: Details about the specific fields that had an error. + items: + $ref: '#/components/schemas/Field' + errors: + type: array + description: An array of all the actual errors that occured. + items: + $ref: '#/components/schemas/ErrorIndividual' + description: The overall class of error that occured. + Field: + type: object + properties: + name: + type: string + description: The field that had an error. + type: + type: string + description: The type of the field that had an error. + value: + type: string + description: The value of the field that had an error. + description: An individual field that had an error. + ErrorIndividual: + type: object + properties: + type: + type: string + description: The error type. + message: + type: string + description: A human readable message giving details about this error. + fields: + type: array + description: Details about the specific fields that had an error. + items: + $ref: '#/components/schemas/Field' + description: An individual error. \ No newline at end of file diff --git a/specs/openapi-merge.json b/specs/openapi-merge.json new file mode 100644 index 0000000000..e1afeae52d --- /dev/null +++ b/specs/openapi-merge.json @@ -0,0 +1,17 @@ +{ + "inputs": [ + { + "inputFile": "./rapid-specs.yaml", + "pathModification": { + "prepend": "/v3" + } + }, + { + "inputFile": "./ad-delivery-specs.yaml", + "pathModification": { + "prepend": "/v1" + } + } + ], + "output": "./specs.yaml" +} diff --git a/specs.yaml b/specs/rapid-specs.yaml similarity index 99% rename from specs.yaml rename to specs/rapid-specs.yaml index 99ea261fb6..073c223067 100644 --- a/specs.yaml +++ b/specs/rapid-specs.yaml @@ -18523,4 +18523,5 @@ components: \ authentication](https://developers.expediagroup.com/docs/rapid/resources/reference/signature-authentication)\ \ page for full details." name: Authorization - in: header \ No newline at end of file + in: header +