diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md
new file mode 100644
index 000000000..49de7a8da
--- /dev/null
+++ b/DOCUMENTATION.md
@@ -0,0 +1,499 @@
+# Expedia Group Java SDK Foundations - Complete Documentation
+
+## Overview
+
+The **Expedia Group Java SDK Foundations** is a comprehensive toolkit for building and maintaining Java/Kotlin SDKs that interact with Expedia Group's platform APIs. This repository provides the core infrastructure, tools, and components needed to generate, build, and publish production-ready SDKs for various Expedia Group services.
+
+## ๐๏ธ Architecture
+
+The repository is organized into several key components:
+
+### Core Components
+
+```
+expediagroup-java-sdk/
+โโโ core/ # Core SDK libraries and utilities
+โโโ generator/ # SDK generation tools
+โ โโโ openapi/ # OpenAPI-based code generator
+โโโ release/ # Generated SDK releases
+โ โโโ rapid/ # Rapid SDK implementation
+โ โโโ fraudPreventionV2/ # Fraud Prevention V2 SDK
+โโโ sdk-test/ # Shared testing framework
+โโโ .github/workflows/ # Reusable CI/CD workflows
+```
+
+### 1. SDK Core (`/core`)
+The foundation layer providing:
+- **Base client classes** (`BaseRapidClient`, `ExpediaGroupClient`, `BaseXapClient`)
+- **Authentication strategies** (Bearer token, Basic auth, Signature-based)
+- **HTTP client configuration** with OkHttp integration
+- **Error handling and exception mapping**
+- **Logging, serialization, and plugin architecture**
+- **Configuration management**
+
+### 2. SDK Generator (`/generator`)
+OpenAPI-based code generation toolkit:
+- **Mustache templates** for consistent code generation
+- **Custom Kotlin/Java generators** extending OpenAPI tooling
+- **Model and operation generation** from OpenAPI specs
+- **Documentation generation** capabilities
+
+### 3. Release SDKs (`/release`)
+Generated, production-ready SDKs:
+- **Rapid SDK**: Hotel booking and management APIs
+- **Fraud Prevention V2 SDK**: Fraud detection services
+
+## ๐ Quick Start
+
+### Prerequisites
+
+- **Java 8+** (JDK 8 or later)
+- **Maven 3.8.0+** (or use included Maven wrapper)
+- **OpenAPI 3.0+ specification** for your target API
+
+### Building the Foundation
+
+```bash
+# Clone the repository
+git clone https://github.com/ExpediaGroup/expediagroup-java-sdk.git
+cd expediagroup-java-sdk
+
+# Build core components
+./mvnw clean install
+```
+
+### Generating a New SDK
+
+```bash
+# Build the generator
+cd generator/openapi
+mvn clean install
+
+# Generate SDK (creates sample in target/sdk)
+../../mvnw exec:java
+
+# Build the generated SDK
+cd target/sdk
+../../../mvnw clean install
+```
+
+## ๐ Usage Guide
+
+### Using Generated SDKs
+
+#### 1. Add SDK Dependency
+
+**Maven:**
+```xml
+
+ com.expediagroup
+ rapid-sdk
+ 5.0.1
+
+```
+
+**Gradle:**
+```groovy
+implementation 'com.expediagroup:rapid-sdk:5.0.1'
+```
+
+#### 2. Initialize the Client
+
+```kotlin
+// Create Rapid client
+val rapidClient = RapidClient.builder()
+ .key("your-api-key")
+ .secret("your-api-secret")
+ .endpoint("https://test.ean.com/v3") // or production endpoint
+ .build()
+```
+
+#### 3. Execute Operations
+
+The SDKs use an **operation-based pattern** where each API call is represented as an operation:
+
+```kotlin
+// Search for available properties
+val availabilityOperation = GetAvailabilityOperationContext.builder()
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .occupancy(listOf("2"))
+ .currency("USD")
+ .language("en-US")
+ .countryCode("US")
+ .propertyId(listOf("12345"))
+ .customerIp("192.168.1.1")
+ .build()
+
+val response = rapidClient.execute(availabilityOperation)
+val properties = response.data // List
+```
+
+```kotlin
+// Create a booking
+val bookingRequest = CreateItineraryRequest.builder()
+ .affiliateReferenceId("your-ref-123")
+ .hold(false)
+ .email("customer@example.com")
+ .phone(PhoneRequest.builder()
+ .countryCode("1")
+ .areaCode("555")
+ .number("1234567")
+ .build())
+ .rooms(listOf(
+ CreateItineraryRequestRoom.builder()
+ .occupancy(CreateItineraryRequestRoomOccupancy.builder()
+ .numberOfAdults(2)
+ .build())
+ .ratePlanId("rate-plan-123")
+ .build()
+ ))
+ .build()
+
+val itineraryOperation = PostItineraryOperation(
+ PostItineraryOperationParams.builder()
+ .customerIp("192.168.1.1")
+ .customerSessionId("session-123")
+ .build(),
+ bookingRequest
+)
+
+val bookingResponse = rapidClient.execute(itineraryOperation)
+val itinerary = bookingResponse.data // ItineraryCreation
+```
+
+#### 4. Retrieve Reservations
+
+```kotlin
+// Get reservation details
+val reservationOperation = GetReservationByItineraryIdOperation(
+ GetReservationByItineraryIdOperationParams.builder()
+ .itineraryId("12345")
+ .customerIp("192.168.1.1")
+ .include(listOf(
+ GetReservationByItineraryIdOperationParams.Include.HISTORY,
+ GetReservationByItineraryIdOperationParams.Include.LINKS
+ ))
+ .build()
+)
+
+val reservationResponse = rapidClient.execute(reservationOperation)
+val reservation = reservationResponse.data // Itinerary
+```
+
+### Asynchronous Operations
+
+All operations support async execution:
+
+```kotlin
+val futureResponse = rapidClient.executeAsync(availabilityOperation)
+futureResponse.thenAccept { response ->
+ val properties = response.data
+ // Process properties
+}
+```
+
+### Error Handling
+
+The SDKs use typed exceptions for different error scenarios:
+
+```kotlin
+try {
+ val response = rapidClient.execute(operation)
+ // Success handling
+} catch (e: ExpediaGroupApiErrorException) {
+ // API returned an error response
+ val errorResponse = e.errorResponse
+ when (errorResponse) {
+ is RapidError -> {
+ // Handle Rapid-specific errors
+ println("Error: ${errorResponse.errors}")
+ }
+ }
+} catch (e: ExpediaGroupServiceException) {
+ // Service-level errors (network, timeout, etc.)
+ println("Service error: ${e.message}")
+} catch (e: ExpediaGroupConfigurationException) {
+ // Configuration errors (missing keys, etc.)
+ println("Configuration error: ${e.message}")
+}
+```
+
+### Builder Pattern
+
+All request objects and operations use the builder pattern:
+
+```kotlin
+val propertyContentParams = GetPropertyContentOperationParams.builder()
+ .propertyId(listOf("12345", "67890"))
+ .language("en-US")
+ .supply_source("expedia")
+ .include(listOf(
+ GetPropertyContentOperationParams.Include.THEMES,
+ GetPropertyContentOperationParams.Include.AMENITIES
+ ))
+ .build()
+```
+
+### Response Handling
+
+Responses are wrapped in a `Response` object:
+
+```kotlin
+val response = rapidClient.execute(operation)
+
+// Access response data
+val data = response.data
+
+// Access response metadata
+val headers = response.headers
+val statusCode = response.statusCode
+val transactionId = response.transactionId
+```
+
+### Configuration Options
+
+#### Basic Configuration
+
+```kotlin
+val client = RapidClient.builder()
+ .key("api-key")
+ .secret("api-secret")
+ .endpoint("https://api.ean.com/v3")
+ .requestTimeout(30000) // 30 seconds
+ .connectionTimeout(10000) // 10 seconds
+ .socketTimeout(60000) // 60 seconds
+ .build()
+```
+
+#### Advanced Configuration
+
+```kotlin
+// Custom OkHttpClient
+val customOkHttpClient = OkHttpClient.Builder()
+ .connectionPool(ConnectionPool(10, 5, TimeUnit.MINUTES))
+ .addInterceptor(customInterceptor)
+ .build()
+
+val client = RapidClient.builder()
+ .key("api-key")
+ .secret("api-secret")
+ .httpClient(customOkHttpClient)
+ .maskedLoggingHeaders(setOf("Authorization", "X-API-Key"))
+ .maskedLoggingBodyFields(setOf("password", "creditCard"))
+ .build()
+```
+
+### Environment Configuration
+
+SDKs support multiple environments:
+
+```kotlin
+// Test environment
+val testClient = RapidClient.builder()
+ .key("test-key")
+ .secret("test-secret")
+ .endpoint("https://test.ean.com/v3")
+ .build()
+
+// Production environment
+val prodClient = RapidClient.builder()
+ .key("prod-key")
+ .secret("prod-secret")
+ .endpoint("https://api.ean.com/v3")
+ .build()
+```
+
+## ๐ง Customization and Extension
+
+### Custom Authentication
+
+Implement custom authentication strategies:
+
+```kotlin
+class CustomAuthStrategy : AuthenticationStrategy {
+ override fun loadAuth(auth: Auth) {
+ // Custom auth logic
+ }
+
+ override fun getAuthorizationHeader(): String {
+ // Return custom auth header
+ }
+}
+```
+
+### Custom HTTP Interceptors
+
+Add custom request/response processing:
+
+```kotlin
+val customClient = OkHttpClient.Builder()
+ .addInterceptor { chain ->
+ val request = chain.request().newBuilder()
+ .addHeader("X-Custom-Header", "value")
+ .build()
+ chain.proceed(request)
+ }
+ .build()
+```
+
+## ๐ SDK Generation
+
+### Generating Custom SDKs
+
+1. **Prepare OpenAPI Specification**
+ - Ensure your API has a valid OpenAPI 3.0+ specification
+ - Use [Spec Transformer](https://github.com/ExpediaGroup/spec-transformer) if needed
+
+2. **Configure Generation**
+ ```bash
+ cd generator/openapi
+ # Modify generation configuration as needed
+ ../../mvnw exec:java
+ ```
+
+3. **Customize Templates**
+ - Templates are located in `generator/openapi/src/main/resources/templates/`
+ - Modify Mustache templates for custom code generation
+
+4. **Build Generated SDK**
+ ```bash
+ cd target/sdk
+ ../../../mvnw clean install
+ ```
+
+### Publishing SDKs
+
+Use the provided GitHub Actions workflows:
+
+1. **Manual Release**: `.github/workflows/manual-release.yml`
+2. **Automated Publishing**: Configurable for Maven Central
+3. **Documentation Generation**: Integrated Dokka support
+
+## ๐งช Testing
+
+### Unit Testing
+
+```kotlin
+// Test with mock responses
+@Test
+fun testGetAvailability() {
+ val mockClient = createMockRapidClient()
+ val operation = GetAvailabilityOperationContext.builder()
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .build()
+
+ val response = mockClient.execute(operation)
+ assertThat(response.data).isNotEmpty()
+}
+```
+
+### Integration Testing
+
+```kotlin
+// Test against sandbox environment
+@Test
+@IntegrationTest
+fun testRealApiCall() {
+ val client = RapidClient.builder()
+ .key(System.getenv("TEST_API_KEY"))
+ .secret(System.getenv("TEST_API_SECRET"))
+ .endpoint("https://test.ean.com/v3")
+ .build()
+
+ // Perform real API calls
+}
+```
+
+## ๐ Best Practices
+
+### 1. Resource Management
+```kotlin
+// Use try-with-resources for file operations
+response.data.use { file ->
+ // Process file content
+}
+```
+
+### 2. Error Handling
+```kotlin
+// Always handle specific exceptions
+try {
+ val response = client.execute(operation)
+ return response.data
+} catch (e: ExpediaGroupApiErrorException) {
+ logger.error("API error: ${e.errorResponse}")
+ throw BusinessException("Booking failed", e)
+} catch (e: ExpediaGroupServiceException) {
+ logger.error("Service error: ${e.message}")
+ throw ServiceUnavailableException("Service temporarily unavailable", e)
+}
+```
+
+### 3. Configuration Management
+```kotlin
+// Use configuration objects for reusable settings
+class ApiConfiguration {
+ companion object {
+ fun createTestClient() = RapidClient.builder()
+ .key(System.getenv("TEST_API_KEY"))
+ .secret(System.getenv("TEST_API_SECRET"))
+ .endpoint("https://test.ean.com/v3")
+ .requestTimeout(30000)
+ .build()
+ }
+}
+```
+
+### 4. Logging
+```kotlin
+// Configure structured logging
+val client = RapidClient.builder()
+ .key("api-key")
+ .secret("api-secret")
+ .maskedLoggingHeaders(setOf("Authorization"))
+ .maskedLoggingBodyFields(setOf("creditCard", "ssn"))
+ .build()
+```
+
+## ๐ Available SDKs
+
+| SDK | Description | Maven Central | Documentation |
+|-----|-------------|---------------|---------------|
+| **Rapid SDK** | Hotel booking, availability, and management | [](https://central.sonatype.com/artifact/com.expediagroup/rapid-sdk) | [Rapid SDK Docs](https://developers.expediagroup.com/docs/products/rapid/sdk/java) |
+| **EWS XAP SDK** | Expedia Web Services XML API | [](https://central.sonatype.com/artifact/com.expediagroup/xap-sdk) | [XAP SDK Docs](https://developers.expediagroup.com/xap/sdk) |
+| **Fraud Prevention V2** | Fraud detection and prevention | [](https://central.sonatype.com/artifact/com.expediagroup/fraudpreventionv2-sdk) | [Fraud Prevention Docs](https://developers.expediagroup.com/docs/products/fraud-prevention/v2) |
+
+## ๐ค Contributing
+
+1. **Fork the repository**
+2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
+3. **Make changes and add tests**
+4. **Commit changes**: `git commit -m 'Add amazing feature'`
+5. **Push to branch**: `git push origin feature/amazing-feature`
+6. **Create Pull Request**
+
+See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
+
+## ๐ License
+
+This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
+
+## ๐ Support
+
+- **Repository Issues**: [GitHub Issues](https://github.com/ExpediaGroup/expediagroup-java-sdk/issues)
+- **SDK-Specific Support**: Refer to individual SDK repositories
+- **Developer Hub**: [Expedia Group Developer Portal](https://developers.expediagroup.com/)
+
+## ๐ Version History
+
+| Version | Release Date | Key Changes |
+|---------|-------------|-------------|
+| 5.0.1 | Latest | Current stable release |
+| 5.0.0 | 2024 | Major version with breaking changes |
+| 4.x.x | 2023 | Previous stable series |
+
+---
+
+**Made with โค๏ธ by the Expedia Group Platform Team**
diff --git a/SDK_GENERATION_GUIDE.md b/SDK_GENERATION_GUIDE.md
new file mode 100644
index 000000000..7dd262178
--- /dev/null
+++ b/SDK_GENERATION_GUIDE.md
@@ -0,0 +1,656 @@
+# SDK Generation Guide
+
+## Overview
+
+This guide explains how to use the Expedia Group Java SDK Foundations to generate custom SDKs from OpenAPI specifications.
+
+## ๐ฏ Who This Guide Is For
+
+- **API Providers** who want to generate Java/Kotlin SDKs for their APIs
+- **Platform Teams** building internal SDKs
+- **Developers** extending existing SDKs with custom functionality
+
+## ๐๏ธ SDK Generation Architecture
+
+### Core Components
+
+1. **OpenAPI Generator**: Extended OpenAPI code generator with custom templates
+2. **Mustache Templates**: Customizable templates for code generation
+3. **Core Libraries**: Shared utilities and base classes
+4. **Build System**: Maven-based build and publishing pipeline
+
+### Generated SDK Structure
+
+```
+generated-sdk/
+โโโ src/main/kotlin/
+โ โโโ client/ # SDK client classes
+โ โ โโโ MyApiClient.kt # Main client implementation
+โ โโโ models/ # Data models
+โ โ โโโ Request*.kt # Request objects
+โ โ โโโ Response*.kt # Response objects
+โ โ โโโ *.kt # Domain models
+โ โโโ operations/ # Operation definitions
+โ โโโ *Operation.kt # Operation classes
+โ โโโ *OperationParams.kt # Parameter classes
+โ โโโ *OperationContext.kt # Context classes
+โโโ docs/ # Generated documentation
+โโโ pom.xml # Maven configuration
+```
+
+## ๐ Getting Started
+
+### Prerequisites
+
+1. **OpenAPI Specification** (3.0+) for your API
+2. **Java 8+** development environment
+3. **Maven 3.8+** build tool
+
+### Step 1: Prepare Your OpenAPI Spec
+
+Ensure your OpenAPI specification follows best practices:
+
+```yaml
+openapi: 3.0.3
+info:
+ title: My API
+ version: 1.0.0
+ description: Custom API for demonstration
+servers:
+ - url: https://api.example.com/v1
+ description: Production server
+ - url: https://test-api.example.com/v1
+ description: Test server
+
+paths:
+ /hotels/search:
+ post:
+ operationId: searchHotels
+ summary: Search for hotels
+ parameters:
+ - name: X-Customer-IP
+ in: header
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SearchRequest'
+ responses:
+ '200':
+ description: Search results
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SearchResponse'
+
+components:
+ schemas:
+ SearchRequest:
+ type: object
+ required:
+ - destination
+ - checkin
+ - checkout
+ properties:
+ destination:
+ type: string
+ description: Destination city or property ID
+ checkin:
+ type: string
+ format: date
+ description: Check-in date (YYYY-MM-DD)
+ checkout:
+ type: string
+ format: date
+ description: Check-out date (YYYY-MM-DD)
+ guests:
+ type: integer
+ minimum: 1
+ maximum: 8
+ default: 2
+ description: Number of guests
+
+ SearchResponse:
+ type: object
+ properties:
+ hotels:
+ type: array
+ items:
+ $ref: '#/components/schemas/Hotel'
+ totalResults:
+ type: integer
+
+ Hotel:
+ type: object
+ properties:
+ id:
+ type: string
+ description: Unique hotel identifier
+ name:
+ type: string
+ description: Hotel name
+ location:
+ $ref: '#/components/schemas/Location'
+ pricePerNight:
+ $ref: '#/components/schemas/Price'
+
+ Location:
+ type: object
+ properties:
+ city:
+ type: string
+ country:
+ type: string
+ coordinates:
+ $ref: '#/components/schemas/Coordinates'
+
+ Coordinates:
+ type: object
+ properties:
+ latitude:
+ type: number
+ format: double
+ longitude:
+ type: number
+ format: double
+
+ Price:
+ type: object
+ properties:
+ amount:
+ type: number
+ format: double
+ currency:
+ type: string
+ pattern: '^[A-Z]{3}$'
+
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+
+security:
+ - ApiKeyAuth: []
+```
+
+### Step 2: Configure the Generator
+
+1. **Clone the repository**:
+ ```bash
+ git clone https://github.com/ExpediaGroup/expediagroup-java-sdk.git
+ cd expediagroup-java-sdk
+ ```
+
+2. **Place your OpenAPI spec**:
+ ```bash
+ cp your-api-spec.yaml generator/openapi/src/main/resources/specs/
+ ```
+
+3. **Configure generation parameters**:
+
+ Edit `generator/openapi/pom.xml` to customize generation:
+
+ ```xml
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ --input-spec=src/main/resources/specs/your-api-spec.yaml
+
+
+ --output=target/sdk
+
+
+ --package-name=com.example.sdk.myapi
+ --client-name=MyApiClient
+ --sdk-version=1.0.0
+
+
+ --base-url=https://api.example.com/v1
+ --auth-type=API_KEY
+
+
+
+ ```
+
+### Step 3: Generate the SDK
+
+```bash
+# Build the generator
+cd generator/openapi
+mvn clean install
+
+# Generate your SDK
+../../mvnw exec:java
+
+# Build the generated SDK
+cd target/sdk
+../../../mvnw clean install
+```
+
+### Step 4: Test the Generated SDK
+
+The generator creates a basic test structure:
+
+```kotlin
+// Generated client usage
+val client = MyApiClient.builder()
+ .key("your-api-key")
+ .endpoint("https://test-api.example.com/v1")
+ .build()
+
+// Search for hotels
+val searchRequest = SearchRequest.builder()
+ .destination("New York")
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .guests(2)
+ .build()
+
+val searchParams = SearchHotelsOperationParams.builder()
+ .customerIp("192.168.1.1")
+ .build()
+
+val operation = SearchHotelsOperation(searchParams, searchRequest)
+val response = client.execute(operation)
+
+response.data.hotels?.forEach { hotel ->
+ println("Hotel: ${hotel.name} - ${hotel.pricePerNight?.amount} ${hotel.pricePerNight?.currency}")
+}
+```
+
+## ๐จ Customization
+
+### Custom Templates
+
+The generator uses Mustache templates located in `generator/openapi/src/main/resources/templates/`:
+
+```
+templates/
+โโโ client.mustache # Main client class
+โโโ model.mustache # Data model classes
+โโโ operation.mustache # Operation classes
+โโโ operationParams.mustache # Parameter classes
+โโโ pom.mustache # Maven POM file
+โโโ README.mustache # SDK documentation
+```
+
+#### Customizing the Client Template
+
+Edit `templates/client.mustache`:
+
+```mustache
+package {{package}}.client
+
+import {{package}}.models.*
+import {{package}}.operations.*
+import com.expediagroup.sdk.core.client.BaseExpediaGroupClient
+import com.expediagroup.sdk.core.configuration.ExpediaGroupClientConfiguration
+
+/**
+ * {{appName}} SDK Client
+ * {{appDescription}}
+ *
+ * Generated on: {{generatedDate}}
+ * Version: {{sdkVersion}}
+ */
+class {{classname}} private constructor(
+ clientConfiguration: ExpediaGroupClientConfiguration
+) : BaseExpediaGroupClient("{{packageName}}", clientConfiguration) {
+
+ class Builder : BaseExpediaGroupClient.Builder() {
+ override fun build() = {{classname}}(
+ ExpediaGroupClientConfiguration(
+ key, secret, endpoint, requestTimeout,
+ connectionTimeout, socketTimeout,
+ maskedLoggingHeaders, maskedLoggingBodyFields
+ )
+ )
+ }
+
+ companion object {
+ @JvmStatic fun builder() = Builder()
+ }
+
+ {{#operations}}
+ {{#operation}}
+ /**
+ * {{summary}}
+ * {{notes}}
+ {{#allParams}}
+ * @param {{paramName}} {{description}}
+ {{/allParams}}
+ * @throws ExpediaGroupApiErrorException
+ * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}EmptyResponse{{/returnType}}
+ */
+ fun execute(operation: {{classname}}Operation): {{#returnType}}Response<{{returnType}}>{{/returnType}}{{^returnType}}EmptyResponse{{/returnType}} {
+ return {{#returnType}}execute<{{operationIdCamelCase}}Request, {{returnType}}>(operation){{/returnType}}{{^returnType}}executeWithEmptyResponse<{{operationIdCamelCase}}Request>(operation){{/returnType}}
+ }
+
+ {{/operation}}
+ {{/operations}}
+}
+```
+
+### Custom Model Generation
+
+Edit `templates/model.mustache` for custom model structures:
+
+```mustache
+package {{package}}.models
+
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+{{#imports}}
+import {{import}}
+{{/imports}}
+
+/**
+ * {{description}}
+ {{#vars}}
+ * @param {{name}} {{description}}
+ {{/vars}}
+ */
+@JsonDeserialize(builder = {{classname}}.Builder::class)
+data class {{classname}}(
+{{#vars}}
+ @get:JsonProperty("{{baseName}}")
+ val {{name}}: {{dataType}}{{#hasDefaultValue}} = {{{defaultValue}}}{{/hasDefaultValue}}{{^hasDefaultValue}}{{#isNullable}}? = null{{/isNullable}}{{/hasDefaultValue}}{{#hasMore}},{{/hasMore}}
+{{/vars}}
+) {
+ companion object {
+ fun builder() = Builder()
+ }
+
+ class Builder {
+ {{#vars}}
+ @JsonProperty("{{baseName}}")
+ private var {{name}}: {{dataType}}{{#isNullable}}?{{/isNullable}} = {{#hasDefaultValue}}{{{defaultValue}}}{{/hasDefaultValue}}{{^hasDefaultValue}}{{#isNullable}}null{{/isNullable}}{{^isNullable}}TODO("Required field"){{/isNullable}}{{/hasDefaultValue}}
+
+ fun {{name}}({{name}}: {{dataType}}{{#isNullable}}?{{/isNullable}}) = apply { this.{{name}} = {{name}} }
+ {{/vars}}
+
+ fun build(): {{classname}} {
+ return {{classname}}(
+ {{#vars}}
+ {{name}} = {{name}}{{#hasMore}},{{/hasMore}}
+ {{/vars}}
+ )
+ }
+ }
+}
+```
+
+### Advanced Configuration
+
+#### Custom Authentication
+
+For APIs with custom authentication, modify the generator configuration:
+
+```yaml
+# In your generation config
+authType: CUSTOM
+authTemplate: |
+ override fun getAuthenticationStrategy(): AuthenticationStrategy {
+ return MyCustomAuthStrategy(configurationProvider)
+ }
+```
+
+#### Custom Error Handling
+
+Add custom error mapping:
+
+```yaml
+errorMapping:
+ 400: BadRequestException
+ 401: UnauthorizedException
+ 403: ForbiddenException
+ 404: NotFoundException
+ 500: InternalServerErrorException
+```
+
+### Step 5: Publishing Your SDK
+
+#### Configure Maven for Publishing
+
+Update the generated `pom.xml`:
+
+```xml
+com.example
+myapi-sdk
+1.0.0
+My API SDK
+SDK for My API
+https://github.com/example/myapi-sdk
+
+
+
+ Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Your Name
+ your.email@example.com
+ Your Organization
+
+
+
+
+ scm:git:git@github.com:example/myapi-sdk.git
+ scm:git:git@github.com:example/myapi-sdk.git
+ https://github.com/example/myapi-sdk
+
+```
+
+#### GitHub Actions for CI/CD
+
+Create `.github/workflows/publish.yml`:
+
+```yaml
+name: Publish SDK
+on:
+ release:
+ types: [published]
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v3
+ with:
+ java-version: '8'
+ distribution: 'temurin'
+
+ - name: Build and publish
+ run: |
+ mvn clean install
+ mvn deploy
+ env:
+ MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
+ MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
+```
+
+## ๐งช Testing Generated SDKs
+
+### Unit Testing Template
+
+The generator creates a testing framework:
+
+```kotlin
+@ExtendWith(MockitoExtension::class)
+class MyApiClientTest {
+
+ @Mock
+ private lateinit var httpClient: HttpClient
+
+ private lateinit var client: MyApiClient
+
+ @BeforeEach
+ fun setup() {
+ client = MyApiClient.builder()
+ .key("test-key")
+ .secret("test-secret")
+ .endpoint("https://test-api.example.com/v1")
+ .build()
+ }
+
+ @Test
+ fun `searchHotels should return valid response`() {
+ // Given
+ val searchRequest = SearchRequest.builder()
+ .destination("New York")
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .build()
+
+ val expectedResponse = SearchResponse.builder()
+ .hotels(listOf(
+ Hotel.builder()
+ .id("hotel-123")
+ .name("Test Hotel")
+ .build()
+ ))
+ .totalResults(1)
+ .build()
+
+ // When
+ val operation = SearchHotelsOperation(
+ SearchHotelsOperationParams.builder()
+ .customerIp("192.168.1.1")
+ .build(),
+ searchRequest
+ )
+
+ val response = client.execute(operation)
+
+ // Then
+ assertThat(response.data.hotels).hasSize(1)
+ assertThat(response.data.hotels?.first()?.name).isEqualTo("Test Hotel")
+ }
+}
+```
+
+### Integration Testing
+
+```kotlin
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+class MyApiClientIntegrationTest {
+
+ private lateinit var client: MyApiClient
+
+ @BeforeAll
+ fun setup() {
+ client = MyApiClient.builder()
+ .key(System.getenv("TEST_API_KEY"))
+ .secret(System.getenv("TEST_API_SECRET"))
+ .endpoint("https://test-api.example.com/v1")
+ .build()
+ }
+
+ @Test
+ fun `should perform real API call`() {
+ val searchRequest = SearchRequest.builder()
+ .destination("New York")
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .guests(2)
+ .build()
+
+ val operation = SearchHotelsOperation(
+ SearchHotelsOperationParams.builder()
+ .customerIp("192.168.1.1")
+ .build(),
+ searchRequest
+ )
+
+ val response = client.execute(operation)
+
+ assertThat(response.statusCode).isEqualTo(200)
+ assertThat(response.data.hotels).isNotNull()
+ }
+}
+```
+
+## ๐ Best Practices
+
+### 1. OpenAPI Specification Guidelines
+
+- **Use descriptive operation IDs**: These become method names
+- **Include comprehensive examples**: Used in documentation generation
+- **Define reusable components**: Reduces code duplication
+- **Use appropriate HTTP status codes**: Enables proper error handling
+- **Add detailed descriptions**: Improves generated documentation
+
+### 2. SDK Design Patterns
+
+- **Builder pattern**: All request objects use builders for flexibility
+- **Operation pattern**: Each API call is represented as an operation object
+- **Response wrapping**: Responses include metadata (headers, status codes)
+- **Type safety**: Strong typing for all parameters and responses
+- **Error handling**: Specific exceptions for different error scenarios
+
+### 3. Versioning Strategy
+
+```xml
+
+1.0.0
+
+
+2.0.0
+1.1.0
+1.0.1
+```
+
+### 4. Documentation Generation
+
+The generator can create comprehensive documentation:
+
+```bash
+# Generate Dokka documentation
+mvn dokka:dokka
+
+# Generate OpenAPI documentation
+mvn exec:java -Dexec.args="--generate-docs"
+```
+
+## ๐ง Troubleshooting
+
+### Common Issues
+
+1. **Generator fails to parse OpenAPI spec**:
+ - Validate your spec using [Swagger Editor](https://editor.swagger.io/)
+ - Check for circular references in schemas
+ - Ensure all `$ref` references are valid
+
+2. **Generated code doesn't compile**:
+ - Check for reserved keywords in property names
+ - Verify all required dependencies are included
+ - Review custom template syntax
+
+3. **Authentication not working**:
+ - Verify security scheme definitions in OpenAPI spec
+ - Check API key/secret configuration
+ - Review endpoint URLs (test vs production)
+
+### Debug Mode
+
+Enable debug logging during generation:
+
+```bash
+mvn exec:java -Dexec.args="--verbose --debug"
+```
+
+This comprehensive guide provides everything needed to generate custom SDKs using the Expedia Group Java SDK Foundations.
diff --git a/SDK_USAGE_GUIDE.md b/SDK_USAGE_GUIDE.md
new file mode 100644
index 000000000..20e2e4376
--- /dev/null
+++ b/SDK_USAGE_GUIDE.md
@@ -0,0 +1,490 @@
+# SDK Usage Guide
+
+## Quick Start for SDK Users
+
+This guide shows you how to use the generated Expedia Group SDKs in your applications.
+
+## ๐จ Rapid SDK - Hotel Booking
+
+### Installation
+
+```xml
+
+ com.expediagroup
+ rapid-sdk
+ 5.0.1
+
+```
+
+### Basic Setup
+
+```kotlin
+val rapidClient = RapidClient.builder()
+ .key("your-api-key")
+ .secret("your-api-secret")
+ .endpoint("https://test.ean.com/v3") // Test environment
+ .build()
+```
+
+### Common Operations
+
+#### 1. Search for Hotels
+
+```kotlin
+// Search for available properties
+val searchParams = GetAvailabilityOperationParams.builder()
+ .checkin("2024-12-01")
+ .checkout("2024-12-03")
+ .occupancy(listOf("2")) // 2 adults
+ .currency("USD")
+ .language("en-US")
+ .countryCode("US")
+ .propertyId(listOf("12345"))
+ .customerIp("192.168.1.1")
+ .build()
+
+val searchOperation = GetAvailabilityOperation(searchParams)
+val response = rapidClient.execute(searchOperation)
+
+response.data.forEach { property ->
+ println("Property: ${property.propertyId}")
+ property.roomTypes?.forEach { room ->
+ println(" Room: ${room.name} - ${room.ratePlans?.firstOrNull()?.price?.total?.inclusive}")
+ }
+}
+```
+
+#### 2. Get Property Details
+
+```kotlin
+val contentParams = GetPropertyContentOperationParams.builder()
+ .propertyId(listOf("12345"))
+ .language("en-US")
+ .include(listOf(
+ GetPropertyContentOperationParams.Include.AMENITIES,
+ GetPropertyContentOperationParams.Include.IMAGES,
+ GetPropertyContentOperationParams.Include.THEMES
+ ))
+ .build()
+
+val contentOperation = GetPropertyContentOperation(contentParams)
+val contentResponse = rapidClient.execute(contentOperation)
+
+contentResponse.data.forEach { (propertyId, content) ->
+ println("Property: ${content.name}")
+ println("Description: ${content.descriptions?.overview}")
+ println("Address: ${content.address?.line1}, ${content.address?.city}")
+
+ content.images?.forEach { image ->
+ println("Image: ${image.url}")
+ }
+}
+```
+
+#### 3. Create a Booking
+
+```kotlin
+// Build the booking request
+val guestInfo = CreateItineraryRequestRoomsGuestInfo.builder()
+ .firstName("John")
+ .lastName("Doe")
+ .build()
+
+val room = CreateItineraryRequestRoom.builder()
+ .occupancy(CreateItineraryRequestRoomOccupancy.builder()
+ .numberOfAdults(2)
+ .build())
+ .ratePlanId("12345-rate-plan")
+ .guestInfo(listOf(guestInfo))
+ .build()
+
+val bookingRequest = CreateItineraryRequest.builder()
+ .affiliateReferenceId("your-booking-ref-${System.currentTimeMillis()}")
+ .hold(false) // false = book immediately, true = hold reservation
+ .email("john.doe@example.com")
+ .phone(PhoneRequest.builder()
+ .countryCode("1")
+ .areaCode("555")
+ .number("1234567")
+ .build())
+ .rooms(listOf(room))
+ .payments(listOf(
+ PaymentRequest.builder()
+ .type(PaymentRequest.Type.CUSTOMER_CARD)
+ .number("4111111111111111")
+ .expirationMonth("12")
+ .expirationYear("2025")
+ .securityCode("123")
+ .build()
+ ))
+ .build()
+
+val bookingParams = PostItineraryOperationParams.builder()
+ .customerIp("192.168.1.1")
+ .customerSessionId("session-${System.currentTimeMillis()}")
+ .build()
+
+val bookingOperation = PostItineraryOperation(bookingParams, bookingRequest)
+
+try {
+ val bookingResponse = rapidClient.execute(bookingOperation)
+ val itinerary = bookingResponse.data
+
+ println("Booking successful!")
+ println("Itinerary ID: ${itinerary.itineraryId}")
+ println("Confirmation Number: ${itinerary.confirmationId}")
+
+ itinerary.rooms?.forEach { room ->
+ println("Room ${room.id}: ${room.confirmationId}")
+ }
+
+} catch (e: ExpediaGroupApiErrorException) {
+ println("Booking failed: ${e.message}")
+ // Handle specific error scenarios
+ when (val error = e.errorResponse) {
+ is RapidError -> {
+ error.errors?.forEach { err ->
+ println("Error: ${err.type} - ${err.message}")
+ }
+ }
+ }
+}
+```
+
+#### 4. Retrieve Existing Booking
+
+```kotlin
+val retrieveParams = GetReservationByItineraryIdOperationParams.builder()
+ .itineraryId("12345678")
+ .customerIp("192.168.1.1")
+ .include(listOf(
+ GetReservationByItineraryIdOperationParams.Include.HISTORY,
+ GetReservationByItineraryIdOperationParams.Include.LINKS
+ ))
+ .build()
+
+val retrieveOperation = GetReservationByItineraryIdOperation(retrieveParams)
+val reservationResponse = rapidClient.execute(retrieveOperation)
+
+val reservation = reservationResponse.data
+println("Booking Status: ${reservation.bookingStatus}")
+println("Total Price: ${reservation.totalAmount}")
+
+reservation.rooms?.forEach { room ->
+ println("Room: ${room.ratePlans?.firstOrNull()?.description}")
+ println("Check-in: ${room.checkIn}")
+ println("Check-out: ${room.checkOut}")
+}
+```
+
+#### 5. Cancel a Booking
+
+```kotlin
+val cancelParams = DeleteRoomOperationParams.builder()
+ .itineraryId("12345678")
+ .roomId("room-123")
+ .customerIp("192.168.1.1")
+ .reason("customer_request")
+ .build()
+
+val cancelOperation = DeleteRoomOperation(cancelParams)
+
+try {
+ rapidClient.execute(cancelOperation)
+ println("Room cancelled successfully")
+} catch (e: ExpediaGroupApiErrorException) {
+ println("Cancellation failed: ${e.message}")
+}
+```
+
+### Advanced Features
+
+#### Pagination
+
+```kotlin
+// Use paginator for large result sets
+val params = GetRegionsOperationParams.builder()
+ .language("en-US")
+ .include(listOf(GetRegionsOperationParams.Include.STANDARD))
+ .build()
+
+val paginator = rapidClient.paginate(GetRegionsOperation(params))
+
+for (page in paginator) {
+ page.data.forEach { region ->
+ println("Region: ${region.name}")
+ }
+}
+```
+
+#### Async Operations
+
+```kotlin
+val futureResponse = rapidClient.executeAsync(searchOperation)
+
+futureResponse.thenAccept { response ->
+ response.data.forEach { property ->
+ println("Found property: ${property.propertyId}")
+ }
+}.exceptionally { throwable ->
+ println("Search failed: ${throwable.message}")
+ null
+}
+```
+
+#### Custom HTTP Configuration
+
+```kotlin
+val customClient = OkHttpClient.Builder()
+ .connectTimeout(10, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .addInterceptor { chain ->
+ val request = chain.request().newBuilder()
+ .addHeader("X-My-Custom-Header", "value")
+ .build()
+ chain.proceed(request)
+ }
+ .build()
+
+val rapidClient = RapidClient.builder()
+ .key("api-key")
+ .secret("api-secret")
+ .httpClient(customClient)
+ .build()
+```
+
+## ๐ก๏ธ Fraud Prevention SDK
+
+### Installation
+
+```xml
+
+ com.expediagroup
+ fraudpreventionv2-sdk
+ 2.0.0
+
+```
+
+### Basic Usage
+
+```kotlin
+val fraudClient = FraudPreventionV2Client.builder()
+ .key("your-api-key")
+ .secret("your-api-secret")
+ .endpoint("https://api.expediagroup.com/fraudpreventionv2")
+ .build()
+
+// Submit account screen event
+val accountScreen = AccountScreenRequest.builder()
+ .siteInfo(SiteInfo.builder()
+ .brandName("YourBrand")
+ .locale("en-US")
+ .build())
+ .deviceDetails(DeviceDetails.builder()
+ .ipAddress("192.168.1.1")
+ .userAgent("Mozilla/5.0...")
+ .build())
+ .accountDetails(AccountDetails.builder()
+ .userId("user123")
+ .username("john.doe@example.com")
+ .build())
+ .build()
+
+val params = AccountScreenNotifyOperationParams.builder()
+ .build()
+
+val operation = AccountScreenNotifyOperation(params, accountScreen)
+fraudClient.execute(operation)
+```
+
+## ๐ง Error Handling Patterns
+
+### Comprehensive Error Handling
+
+```kotlin
+fun bookHotel(bookingRequest: CreateItineraryRequest): BookingResult {
+ return try {
+ val response = rapidClient.execute(bookingOperation)
+ BookingResult.Success(response.data)
+
+ } catch (e: ExpediaGroupApiErrorException) {
+ when (val error = e.errorResponse) {
+ is RapidError -> {
+ val firstError = error.errors?.firstOrNull()
+ when (firstError?.type) {
+ "ROOM_UNAVAILABLE" -> BookingResult.RoomUnavailable
+ "PAYMENT_FAILED" -> BookingResult.PaymentFailed(firstError.message)
+ "INVALID_INPUT" -> BookingResult.InvalidInput(firstError.message)
+ else -> BookingResult.ApiError(e.message ?: "Unknown error")
+ }
+ }
+ else -> BookingResult.ApiError(e.message ?: "Unknown error")
+ }
+ } catch (e: ExpediaGroupServiceException) {
+ BookingResult.ServiceUnavailable
+ } catch (e: ExpediaGroupConfigurationException) {
+ BookingResult.ConfigurationError(e.message ?: "Configuration error")
+ } catch (e: Exception) {
+ BookingResult.UnknownError(e.message ?: "Unknown error")
+ }
+}
+
+sealed class BookingResult {
+ data class Success(val itinerary: ItineraryCreation) : BookingResult()
+ object RoomUnavailable : BookingResult()
+ data class PaymentFailed(val reason: String?) : BookingResult()
+ data class InvalidInput(val message: String?) : BookingResult()
+ data class ApiError(val message: String) : BookingResult()
+ object ServiceUnavailable : BookingResult()
+ data class ConfigurationError(val message: String) : BookingResult()
+ data class UnknownError(val message: String) : BookingResult()
+}
+```
+
+## ๐๏ธ Builder Pattern Examples
+
+All SDK objects use the builder pattern for clean, type-safe construction:
+
+```kotlin
+// Complex nested object construction
+val searchRequest = GetAvailabilityOperationParams.builder()
+ .checkin("2024-12-01")
+ .checkout("2024-12-05")
+ .occupancy(listOf("2", "1-9")) // 2 adults, 1 adult + 1 child age 9
+ .currency("USD")
+ .language("en-US")
+ .countryCode("US")
+ .propertyId(listOf("12345", "67890"))
+ .rateOption(listOf(
+ GetAvailabilityOperationParams.RateOption.MEMBER,
+ GetAvailabilityOperationParams.RateOption.NET_RATES
+ ))
+ .salesChannel("website")
+ .salesEnvironment("hotel_only")
+ .filter(listOf(
+ GetAvailabilityOperationParams.Filter.REFUNDABLE,
+ GetAvailabilityOperationParams.Filter.PROPERTY_COLLECTBOOLEAN
+ ))
+ .include(listOf(
+ GetAvailabilityOperationParams.Include.AMENITIES,
+ GetAvailabilityOperationParams.Include.SALE_SCENARIO
+ ))
+ .build()
+```
+
+## ๐ Response Processing
+
+### Extracting Data from Responses
+
+```kotlin
+val response = rapidClient.execute(searchOperation)
+
+// Response metadata
+println("Status: ${response.statusCode}")
+println("Transaction ID: ${response.transactionId}")
+response.headers.forEach { (key, values) ->
+ println("Header $key: ${values.joinToString(", ")}")
+}
+
+// Process the actual data
+response.data.forEach { property ->
+ // Property details
+ println("Property: ${property.propertyId}")
+ println("Name: ${property.name}")
+
+ // Availability and pricing
+ property.roomTypes?.forEach { roomType ->
+ println(" Room Type: ${roomType.name}")
+
+ roomType.ratePlans?.forEach { ratePlan ->
+ println(" Rate Plan: ${ratePlan.id}")
+ println(" Price: ${ratePlan.price?.total?.inclusive} ${ratePlan.price?.total?.currency}")
+
+ // Cancellation policy
+ ratePlan.cancellationPolicy?.let { policy ->
+ println(" Cancellation: ${policy.type}")
+ }
+ }
+ }
+
+ // Property amenities
+ property.amenities?.forEach { amenity ->
+ println(" Amenity: ${amenity.name}")
+ }
+}
+```
+
+## ๐ Configuration Management
+
+### Environment-Based Configuration
+
+```kotlin
+class RapidClientFactory {
+ companion object {
+ fun createClient(environment: Environment): RapidClient {
+ return when (environment) {
+ Environment.TEST -> RapidClient.builder()
+ .key(System.getenv("RAPID_TEST_KEY"))
+ .secret(System.getenv("RAPID_TEST_SECRET"))
+ .endpoint("https://test.ean.com/v3")
+ .requestTimeout(30000)
+ .build()
+
+ Environment.PRODUCTION -> RapidClient.builder()
+ .key(System.getenv("RAPID_PROD_KEY"))
+ .secret(System.getenv("RAPID_PROD_SECRET"))
+ .endpoint("https://api.ean.com/v3")
+ .requestTimeout(10000)
+ .build()
+ }
+ }
+ }
+
+ enum class Environment {
+ TEST, PRODUCTION
+ }
+}
+```
+
+### Spring Boot Integration
+
+```kotlin
+@Configuration
+class SdkConfiguration {
+
+ @Bean
+ @Primary
+ fun rapidClient(
+ @Value("\${rapid.api.key}") apiKey: String,
+ @Value("\${rapid.api.secret}") apiSecret: String,
+ @Value("\${rapid.api.endpoint}") endpoint: String
+ ): RapidClient {
+ return RapidClient.builder()
+ .key(apiKey)
+ .secret(apiSecret)
+ .endpoint(endpoint)
+ .requestTimeout(30000)
+ .connectionTimeout(10000)
+ .socketTimeout(60000)
+ .build()
+ }
+}
+
+@Service
+class HotelService(private val rapidClient: RapidClient) {
+
+ fun searchHotels(searchCriteria: SearchCriteria): List {
+ val params = GetAvailabilityOperationParams.builder()
+ .checkin(searchCriteria.checkin)
+ .checkout(searchCriteria.checkout)
+ .occupancy(searchCriteria.occupancy)
+ .customerIp(searchCriteria.customerIp)
+ .build()
+
+ val operation = GetAvailabilityOperation(params)
+ return rapidClient.execute(operation).data
+ }
+}
+```
+
+This usage guide provides practical examples and patterns for using the generated SDKs effectively in real applications.