{"openapi":"3.0.3","info":{"title":"Flight Search API","description":"\n          **Flight search service powered by PKFare API**\n\n          Comprehensive flight search and booking capabilities:\n          - 🔍 Real-time flight search (600+ airlines)\n          - 💰 Precise pricing and fare information\n          - 📋 Detailed flight information and amenities\n          - 🌍 Global flight coverage\n          - ⚡ Fast search responses with caching\n\n          All flight data is enriched with airline logos, city names, and detailed segment information.\n          ","version":"1.0.0","contact":{"name":"Etera Flight Vertical"}},"tags":[{"name":"flights","description":"✈️ Flight search, pricing, and detailed information"},{"name":"airlines","description":"✈️ Airline information and lookup"},{"name":"health","description":"💓 Service health and monitoring"}],"servers":[{"url":"http://localhost:3101","description":"Local development server"},{"url":"https://search.etera.ai","description":"Production server"}],"paths":{"/flights/details":{"post":{"parameters":[],"operationId":"postFlightsDetails","tags":["flights"],"summary":"📋 Get Flight Details (Simplified)","description":"\n        **Get flight details using inboundFlightHash (simplified for search-unified flow)**\n\n        This is a simplified endpoint that only requires the `inboundFlightHash` from search-unified results.\n        The `solutionKey` and `solutionId` are automatically extracted from the cache.\n\n        ### **Request Body**\n        - **inboundFlightHash** (required): Inbound flight hash from search-unified response\n        - **outboundFlightHash** (optional): Outbound flight hash for complete round-trip details\n        - **adults** (optional): Number of adult passengers (default: 1)\n        - **children** (optional): Number of child passengers\n        - **infants** (optional): Number of infant passengers\n        - **solutionKey** (optional): Solution key (auto-extracted from cache if not provided, used for validation)\n        - **solutionId** (optional): Solution ID (auto-extracted from cache if not provided)\n\n        ### **Example Request**\n        ```json\n        {\n          \"inboundFlightHash\": \"GF_6_LHR_BAH_1769608200000_1769642400000|GF_504_BAH_DXB_1769651400000_1769659800000\",\n          \"outboundFlightHash\": \"GF_513_DXB_BAH_1769355300000_1769356740000|GF_7_BAH_LHR_1769364900000_1769380500000\",\n          \"solutionKey\": \"9bafcd3de1809cb4d8cd066b77ce4b59\",\n          \"adults\": 1\n        }\n        ```\n        ","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"inboundFlightHash":{"description":"Inbound flight hash from search-unified (required)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified (optional, for complete round-trip)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"solutionKey":{"description":"Solution key (optional, auto-extracted from cache if not provided, used for validation)","type":"string"},"solutionId":{"description":"Solution ID (optional, auto-extracted from cache if not provided)","type":"string"}},"required":["inboundFlightHash"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"inboundFlightHash":{"description":"Inbound flight hash from search-unified (required)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified (optional, for complete round-trip)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"solutionKey":{"description":"Solution key (optional, auto-extracted from cache if not provided, used for validation)","type":"string"},"solutionId":{"description":"Solution ID (optional, auto-extracted from cache if not provided)","type":"string"}},"required":["inboundFlightHash"]}},"text/plain":{"schema":{"type":"object","properties":{"inboundFlightHash":{"description":"Inbound flight hash from search-unified (required)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified (optional, for complete round-trip)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"solutionKey":{"description":"Solution key (optional, auto-extracted from cache if not provided, used for validation)","type":"string"},"solutionId":{"description":"Solution ID (optional, auto-extracted from cache if not provided)","type":"string"}},"required":["inboundFlightHash"]}}}},"responses":{"200":{}}}},"/flights/{solutionKey}":{"get":{"parameters":[{"description":"Solution key (offer ID) from search results","schema":{"type":"string"},"in":"path","name":"solutionKey","required":true},{"description":"Number of adult passengers","schema":{"type":"number","minimum":1},"in":"query","name":"adults","required":false},{"description":"Number of child passengers","schema":{"type":"number","minimum":0},"in":"query","name":"children","required":false},{"description":"Number of infant passengers","schema":{"type":"number","minimum":0},"in":"query","name":"infants","required":false},{"description":"Solution ID from search-unified (required for search-unified flow)","schema":{"type":"string"},"in":"query","name":"solutionId","required":false},{"description":"Outbound flight hash from search-unified (optional, for validation)","schema":{"type":"string"},"in":"query","name":"outboundFlightHash","required":false},{"description":"Inbound flight hash from search-unified (required for search-unified flow)","schema":{"type":"string"},"in":"query","name":"inboundFlightHash","required":false},{"description":"Response format: 'default' (simplified) or 'booking' (raw FlightOffer for booking service)","schema":{"type":"string","enum":["default","booking"]},"in":"query","name":"format","required":false}],"operationId":"getFlightsBySolutionKey","tags":["flights"],"summary":"📋 Get Flight Details","description":"\n        **Get detailed flight information by solution key**\n\n        This endpoint returns comprehensive flight details for a specific flight offer.\n        The solution must be from a recent search (within 15 minutes).\n\n        ### **URL Parameters**\n        - **solutionKey** (optional): Solution key (offer ID) from search results. Required for regular search flow, optional for search-unified flow.\n\n        ### **Query Parameters**\n        - **adults** (optional): Number of adult passengers (for reference)\n        - **children** (optional): Number of child passengers (for reference)\n        - **infants** (optional): Number of infant passengers (for reference)\n        - **inboundFlightHash** (optional): Inbound flight hash from search-unified. If provided, solutionKey and solutionId are extracted automatically from cache.\n        - **outboundFlightHash** (optional): Outbound flight hash from search-unified (for complete round-trip details)\n        - **solutionId** (optional): Solution ID from search-unified (auto-extracted from cache if not provided)\n\n        ### **Usage Scenarios**\n\n        **Regular Search Flow:**\n        ```\n        GET /flights/a2ba983f73364c359420a12faf67179d?adults=1&children=2&infants=1\n        ```\n\n        **Search-Unified Flow (Simplified):**\n        After user selects an inbound flight from `/search-unified`, you can use just the flightHash:\n        ```\n        GET /flights?inboundFlightHash={inboundFlightHash}&outboundFlightHash={outboundFlightHash}&adults=2\n        ```\n        Or with solutionKey (for validation):\n        ```\n        GET /flights/{solutionKey}?inboundFlightHash={inboundFlightHash}&outboundFlightHash={outboundFlightHash}&adults=2\n        ```\n        Where:\n        - `inboundFlightHash` (required): The `flightHash` of the selected inbound flight. solutionKey and solutionId are auto-extracted from cache.\n        - `outboundFlightHash` (optional): The `flightHash` of the outbound flight (for complete round-trip details)\n        - `solutionKey` (optional): Can be omitted - will be extracted from cache automatically\n\n        ### **Response**\n        Returns detailed flight information including:\n        - Complete journey details with all segments (outbound + return for round-trip)\n        - Pricing breakdown\n        - Booking information (refundable, changeable, fees)\n        - Baggage allowance\n        - Amenities (meals, wifi, seat selection)\n        - Availability information\n\n        ### **Time Window**\n        The solution must be from a search within the last **15 minutes**.\n        If expired, you'll need to search again.\n\n        ### **Example Requests**\n\n        **Regular Search:**\n        ```\n        GET /flights/a2ba983f73364c359420a12faf67179d?adults=1&children=2&infants=1\n        ```\n\n        **Search-Unified:**\n        ```\n        GET /flights/abc123?solutionId=xyz789&inboundFlightHash=EK_8_LHR_DXB_1737792000000_1737810300000&outboundFlightHash=EK_29_DXB_LHR_1737705600000_1737723000000&adults=2\n        ```\n        ","responses":{"200":{}}}},"/flights/pricing":{"post":{"parameters":[],"operationId":"postFlightsPricing","tags":["flights"],"summary":"💰 Get Precise Pricing","description":"\n        **Get detailed pricing for a selected flight solution**\n\n        This endpoint retrieves precise pricing information for a flight solution selected from search results.\n        Must be called within 15 minutes of the original search.\n\n        ### **Request Parameters**\n        - **solutionKey** (required): Solution key from search results (short hash)\n        - **solutionId** (required): Solution ID from search results (long encoded string from pricingData)\n        - **journeys** (required): Journey details with segments (from pricingData.journeys)\n        - **adults** (required): Number of adult passengers\n        - **children** (optional): Number of child passengers\n        - **infants** (optional): Number of infant passengers\n\n        ### **Usage**\n        Use the `pricingData` object from `/flights/find-return-options` response directly:\n        ```json\n        {\n          \"solutionKey\": \"{pricingData.solutionKey}\",\n          \"solutionId\": \"{pricingData.solutionId}\",\n          \"journeys\": {pricingData.journeys},\n          \"adults\": 1\n        }\n        ```\n\n        ### **Response**\n        Returns detailed pricing information including:\n        - Fare breakdown by passenger type\n        - Taxes and fees\n        - Solution details needed for booking\n\n        ### **Time Window**\n        This endpoint must be called within **15 minutes** of the original search.\n        ","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results (short hash)","type":"string"},"solutionId":{"description":"Solution ID from search results (long encoded string) - required by PKFare API","type":"string"},"journeys":{"type":"object","patternProperties":{"^(.*)$":{"type":"array","items":{"type":"object","properties":{"airline":{"type":"string"},"flightNum":{"type":"string"},"arrival":{"type":"string"},"arrivalDate":{"type":"string"},"arrivalTime":{"type":"string"},"departure":{"type":"string"},"departureDate":{"type":"string"},"departureTime":{"type":"string"},"bookingCode":{"type":"string"}},"required":["airline","flightNum","arrival","arrivalDate","arrivalTime","departure","departureDate","departureTime","bookingCode"]}}}},"adults":{"minimum":1,"type":"number"},"children":{"minimum":0,"type":"number"},"infants":{"minimum":0,"type":"number"}},"required":["solutionKey","solutionId","journeys","adults"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results (short hash)","type":"string"},"solutionId":{"description":"Solution ID from search results (long encoded string) - required by PKFare API","type":"string"},"journeys":{"type":"object","patternProperties":{"^(.*)$":{"type":"array","items":{"type":"object","properties":{"airline":{"type":"string"},"flightNum":{"type":"string"},"arrival":{"type":"string"},"arrivalDate":{"type":"string"},"arrivalTime":{"type":"string"},"departure":{"type":"string"},"departureDate":{"type":"string"},"departureTime":{"type":"string"},"bookingCode":{"type":"string"}},"required":["airline","flightNum","arrival","arrivalDate","arrivalTime","departure","departureDate","departureTime","bookingCode"]}}}},"adults":{"minimum":1,"type":"number"},"children":{"minimum":0,"type":"number"},"infants":{"minimum":0,"type":"number"}},"required":["solutionKey","solutionId","journeys","adults"]}},"text/plain":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results (short hash)","type":"string"},"solutionId":{"description":"Solution ID from search results (long encoded string) - required by PKFare API","type":"string"},"journeys":{"type":"object","patternProperties":{"^(.*)$":{"type":"array","items":{"type":"object","properties":{"airline":{"type":"string"},"flightNum":{"type":"string"},"arrival":{"type":"string"},"arrivalDate":{"type":"string"},"arrivalTime":{"type":"string"},"departure":{"type":"string"},"departureDate":{"type":"string"},"departureTime":{"type":"string"},"bookingCode":{"type":"string"}},"required":["airline","flightNum","arrival","arrivalDate","arrivalTime","departure","departureDate","departureTime","bookingCode"]}}}},"adults":{"minimum":1,"type":"number"},"children":{"minimum":0,"type":"number"},"infants":{"minimum":0,"type":"number"}},"required":["solutionKey","solutionId","journeys","adults"]}}}},"responses":{"200":{}}}},"/flights/fare-options":{"post":{"parameters":[],"operationId":"postFlightsFare-options","tags":["flights"],"summary":"💰 Get Fare Options","description":"\n        **Get fare options for a specific flight**\n\n        This endpoint has two modes:\n\n        ### **Mode 1: Get fare options from cache (same cabin class)**\n        When `cabinClass` is NOT provided, returns fare options from cache (same cabin class as initial search).\n        - Works with flights from recent `/flights/search-unified` calls\n        - Returns all fare categories (Economy Basic, Economy Value, etc.) for the same cabin class\n\n        ### **Mode 2: Search for fare options in different cabin class**\n        When `cabinClass` IS provided, searches PKFare for the same flight but in the requested cabin class.\n        - **Use case**: User is viewing Economy fare options and wants to see Business class options\n        - Makes a new search to PKFare with the same flight details but different cabin class\n        - Returns all fare options for the requested cabin class\n\n        ### **Request Body**\n        - **flightHash** (required): Flight hash from search-unified response\n          - For one-way: Use outbound flight hash\n          - For round-trip: Use inbound flight hash\n        - **outboundFlightHash** (optional): Outbound flight hash (for round-trip context)\n        - **cabinClass** (optional): Requested cabin class (e.g., \"business\", \"first\", \"premium_economy\")\n          - If provided: Searches PKFare for fare options in this cabin class\n          - If not provided: Returns fare options from cache (same cabin class)\n        - **adults** (required when cabinClass is provided): Number of adult passengers\n        - **children** (optional): Number of child passengers\n        - **infants** (optional): Number of infant passengers\n\n        ### **Response**\n        Returns all fare options for the flight, including:\n        - **fareOptions**: Array of all available fare options with:\n          - solutionKey, solutionId\n          - fareCategory (e.g., \"ECONOMY LIGHT\", \"BUSINESS FLEX\")\n          - pricing (total, base, tax, fees)\n          - booking rules (refundable, changeable, cancellation/change fees)\n          - baggage allowances\n          - amenities (meals, wifi, seat selection)\n          - Raw PKFare data (miniRulesMap, baggageMap, otherFareRules)\n        - Flight details (legs, duration, airport change info)\n        - Backward compatibility fields (cheapest fare option)\n\n        ### **Example Request 1: Get from cache (same cabin class)**\n        ```json\n        {\n          \"flightHash\": \"EK_708_DXB_LHR_1737705600000_1737723000000\"\n        }\n        ```\n\n        ### **Example Request 2: Search for Business class**\n        ```json\n        {\n          \"flightHash\": \"EK_708_DXB_LHR_1737705600000_1737723000000\",\n          \"outboundFlightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n          \"cabinClass\": \"business\",\n          \"adults\": 1\n        }\n        ```\n\n        ### **Example Response**\n        ```json\n        {\n          \"success\": true,\n          \"data\": {\n            \"flightHash\": \"EK_708_DXB_LHR_1737705600000_1737723000000\",\n            \"totalDuration\": 760,\n            \"legs\": [...],\n            \"airportChange\": false,\n            \"fareOptions\": [\n              {\n                \"solutionKey\": \"...\",\n                \"solutionId\": \"...\",\n                \"fareCategory\": \"BUSINESS FLEX\",\n                \"pricing\": {\n                  \"total\": 4500,\n                  \"currency\": \"AED\",\n                  \"base\": 4000,\n                  \"tax\": 500\n                },\n                \"booking\": {\n                  \"refundable\": true,\n                  \"changeable\": true\n                },\n                \"baggage\": {\n                  \"carryOn\": { \"pieces\": 2, \"weight\": 7 },\n                  \"checked\": { \"pieces\": 2, \"weight\": 32 }\n                },\n                \"amenities\": {\n                  \"meals\": { \"available\": true },\n                  \"seatSelection\": { \"available\": true }\n                }\n              }\n            ],\n            \"solutionKey\": \"...\",\n            \"pricing\": { \"total\": 4500, ... }\n          }\n        }\n        ```\n\n        ### **Error Responses**\n        - **B037**: Flight data not found in cache - search for flights again\n        - **B024**: Flight data has expired - search for flights again\n        - **B038**: No fare options found for requested cabin class\n        - **P002**: Missing required parameter\n        ","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"flightHash":{"description":"Flight hash (outbound for one-way, inbound for round-trip)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash (optional, for round-trip context)","type":"string"},"cabinClass":{"description":"Requested cabin class (e.g., 'business', 'first', 'premium_economy'). If provided, searches PKFare for fare options in this cabin class.","type":"string"},"adults":{"description":"Number of adult passengers (required when cabinClass is provided)","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["flightHash"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"flightHash":{"description":"Flight hash (outbound for one-way, inbound for round-trip)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash (optional, for round-trip context)","type":"string"},"cabinClass":{"description":"Requested cabin class (e.g., 'business', 'first', 'premium_economy'). If provided, searches PKFare for fare options in this cabin class.","type":"string"},"adults":{"description":"Number of adult passengers (required when cabinClass is provided)","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["flightHash"]}},"text/plain":{"schema":{"type":"object","properties":{"flightHash":{"description":"Flight hash (outbound for one-way, inbound for round-trip)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash (optional, for round-trip context)","type":"string"},"cabinClass":{"description":"Requested cabin class (e.g., 'business', 'first', 'premium_economy'). If provided, searches PKFare for fare options in this cabin class.","type":"string"},"adults":{"description":"Number of adult passengers (required when cabinClass is provided)","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["flightHash"]}}}},"responses":{"200":{}}}},"/flights/pricing-simple":{"post":{"parameters":[],"operationId":"postFlightsPricing-simple","tags":["flights"],"summary":"💰 Get Precise Pricing (Simplified)","description":"\n        **Get precise pricing using flightHash - Simplified API**\n\n        This is a simplified version of the precise pricing endpoint that only requires:\n        - `solutionKey` - From search results\n        - `solutionId` - From search results (optional, retrieved from cache if not provided)\n        - `outboundFlightHash` - From search-unified results\n        - `inboundFlightHash` - From search-unified results (optional, for round-trip)\n\n        All journey details are automatically retrieved from cached flight data, so you don't need to pass the full journey structure.\n\n        ### **Request Example**\n\n        **One-way:**\n        ```json\n        {\n          \"solutionKey\": \"abc123\",\n          \"outboundFlightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n          \"adults\": 1\n        }\n        ```\n\n        **Round-trip:**\n        ```json\n        {\n          \"solutionKey\": \"abc123\",\n          \"outboundFlightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n          \"inboundFlightHash\": \"EK_8_LHR_DXB_1737792000000_1737810000000\",\n          \"adults\": 2,\n          \"children\": 1\n        }\n        ```\n\n        ### **Response**\n        Returns detailed pricing information including:\n        - Fare breakdown by passenger type\n        - Taxes and fees\n        - Solution details needed for booking\n        - **rawResponse**: Complete raw PKFare API response for debugging and advanced use cases\n\n        ### **Benefits**\n        - ✅ Much simpler API - no need to pass full journey details\n        - ✅ Automatically retrieves journey data from cache\n        - ✅ Less error-prone - no manual journey construction\n        - ✅ Same functionality as `/flights/pricing` endpoint\n        - ✅ Includes raw PKFare response for debugging\n\n        ### **Time Window**\n        Must be called within **15 minutes** of the original search.\n        ","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results","type":"string"},"solutionId":{"description":"Solution ID from search results (optional - will be retrieved from cache if not provided)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified results","type":"string"},"inboundFlightHash":{"description":"Inbound flight hash from search-unified results (for round-trip)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["solutionKey","outboundFlightHash","adults"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results","type":"string"},"solutionId":{"description":"Solution ID from search results (optional - will be retrieved from cache if not provided)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified results","type":"string"},"inboundFlightHash":{"description":"Inbound flight hash from search-unified results (for round-trip)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["solutionKey","outboundFlightHash","adults"]}},"text/plain":{"schema":{"type":"object","properties":{"solutionKey":{"description":"Solution key from search results","type":"string"},"solutionId":{"description":"Solution ID from search results (optional - will be retrieved from cache if not provided)","type":"string"},"outboundFlightHash":{"description":"Outbound flight hash from search-unified results","type":"string"},"inboundFlightHash":{"description":"Inbound flight hash from search-unified results (for round-trip)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"}},"required":["solutionKey","outboundFlightHash","adults"]}}}},"responses":{"200":{}}}},"/flights/search":{"post":{"parameters":[],"operationId":"postFlightsSearch","tags":["flights"],"summary":"🔍 Search Flights","description":"\n        **Unified search for round-trip flights grouped by unique outbound journey**\n\n        This endpoint is designed for a two-step flight selection flow:\n        1. User sees all unique outbound flights\n        2. User selects an outbound and sees all compatible return flights\n\n        ### **Key Features**\n        - Groups all solutions by unique outbound flight\n        - Each outbound contains all compatible return options\n        - Flight hash identifies each unique flight combination\n        - Hash format: `{airline}_{flightNum}_{departure}_{arrival}_{departureTimestamp}_{arrivalTimestamp}`\n        - Multi-leg flights use `|` separator between legs\n        - **totalDuration**: Total travel time including layovers (minutes)\n        - **stopoverDuration**: Time between connecting legs (minutes)\n        - **airportChange**: True if connecting flights use different airports\n        - **expiresAt**: When this search result expires (ISO timestamp)\n\n        ### **Request Body**\n        - **origin** (required): Origin airport IATA code (e.g., \"DXB\")\n        - **destination** (required): Destination airport IATA code (e.g., \"LHR\")\n        - **departureDate** (required): Departure date (YYYY-MM-DD)\n        - **returnDate** (required): Return date (YYYY-MM-DD)\n        - **adults** (required): Number of adult passengers (min: 1)\n        - **children** (optional): Number of child passengers\n        - **infants** (optional): Number of infant passengers\n        - **cabinClass** (optional): Preferred cabin class\n        - **nonstop** (optional): Only show nonstop flights\n        - **airline** (optional): Filter by specific airline (legacy - use airlines array instead)\n        - **airlines** (optional): Array of airline codes to include (e.g., [\"EK\", \"QR\", \"EY\"])\n        - **excludeAirlines** (optional): Array of airline codes to exclude (e.g., [\"FZ\", \"G9\"])\n        - **tag** (optional): Fare category tag filter (e.g., \"ECONOMY LIGHT\", \"ECONOMY STANDARD\", \"ECONOMY FLEX\", \"BUSINESS FLEX\"). Filters results to specific branded fare types within the selected cabin class.\n        - **sortBy** (optional): Sort results by \"price\", \"duration\", \"departure_time\", or \"arrival_time\" (default: \"price\")\n        - **sortOrder** (optional): Sort order \"asc\" or \"desc\" (default: \"asc\")\n        - **priceRange** (optional): Filter by price range\n          - **min** (optional): Minimum price\n          - **max** (optional): Maximum price\n          - **currency** (optional): Currency code (e.g., \"USD\", \"AED\")\n        - **departureTimeRange** (optional): Filter by departure time window\n          - **earliest** (optional): Earliest departure time (HH:MM format, e.g., \"06:00\")\n          - **latest** (optional): Latest departure time (HH:MM format, e.g., \"12:00\")\n        - **arrivalTimeRange** (optional): Filter by arrival time window\n          - **earliest** (optional): Earliest arrival time (HH:MM format, e.g., \"14:00\")\n          - **latest** (optional): Latest arrival time (HH:MM format, e.g., \"22:00\")\n        - **durationRange** (optional): Filter by flight duration\n          - **min** (optional): Minimum duration in minutes\n          - **max** (optional): Maximum duration in minutes\n        - **currency** (optional): Currency code (default: \"AED\")\n\n        ### **Response Structure**\n        ```json\n        {\n          \"success\": true,\n          \"data\": {\n            \"flights\": [\n              {\n                \"outbound\": {\n                  \"flightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n                  \"totalDuration\": 470,\n                  \"airportChange\": false,\n                  \"tags\": [\"CHEAPEST\", \"NONSTOP\"],\n                  \"legs\": [\n                    {\n                      \"airline\": \"EK\",\n                      \"flightNumber\": \"29\",\n                      \"departure\": { \"airport\": \"DXB\", \"terminal\": \"3\", \"dateTime\": \"2026-01-24T09:40:00\", \"time\": \"09:40\" },\n                      \"arrival\": { \"airport\": \"LHR\", \"terminal\": \"3\", \"dateTime\": \"2026-01-24T13:50:00\", \"time\": \"13:50\" },\n                      \"duration\": 470,\n                      \"aircraft\": \"388\",\n                      \"cabinClass\": \"ECONOMY\",\n                      \"bookingCode\": \"L\"\n                    }\n                  ]\n                },\n                \"inbounds\": [\n                  {\n                    \"flightHash\": \"EK_8_LHR_DXB_...\",\n                    \"totalDuration\": 435,\n                    \"airportChange\": false,\n                    \"solutionKey\": \"...\",\n                    \"solutionId\": \"...\",\n                    \"legs\": [\n                      {\n                        \"duration\": 435,\n                        \"stopoverDuration\": null\n                      }\n                    ],\n                    \"pricing\": {\n                      \"total\": 1433.63,\n                      \"currency\": \"USD\",\n                      \"base\": 860.45,\n                      \"tax\": 573.18\n                    },\n                    \"booking\": { \"refundable\": false, \"changeable\": true },\n                    \"baggage\": { \"carryOn\": { \"weight\": 12 } },\n                    \"miniRulesMap\": {...},\n                    \"baggageInfos\": {...}\n                  }\n                ],\n                \"priceRange\": { \"min\": 1200, \"max\": 2500, \"currency\": \"USD\" },\n                \"inboundCount\": 15\n              }\n            ],\n            \"expiresAt\": \"2026-01-24T12:30:00.000Z\"\n          },\n          \"meta\": {\n            \"totalOutbounds\": 12,\n            \"totalSolutions\": 156,\n            \"search\": {...},\n            \"searchDuration\": 1500,\n            \"provider\": \"pkfare\",\n            \"cheapest\": {\n              \"outboundFlightHash\": \"...\",\n              \"inboundFlightHash\": \"...\",\n              \"price\": 1200,\n              \"currency\": \"USD\"\n            }\n          }\n        }\n        ```\n\n        ### **Booking Flow**\n        1. User selects an outbound flight (by flightHash)\n        2. User selects an inbound from that outbound's `inbounds` array\n        3. Use `solutionKey` and `solutionId` for precise pricing: POST /flights/pricing with solutionKey, solutionId, and journeys extracted from the flight offer\n\n        ### **Example Request**\n        ```json\n        {\n          \"origin\": \"DXB\",\n          \"destination\": \"LHR\",\n          \"departureDate\": \"2026-01-24\",\n          \"returnDate\": \"2026-01-29\",\n          \"adults\": 1,\n          \"currency\": \"USD\"\n        }\n        ```\n        ","examples":[{"summary":"Round-trip unified search","value":{"origin":"DXB","destination":"LHR","departureDate":"2026-01-24","returnDate":"2026-01-29","adults":1,"currency":"USD"}},{"summary":"Family round-trip unified search","value":{"origin":"DXB","destination":"LHR","departureDate":"2026-01-24","returnDate":"2026-01-29","adults":2,"children":1,"infants":1,"cabinClass":"economy","currency":"AED"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code (e.g., 'DXB')","type":"string"},"destination":{"description":"Destination airport IATA code (e.g., 'LHR')","type":"string"},"departureDate":{"description":"Departure date in YYYY-MM-DD format","type":"string"},"returnDate":{"description":"Return date in YYYY-MM-DD format (optional for one-way flights)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"},"cabinClass":{"description":"Preferred cabin class","anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"nonstop":{"description":"Only show nonstop flights","type":"boolean"},"airline":{"description":"Filter by specific airline code","type":"string"},"maxStops":{"description":"Maximum number of stops","minimum":0,"type":"number"},"maxResults":{"description":"Maximum number of results to return","minimum":1,"maximum":100,"type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED', 'EUR'). Defaults to 'AED'","type":"string"},"tag":{"description":"Fare category tag filter (e.g., 'ECONOMY LIGHT', 'ECONOMY STANDARD', 'ECONOMY FLEX', 'BUSINESS FLEX'). Filters results to specific branded fare types within the selected cabin class.","type":"string"},"airlines":{"description":"Array of airline codes to include (e.g., ['EK', 'QR', 'EY']). If provided, only flights from these airlines will be returned.","type":"array","items":{"type":"string"}},"excludeAirlines":{"description":"Array of airline codes to exclude (e.g., ['FZ', 'G9']). Flights from these airlines will be filtered out.","type":"array","items":{"type":"string"}},"sortBy":{"description":"Sort results by price, duration, departure_time, or arrival_time","anyOf":[{"const":"price","type":"string"},{"const":"duration","type":"string"},{"const":"departure_time","type":"string"},{"const":"arrival_time","type":"string"}]},"sortOrder":{"description":"Sort order (asc or desc)","anyOf":[{"const":"asc","type":"string"},{"const":"desc","type":"string"}]},"priceRange":{"type":"object","properties":{"min":{"description":"Minimum price","type":"number"},"max":{"description":"Maximum price","type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}}},"departureTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest departure time (HH:MM format)","type":"string"},"latest":{"description":"Latest departure time (HH:MM format)","type":"string"}}},"arrivalTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest arrival time (HH:MM format)","type":"string"},"latest":{"description":"Latest arrival time (HH:MM format)","type":"string"}}},"durationRange":{"type":"object","properties":{"min":{"description":"Minimum duration in minutes","type":"number"},"max":{"description":"Maximum duration in minutes","type":"number"}}}},"required":["origin","destination","departureDate","adults"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code (e.g., 'DXB')","type":"string"},"destination":{"description":"Destination airport IATA code (e.g., 'LHR')","type":"string"},"departureDate":{"description":"Departure date in YYYY-MM-DD format","type":"string"},"returnDate":{"description":"Return date in YYYY-MM-DD format (optional for one-way flights)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"},"cabinClass":{"description":"Preferred cabin class","anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"nonstop":{"description":"Only show nonstop flights","type":"boolean"},"airline":{"description":"Filter by specific airline code","type":"string"},"maxStops":{"description":"Maximum number of stops","minimum":0,"type":"number"},"maxResults":{"description":"Maximum number of results to return","minimum":1,"maximum":100,"type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED', 'EUR'). Defaults to 'AED'","type":"string"},"tag":{"description":"Fare category tag filter (e.g., 'ECONOMY LIGHT', 'ECONOMY STANDARD', 'ECONOMY FLEX', 'BUSINESS FLEX'). Filters results to specific branded fare types within the selected cabin class.","type":"string"},"airlines":{"description":"Array of airline codes to include (e.g., ['EK', 'QR', 'EY']). If provided, only flights from these airlines will be returned.","type":"array","items":{"type":"string"}},"excludeAirlines":{"description":"Array of airline codes to exclude (e.g., ['FZ', 'G9']). Flights from these airlines will be filtered out.","type":"array","items":{"type":"string"}},"sortBy":{"description":"Sort results by price, duration, departure_time, or arrival_time","anyOf":[{"const":"price","type":"string"},{"const":"duration","type":"string"},{"const":"departure_time","type":"string"},{"const":"arrival_time","type":"string"}]},"sortOrder":{"description":"Sort order (asc or desc)","anyOf":[{"const":"asc","type":"string"},{"const":"desc","type":"string"}]},"priceRange":{"type":"object","properties":{"min":{"description":"Minimum price","type":"number"},"max":{"description":"Maximum price","type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}}},"departureTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest departure time (HH:MM format)","type":"string"},"latest":{"description":"Latest departure time (HH:MM format)","type":"string"}}},"arrivalTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest arrival time (HH:MM format)","type":"string"},"latest":{"description":"Latest arrival time (HH:MM format)","type":"string"}}},"durationRange":{"type":"object","properties":{"min":{"description":"Minimum duration in minutes","type":"number"},"max":{"description":"Maximum duration in minutes","type":"number"}}}},"required":["origin","destination","departureDate","adults"]}},"text/plain":{"schema":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code (e.g., 'DXB')","type":"string"},"destination":{"description":"Destination airport IATA code (e.g., 'LHR')","type":"string"},"departureDate":{"description":"Departure date in YYYY-MM-DD format","type":"string"},"returnDate":{"description":"Return date in YYYY-MM-DD format (optional for one-way flights)","type":"string"},"adults":{"description":"Number of adult passengers","minimum":1,"type":"number"},"children":{"description":"Number of child passengers","minimum":0,"type":"number"},"infants":{"description":"Number of infant passengers","minimum":0,"type":"number"},"cabinClass":{"description":"Preferred cabin class","anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"nonstop":{"description":"Only show nonstop flights","type":"boolean"},"airline":{"description":"Filter by specific airline code","type":"string"},"maxStops":{"description":"Maximum number of stops","minimum":0,"type":"number"},"maxResults":{"description":"Maximum number of results to return","minimum":1,"maximum":100,"type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED', 'EUR'). Defaults to 'AED'","type":"string"},"tag":{"description":"Fare category tag filter (e.g., 'ECONOMY LIGHT', 'ECONOMY STANDARD', 'ECONOMY FLEX', 'BUSINESS FLEX'). Filters results to specific branded fare types within the selected cabin class.","type":"string"},"airlines":{"description":"Array of airline codes to include (e.g., ['EK', 'QR', 'EY']). If provided, only flights from these airlines will be returned.","type":"array","items":{"type":"string"}},"excludeAirlines":{"description":"Array of airline codes to exclude (e.g., ['FZ', 'G9']). Flights from these airlines will be filtered out.","type":"array","items":{"type":"string"}},"sortBy":{"description":"Sort results by price, duration, departure_time, or arrival_time","anyOf":[{"const":"price","type":"string"},{"const":"duration","type":"string"},{"const":"departure_time","type":"string"},{"const":"arrival_time","type":"string"}]},"sortOrder":{"description":"Sort order (asc or desc)","anyOf":[{"const":"asc","type":"string"},{"const":"desc","type":"string"}]},"priceRange":{"type":"object","properties":{"min":{"description":"Minimum price","type":"number"},"max":{"description":"Maximum price","type":"number"},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}}},"departureTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest departure time (HH:MM format)","type":"string"},"latest":{"description":"Latest departure time (HH:MM format)","type":"string"}}},"arrivalTimeRange":{"type":"object","properties":{"earliest":{"description":"Earliest arrival time (HH:MM format)","type":"string"},"latest":{"description":"Latest arrival time (HH:MM format)","type":"string"}}},"durationRange":{"type":"object","properties":{"min":{"description":"Minimum duration in minutes","type":"number"},"max":{"description":"Maximum duration in minutes","type":"number"}}}},"required":["origin","destination","departureDate","adults"]}}}},"responses":{"200":{}}}},"/flights/decode/{flightHash}":{"get":{"parameters":[{"description":"Flight hash from unified search (format: {airline}_{flightNum}_{departure}_{arrival}_{departureTimestamp}_{arrivalTimestamp}, multiple legs joined by |)","schema":{"type":"string"},"in":"path","name":"flightHash","required":true}],"operationId":"getFlightsDecodeByFlightHash","tags":["flights"],"summary":"🔍 Decode Flight Hash","description":"\n        **Decode a flight hash to extract full flight information**\n\n        This endpoint decodes a flight hash (from unified search results) and returns detailed flight information.\n        The hash uniquely identifies a flight by its airline, flight number, airports, and timestamps.\n\n        ### **Hash Format**\n        - Single leg: `{airline}_{flightNum}_{departure}_{arrival}_{departureTimestamp}_{arrivalTimestamp}`\n        - Multiple legs: Legs joined by `|` separator\n        - Example: `EK_29_DXB_LHR_1737705600000_1737723000000`\n        - Example (multi-leg): `RJ_611_DXB_AMM_1769233500000_1769242800000|RJ_111_AMM_LHR_1769250000000_1769262000000`\n\n        ### **URL Parameters**\n        - **flightHash** (required): Flight hash from unified search results\n\n        ### **Response Structure**\n        Matches the main flight object structure with city names and airline details always included.\n        When data comes from cache (from search-unified), includes complete pricing, booking, and baggage information.\n        \n        **Response from Cache (when available from search-unified):**\n        ```json\n        {\n          \"success\": true,\n          \"data\": {\n            \"flightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n            \"totalDuration\": 470,\n            \"airportChange\": false,\n            \"legs\": [...],\n            \"origin\": {\n              \"airport\": \"DXB\",\n              \"city\": \"Dubai\"\n            },\n            \"destination\": {\n              \"airport\": \"LHR\",\n              \"city\": \"London\"\n            },\n            \"solutionKey\": \"abc123\",\n            \"solutionId\": \"xyz789\",\n            \"pricing\": {\n              \"total\": 1500,\n              \"currency\": \"AED\",\n              \"base\": 1200,\n              \"tax\": 300\n            },\n            \"booking\": {\n              \"refundable\": true,\n              \"changeable\": false\n            },\n            \"baggage\": {\n              \"carryOn\": { \"pieces\": 1 },\n              \"checked\": { \"pieces\": 1, \"weight\": 30 }\n            }\n          },\n          \"meta\": {\n            \"cached\": true,\n            \"cachedAt\": \"2026-01-24T10:00:00.000Z\",\n            \"expiresAt\": \"2026-01-24T10:30:00.000Z\",\n            \"timeRemaining\": 1800000,\n            \"timeRemainingFormatted\": \"15 minutes\",\n            \"source\": \"cache\",\n            \"hasCompleteData\": true\n          }\n        }\n        ```\n\n        **Response from Hash Decoding (when not in cache):**\n        ```json\n        {\n          \"success\": true,\n          \"data\": {\n            \"flightHash\": \"EK_29_DXB_LHR_1737705600000_1737723000000\",\n            \"totalDuration\": 470,\n            \"airportChange\": false,\n            \"legs\": [...],\n            \"origin\": {\n              \"airport\": \"DXB\",\n              \"city\": \"Dubai\"\n            },\n            \"destination\": {\n              \"airport\": \"LHR\",\n              \"city\": \"London\"\n            }\n          },\n          \"meta\": {\n            \"cached\": false,\n            \"decodedAt\": \"2026-01-24T10:15:00.000Z\",\n            \"source\": \"hash\",\n            \"hasCompleteData\": false\n          }\n        }\n        ```\n\n        ### **Metadata Fields**\n        - **cached** (boolean): Whether data came from cache or was decoded from hash\n        - **cachedAt** (string, optional): ISO timestamp when data was cached (only when cached=true)\n        - **expiresAt** (string, optional): ISO timestamp when cache expires (only when cached=true)\n        - **timeRemaining** (number, optional): Time remaining in milliseconds until cache expires (only when cached=true)\n        - **timeRemainingFormatted** (string, optional): Human-readable time remaining (e.g., \"15 minutes\", only when cached=true)\n        - **decodedAt** (string, optional): ISO timestamp when data was decoded from hash (only when cached=false)\n        - **source** (string): Source of the data - \"cache\" or \"hash\"\n        - **hasCompleteData** (boolean): Whether pricing/booking/baggage data is available (true when from cache with search-unified data)\n\n        ### **Use Cases**\n        - Decode flight hashes from unified search to display flight details\n        - Reconstruct flight information for booking flow\n        - Validate flight hash format\n        - Get human-readable flight information from hash\n\n        ### **Example Requests**\n        ```\n        GET /flights/decode/EK_29_DXB_LHR_1737705600000_1737723000000\n        GET /flights/decode/RJ_611_DXB_AMM_1769233500000_1769242800000|RJ_111_AMM_LHR_1769250000000_1769262000000\n        ```\n\n        **Note:** City names and airline details are always included in the response, matching the main flight object structure.\n        ","examples":[{"summary":"Decode single-leg flight","value":{"flightHash":"EK_29_DXB_LHR_1737705600000_1737723000000"}},{"summary":"Decode multi-leg flight","value":{"flightHash":"RJ_611_DXB_AMM_1769233500000_1769242800000|RJ_111_AMM_LHR_1769250000000_1769262000000"}}],"responses":{"200":{}}}},"/flights/find-return-options":{"post":{"parameters":[],"operationId":"postFlightsFind-return-options","tags":["flights"],"summary":"🔍 Find Return Flight Options","description":"\n        **Find return flight options that match a selected outbound flight**\n\n        This endpoint searches for return flights that can be combined with a specific outbound flight.\n        It matches flights by comparing flight numbers (airline + flightNumber) from segments.\n\n        ### **Use Case**\n        User selects an outbound flight (e.g., \"EK29\" from DXB to LHR) and wants to see all return flight\n        options that can be combined with that specific outbound flight.\n\n        ### **Request Body**\n        - **outboundSegments** (required): Array of selected outbound flight segments\n          - Each segment must have:\n            - **airline**: Airline IATA code (e.g., \"EK\")\n            - **flightNumber**: Flight number (e.g., \"29\")\n            - **departure** (optional): Departure airport and date/time\n            - **arrival** (optional): Arrival airport and date/time\n        - **searchParams** (required): Search parameters for the round-trip search\n          - **origin**: Origin airport IATA code\n          - **destination**: Destination airport IATA code\n          - **departureDate**: Departure date (YYYY-MM-DD)\n          - **returnDate**: Return date (YYYY-MM-DD) - **required**\n          - **adults**: Number of adult passengers (minimum: 1)\n          - **children** (optional): Number of child passengers\n          - **infants** (optional): Number of infant passengers\n          - **cabinClass** (optional): Preferred cabin class\n          - **currency** (optional): Currency code\n        - **searchKey** (optional): Search key from previous search (for caching)\n\n        ### **Response**\n        Returns an array of return flight options that match the selected outbound flight:\n        - **returnOptions**: Array of matching return flights\n          - **returnJourney**: Full journey details for the return flight\n          - **solutionKey**: Solution key for booking\n          - **returnJourneyId**: Return journey ID from PKFare\n          - **outboundJourneyId**: Outbound journey ID (for reference)\n          - **pricing**: Pricing information\n        - **total**: Total number of matching return options\n        - **matchedOutbound**: Echo of the matched outbound segments\n        - **metadata**: Search metadata (provider, duration)\n\n        ### **Matching Logic**\n        The endpoint matches solutions where:\n        1. The outbound journey (journey_0) has segments with matching flight numbers\n        2. All segments must match exactly (airline + flightNumber)\n        3. The solution has a return journey (journey_1)\n\n        ### **Example Request**\n        ```json\n        {\n          \"outboundSegments\": [\n            {\n              \"airline\": \"EK\",\n              \"flightNumber\": \"29\",\n              \"departure\": {\n                \"airport\": \"DXB\"\n              },\n              \"arrival\": {\n                \"airport\": \"LHR\"\n              }\n            }\n          ],\n          \"searchParams\": {\n            \"origin\": \"DXB\",\n            \"destination\": \"LHR\",\n            \"departureDate\": \"2026-01-02\",\n            \"returnDate\": \"2026-01-10\",\n            \"adults\": 1,\n            \"currency\": \"USD\"\n          }\n        }\n        ```\n        ","examples":[{"summary":"Find return options for single-segment outbound","value":{"outboundSegments":[{"airline":"EK","flightNumber":"29","departure":{"airport":"DXB"},"arrival":{"airport":"LHR"}}],"searchParams":{"origin":"DXB","destination":"LHR","departureDate":"2026-01-02","returnDate":"2026-01-10","adults":1}}},{"summary":"Find return options for multi-segment outbound","value":{"outboundSegments":[{"airline":"AF","flightNumber":"1681","departure":{"airport":"LHR"},"arrival":{"airport":"CDG"}},{"airline":"AF","flightNumber":"XXX","departure":{"airport":"CDG"},"arrival":{"airport":"DXB"}}],"searchParams":{"origin":"DXB","destination":"LHR","departureDate":"2026-01-02","returnDate":"2026-01-10","adults":2,"children":1}}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"outboundSegments":{"description":"Selected outbound flight segments for matching","type":"array","items":{"type":"object","properties":{"airline":{"description":"Airline IATA code (e.g., 'EK')","type":"string"},"flightNumber":{"description":"Flight number (e.g., '29')","type":"string"},"departure":{"type":"object","properties":{"airport":{"description":"Departure airport IATA code","type":"string"},"dateTime":{"description":"Departure date/time (ISO 8601)","type":"string"}},"required":["airport"]},"arrival":{"type":"object","properties":{"airport":{"description":"Arrival airport IATA code","type":"string"},"dateTime":{"description":"Arrival date/time (ISO 8601)","type":"string"}},"required":["airport"]}},"required":["airline","flightNumber"]}},"searchParams":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code","type":"string"},"destination":{"description":"Destination airport IATA code","type":"string"},"departureDate":{"description":"Departure date (YYYY-MM-DD)","type":"string"},"returnDate":{"description":"Return date (YYYY-MM-DD)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"cabinClass":{"anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}},"required":["origin","destination","departureDate","returnDate","adults"]},"searchKey":{"description":"Optional: Search key from previous search (for caching)","type":"string"}},"required":["outboundSegments","searchParams"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"outboundSegments":{"description":"Selected outbound flight segments for matching","type":"array","items":{"type":"object","properties":{"airline":{"description":"Airline IATA code (e.g., 'EK')","type":"string"},"flightNumber":{"description":"Flight number (e.g., '29')","type":"string"},"departure":{"type":"object","properties":{"airport":{"description":"Departure airport IATA code","type":"string"},"dateTime":{"description":"Departure date/time (ISO 8601)","type":"string"}},"required":["airport"]},"arrival":{"type":"object","properties":{"airport":{"description":"Arrival airport IATA code","type":"string"},"dateTime":{"description":"Arrival date/time (ISO 8601)","type":"string"}},"required":["airport"]}},"required":["airline","flightNumber"]}},"searchParams":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code","type":"string"},"destination":{"description":"Destination airport IATA code","type":"string"},"departureDate":{"description":"Departure date (YYYY-MM-DD)","type":"string"},"returnDate":{"description":"Return date (YYYY-MM-DD)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"cabinClass":{"anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}},"required":["origin","destination","departureDate","returnDate","adults"]},"searchKey":{"description":"Optional: Search key from previous search (for caching)","type":"string"}},"required":["outboundSegments","searchParams"]}},"text/plain":{"schema":{"type":"object","properties":{"outboundSegments":{"description":"Selected outbound flight segments for matching","type":"array","items":{"type":"object","properties":{"airline":{"description":"Airline IATA code (e.g., 'EK')","type":"string"},"flightNumber":{"description":"Flight number (e.g., '29')","type":"string"},"departure":{"type":"object","properties":{"airport":{"description":"Departure airport IATA code","type":"string"},"dateTime":{"description":"Departure date/time (ISO 8601)","type":"string"}},"required":["airport"]},"arrival":{"type":"object","properties":{"airport":{"description":"Arrival airport IATA code","type":"string"},"dateTime":{"description":"Arrival date/time (ISO 8601)","type":"string"}},"required":["airport"]}},"required":["airline","flightNumber"]}},"searchParams":{"type":"object","properties":{"origin":{"description":"Origin airport IATA code","type":"string"},"destination":{"description":"Destination airport IATA code","type":"string"},"departureDate":{"description":"Departure date (YYYY-MM-DD)","type":"string"},"returnDate":{"description":"Return date (YYYY-MM-DD)","type":"string"},"adults":{"minimum":1,"description":"Number of adult passengers","type":"number"},"children":{"minimum":0,"description":"Number of child passengers","type":"number"},"infants":{"minimum":0,"description":"Number of infant passengers","type":"number"},"cabinClass":{"anyOf":[{"const":"economy","type":"string"},{"const":"premium_economy","type":"string"},{"const":"business","type":"string"},{"const":"first","type":"string"}]},"currency":{"description":"Currency code (e.g., 'USD', 'AED')","type":"string"}},"required":["origin","destination","departureDate","returnDate","adults"]},"searchKey":{"description":"Optional: Search key from previous search (for caching)","type":"string"}},"required":["outboundSegments","searchParams"]}}}},"responses":{"200":{}}}},"/flights/validate-precise-pricing/{solutionKey}":{"get":{"parameters":[{"description":"Solution key to validate","schema":{"type":"string"},"in":"path","name":"solutionKey","required":true}],"operationId":"getFlightsValidate-precise-pricingBySolutionKey","tags":["flights"],"summary":"⏱️ Validate Precise Pricing Time Window","description":"\n        **Validate that precise pricing is still within the 30-minute time window**\n\n        This endpoint checks if a solutionKey's precise pricing timestamp is still valid for booking or penalty operations.\n        Must be called before creating a booking to ensure the precise pricing result hasn't expired.\n\n        ### **Request Parameters**\n        - **solutionKey** (required): Solution key from precise pricing call\n\n        ### **Response**\n        - **success**: Whether the validation check succeeded\n        - **isValid**: Whether the time window is still valid\n        - **timeRemaining**: Milliseconds remaining until expiration\n        - **timestamp**: When precise pricing was called (if valid)\n        - **expirationTime**: ISO timestamp when the window expires (if valid)\n        - **error**: Error details if validation failed\n\n        ### **Error Codes**\n        - **B037**: Precise pricing timestamp not found (precise pricing not called yet)\n        - **B024**: Precise pricing has expired (more than 15 minutes have passed)\n\n        ### **Use Case**\n        Booking service should call this endpoint before creating an order to ensure the precise pricing result is still valid.\n\n        ### **Example Request**\n        ```\n        GET /flights/validate-precise-pricing/abc123xyz\n        ```\n\n        ### **Example Response (Valid)**\n        ```json\n        {\n          \"success\": true,\n          \"isValid\": true,\n          \"timeRemaining\": 1200000,\n          \"timestamp\": 1737705600000,\n          \"expirationTime\": \"2026-01-24T10:30:00.000Z\"\n        }\n        ```\n\n        ### **Example Response (Expired)**\n        ```json\n        {\n          \"success\": false,\n          \"isValid\": false,\n          \"timeRemaining\": 0,\n          \"error\": {\n            \"errorCode\": \"B024\",\n            \"errorMessage\": \"The precise pricing result has expired...\",\n            \"retryable\": false,\n            \"category\": \"business\",\n            \"userAction\": \"Please call precise pricing again...\"\n          }\n        }\n        ```\n        ","responses":{"200":{}}}},"/airlines/":{"get":{"parameters":[{"description":"Search by airline name, IATA, or ICAO code","schema":{"type":"string"},"in":"query","name":"search","required":false},{"description":"Filter by country name","schema":{"type":"string"},"in":"query","name":"country","required":false},{"description":"Filter by active status (true/false)","schema":{"anyOf":[{"const":"true","type":"string"},{"const":"false","type":"string"}]},"in":"query","name":"active","required":false},{"description":"Maximum number of results (default: 50, max: 200)","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"Offset for pagination (default: 0)","schema":{"type":"string"},"in":"query","name":"offset","required":false},{"description":"Sort by field","schema":{"anyOf":[{"const":"name","type":"string"},{"const":"iata","type":"string"},{"const":"country","type":"string"}]},"in":"query","name":"sortBy","required":false},{"description":"Sort order (default: asc)","schema":{"anyOf":[{"const":"asc","type":"string"},{"const":"desc","type":"string"}]},"in":"query","name":"sortOrder","required":false}],"operationId":"getAirlines","tags":["airlines"],"summary":"✈️ Get Airlines","description":"\n        **Get list of airlines with search, filters, and pagination**\n\n        This endpoint returns a comprehensive list of airlines from the database.\n        Supports searching, filtering by country/status, sorting, and pagination.\n\n        ### **Query Parameters**\n        - **search** (optional): Search by airline name, IATA code, or ICAO code\n        - **country** (optional): Filter by country name (partial match)\n        - **active** (optional): Filter by active status (\"true\" or \"false\")\n        - **limit** (optional): Maximum number of results (default: 50, max: 200)\n        - **offset** (optional): Offset for pagination (default: 0)\n        - **sortBy** (optional): Sort by \"name\", \"iata\", or \"country\" (default: \"name\")\n        - **sortOrder** (optional): Sort order \"asc\" or \"desc\" (default: \"asc\")\n\n        ### **Response**\n        Returns paginated list of airlines with:\n        - **data**: Array of airline objects with name, IATA, ICAO, country, logo, etc.\n        - **pagination**: Pagination metadata (total, limit, offset, hasMore)\n        - **filters**: Applied filters for reference\n\n        ### **Example Requests**\n        - Get all active airlines: `GET /airlines?active=true`\n        - Search for \"Turkish\": `GET /airlines?search=Turkish`\n        - Get airlines from UAE: `GET /airlines?country=United Arab Emirates`\n        - Paginated results: `GET /airlines?limit=20&offset=0`\n        - Sorted by name: `GET /airlines?sortBy=name&sortOrder=asc`\n        ","examples":[{"summary":"Get all active airlines","value":{"active":"true","limit":"50"}},{"summary":"Search for airlines","value":{"search":"Turkish"}},{"summary":"Filter by country","value":{"country":"United Arab Emirates","active":"true"}},{"summary":"Paginated and sorted","value":{"limit":"20","offset":"0","sortBy":"name","sortOrder":"asc"}}],"responses":{"200":{}}}},"/airlines/{iata}":{"get":{"parameters":[{"description":"IATA airline code (e.g., 'EK', 'TK', 'LH')","schema":{"type":"string","minLength":1,"maxLength":3},"in":"path","name":"iata","required":true}],"operationId":"getAirlinesByIata","tags":["airlines"],"summary":"✈️ Get Airline by IATA Code","description":"\n        **Get detailed information for a specific airline by IATA code**\n\n        Returns complete airline information including name, codes, country, logo, and status.\n\n        ### **Path Parameters**\n        - **iata** (required): IATA 2-letter airline code (e.g., \"EK\", \"TK\", \"LH\")\n\n        ### **Response**\n        Returns airline object with:\n        - **name**: Full airline name\n        - **iata**: IATA code\n        - **icao**: ICAO code\n        - **callsign**: Radio callsign\n        - **country**: Country of origin\n        - **logo**: Logo URL\n        - **active**: Active status\n\n        ### **Example**\n        `GET /airlines/EK` returns Emirates Airlines information\n        ","responses":{"200":{}}}},"/airlines/stats":{"get":{"operationId":"getAirlinesStats","tags":["airlines"],"summary":"📊 Get Airline Statistics","description":"\n        **Get statistics about the airline database**\n\n        Returns aggregate statistics including:\n        - Total number of airlines\n        - Active vs inactive counts\n        - Number of countries\n        - Top 10 countries by airline count\n\n        ### **Response**\n        Returns statistics object with counts and top countries.\n        ","responses":{"200":{}}}},"/":{"get":{"operationId":"getIndex","responses":{"200":{}}}},"/health":{"get":{"operationId":"getHealth","responses":{"200":{}}}}},"components":{"schemas":{}}}