{"openapi":"3.0.3","info":{"title":"Search & Recommendation Engine API","description":"⚡ Ultra-fast experience search and AI-powered recommendation engine with sophisticated fuzzy matching, quality weightage, and optional user personalization","version":"2.0.0"},"tags":[{"name":"recommendations","description":"🎯 AI-powered experience recommendations"},{"name":"search","description":"🔍 Advanced experience search with fuzzy matching"},{"name":"fuzzy-search","description":"🧠 Intelligent fuzzy search with quality weightage"},{"name":"analytics","description":"📊 Search & recommendation analytics"},{"name":"monitoring","description":"📈 Performance monitoring and health checks"}],"paths":{"/search/":{"get":{"parameters":[{"description":"Search query","schema":{"type":"string"},"in":"query","name":"q","required":false},{"description":"Latitude coordinate","schema":{"type":"string"},"in":"query","name":"lat","required":false},{"description":"Longitude coordinate","schema":{"type":"string"},"in":"query","name":"lng","required":false},{"description":"Search radius in meters","schema":{"type":"string"},"in":"query","name":"radius","required":false},{"description":"Comma-separated categories","schema":{"type":"string"},"in":"query","name":"categories","required":false},{"description":"Filter by city name (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false},{"description":"Filter by Headout ID (exact match)","schema":{"type":"string"},"in":"query","name":"headoutId","required":false},{"description":"Price range (e.g., '0-100')","schema":{"type":"string"},"in":"query","name":"priceRange","required":false},{"description":"Filter by cancellable status (true/false)","schema":{"type":"string"},"in":"query","name":"cancellable","required":false},{"description":"Filter by reschedulable status (true/false)","schema":{"type":"string"},"in":"query","name":"reschedulable","required":false},{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"Offset for pagination","schema":{"type":"string"},"in":"query","name":"offset","required":false},{"description":"Sort by field","schema":{"type":"string"},"in":"query","name":"sortBy","required":false},{"description":"Sort order (asc/desc)","schema":{"type":"string"},"in":"query","name":"sortOrder","required":false}],"operationId":"getSearch","summary":"Search experiences","description":"Search for experiences using various filters and parameters. Use city parameter to filter by specific city name (case-insensitive). Use headoutId parameter to filter by exact Headout ID match.","tags":["search"],"responses":{"200":{}}}},"/search/count":{"get":{"operationId":"getSearchCount","summary":"Get total experience count","description":"Get the total number of experiences in the database","tags":["search"],"responses":{"200":{}}}},"/search/{id}":{"get":{"parameters":[{"description":"Experience ID","schema":{"type":"string"},"in":"path","name":"id","required":true}],"operationId":"getSearchById","summary":"Get experience by ID","description":"Retrieve a specific experience by its ID","tags":["search"],"responses":{"200":{}}}},"/search/fuzzy":{"get":{"parameters":[{"description":"Search query for fuzzy matching","schema":{"type":"string"},"in":"query","name":"q","required":false},{"description":"Latitude coordinate","schema":{"type":"string"},"in":"query","name":"lat","required":false},{"description":"Longitude coordinate","schema":{"type":"string"},"in":"query","name":"lng","required":false},{"description":"Search radius in meters","schema":{"type":"string"},"in":"query","name":"radius","required":false},{"description":"Comma-separated categories","schema":{"type":"string"},"in":"query","name":"categories","required":false},{"description":"Filter by city name (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false},{"description":"Filter by Headout ID (exact match)","schema":{"type":"string"},"in":"query","name":"headoutId","required":false},{"description":"Minimum price in AED","schema":{"type":"string"},"in":"query","name":"priceFrom","required":false},{"description":"Maximum price in AED","schema":{"type":"string"},"in":"query","name":"priceTo","required":false},{"description":"Price range categories: CHEAP,AVERAGE,PREMIUM,LUXURY","schema":{"type":"string"},"in":"query","name":"priceRange","required":false},{"description":"Filter by cancellable status (true/false)","schema":{"type":"string"},"in":"query","name":"cancellable","required":false},{"description":"Filter by reschedulable status (true/false)","schema":{"type":"string"},"in":"query","name":"reschedulable","required":false},{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"Offset for pagination","schema":{"type":"string"},"in":"query","name":"offset","required":false},{"description":"Minimum fuzzy match score (0-1)","schema":{"type":"string"},"in":"query","name":"minScore","required":false},{"description":"Include detailed fuzzy match information","schema":{"type":"string"},"in":"query","name":"includeFuzzyDetails","required":false},{"description":"Bypass cache and fetch fresh results","schema":{"type":"string"},"in":"query","name":"noCache","required":false}],"operationId":"getSearchFuzzy","summary":"Fuzzy search experiences","description":"Intelligent search with typo tolerance, phonetic matching, and semantic understanding. Query parameter is optional - if not provided, returns location/category filtered results. Use noCache=true to bypass cache. Use city parameter to filter by specific city. Use priceFrom/priceTo for exact price ranges or priceRangeEnum for predefined categories (CHEAP, AVERAGE, PREMIUM, LUXURY).","tags":["search"],"responses":{"200":{}}}},"/recommend/":{"get":{"parameters":[{"description":"Search query for vector semantic search","schema":{"type":"string"},"in":"query","name":"q","required":true},{"description":"Latitude coordinate","schema":{"type":"string"},"in":"query","name":"lat","required":false},{"description":"Longitude coordinate","schema":{"type":"string"},"in":"query","name":"lng","required":false},{"description":"Search radius in meters","schema":{"type":"string"},"in":"query","name":"radius","required":false},{"description":"Comma-separated categories","schema":{"type":"string"},"in":"query","name":"categories","required":false},{"description":"Filter by city name (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false},{"description":"Filter by Headout ID (exact match)","schema":{"type":"string"},"in":"query","name":"headoutId","required":false},{"description":"Price range (e.g., '0-100')","schema":{"type":"string"},"in":"query","name":"priceRange","required":false},{"description":"Filter by cancellable status (true/false)","schema":{"type":"string"},"in":"query","name":"cancellable","required":false},{"description":"Filter by reschedulable status (true/false)","schema":{"type":"string"},"in":"query","name":"reschedulable","required":false},{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"Offset for pagination","schema":{"type":"string"},"in":"query","name":"offset","required":false},{"description":"Use BAAI reranker to improve results (default: true)","schema":{"type":"string"},"in":"query","name":"useReranker","required":false},{"description":"Minimum cosine similarity threshold (0-1, default: 0.3)","schema":{"type":"string"},"in":"query","name":"similarityThreshold","required":false}],"operationId":"getRecommend","summary":"Vector search recommendations","description":"Semantic search using BAAI bge-base-en embeddings with hard filters. Results are reranked using BAAI reranker for improved relevance. Supports all standard filters: categories, city, headoutId, price range, cancellable, reschedulable, and location-based filtering.","tags":["search","vector","recommendations"],"responses":{"200":{}}}},"/recommendations/":{"get":{"parameters":[{"schema":{"type":"string"},"in":"header","name":"x-user-id","required":false},{"schema":{"type":"string"},"in":"query","name":"lat","required":false},{"schema":{"type":"string"},"in":"query","name":"lng","required":false},{"schema":{"type":"string"},"in":"query","name":"radius","required":false},{"schema":{"type":"string"},"in":"query","name":"categories","required":false},{"schema":{"type":"string"},"in":"query","name":"context","required":false},{"schema":{"type":"string"},"in":"query","name":"priceRange","required":false},{"schema":{"type":"string"},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"useBayesian","required":false},{"description":"City filter (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false}],"operationId":"getRecommendations","summary":"Get smart experience recommendations","description":"Get AI-powered experience recommendations based on location, preferences, and context","tags":["recommendations"],"responses":{"200":{}}}},"/recommendations/search":{"get":{"parameters":[{"description":"Natural language search query","schema":{"type":"string"},"in":"query","name":"q","required":true}],"operationId":"getRecommendationsSearch","summary":"Natural language experience search","description":"Search experiences using natural language queries like 'adventure activities near downtown'","tags":["search"],"responses":{"200":{}}}},"/recommendations/nearby":{"get":{"parameters":[{"description":"Latitude coordinate","schema":{"type":"string"},"in":"query","name":"lat","required":true},{"description":"Longitude coordinate","schema":{"type":"string"},"in":"query","name":"lng","required":true},{"description":"Search radius in meters","schema":{"type":"string"},"in":"query","name":"radius","required":false},{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false}],"operationId":"getRecommendationsNearby","summary":"Get nearby experiences","description":"Find experiences near a specific location","tags":["recommendations"],"responses":{"200":{}}}},"/recommendations/trending":{"get":{"parameters":[{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"City filter (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false}],"operationId":"getRecommendationsTrending","summary":"Get trending experiences","description":"Find popular and trending experiences","tags":["recommendations"],"responses":{"200":{}}}},"/recommendations/context/{context}":{"get":{"parameters":[{"description":"Experience context","schema":{"type":"string","enum":["adventure","family","romantic","cultural","thrill","relaxation"]},"in":"path","name":"context","required":true},{"description":"Latitude coordinate","schema":{"type":"string"},"in":"query","name":"lat","required":false},{"description":"Longitude coordinate","schema":{"type":"string"},"in":"query","name":"lng","required":false},{"description":"Maximum number of results","schema":{"type":"string"},"in":"query","name":"limit","required":false},{"description":"City filter (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false}],"operationId":"getRecommendationsContextByContext","summary":"Get context-aware recommendations","description":"Get recommendations based on specific context (adventure, family, romantic, etc.)","tags":["recommendations"],"responses":{"200":{}}}},"/recommendations/categories":{"get":{"parameters":[{"description":"City code to filter categories by (case-insensitive)","schema":{"type":"string"},"in":"query","name":"city","required":false},{"description":"Include categories without activities from Headout API (default: false, requires city parameter)","schema":{"type":"string"},"in":"query","name":"includeWithoutActivities","required":false},{"description":"Language code for Headout API (default: EN)","schema":{"type":"string","default":"EN"},"in":"query","name":"languageCode","required":false}],"operationId":"getRecommendationsCategories","summary":"Get all categories with enhanced metadata","description":"Get categories that have activities by default. Optionally include categories without activities from Headout API (requires city parameter). Returns detailed metadata about category sources and counts.","tags":["search"],"responses":{"200":{}}}},"/recommendations/suggestions":{"get":{"parameters":[{"description":"Partial query for suggestions","schema":{"type":"string"},"in":"query","name":"q","required":true}],"operationId":"getRecommendationsSuggestions","summary":"Get search suggestions","description":"Get autocomplete suggestions for search queries","tags":["search"],"responses":{"200":{}}}},"/recommendations/stats":{"get":{"operationId":"getRecommendationsStats","summary":"Get search statistics","description":"Get analytics and statistics about the search system","tags":["analytics"],"responses":{"200":{}}}},"/mcp/tools":{"get":{"operationId":"getMcpTools","tags":["mcp"],"summary":"Get available MCP tools","description":"Returns a list of all available MCP tools for search service with their schemas and descriptions","responses":{"200":{}}}},"/mcp/tools/{tool}":{"get":{"operationId":"getMcpToolsByTool","tags":["mcp"],"summary":"Get tool schema","description":"Returns the schema definition for a specific MCP tool","parameters":[{"schema":{"type":"string"},"in":"path","name":"tool","required":true}],"responses":{"200":{}}}},"/mcp/execute/{tool}":{"post":{"parameters":[{"schema":{"type":"string"},"in":"path","name":"tool","required":true}],"operationId":"postMcpExecuteByTool","tags":["mcp"],"summary":"Execute MCP tool","description":"Execute a specific MCP tool with the provided parameters","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","patternProperties":{"^(.*)$":{}}}},"multipart/form-data":{"schema":{"type":"object","patternProperties":{"^(.*)$":{}}}},"text/plain":{"schema":{"type":"object","patternProperties":{"^(.*)$":{}}}}}},"responses":{"200":{}}}},"/mcp/health":{"get":{"operationId":"getMcpHealth","tags":["mcp"],"summary":"MCP health check","description":"Check if the search service MCP module is healthy and responsive","responses":{"200":{}}}},"/embeddings/generate":{"post":{"parameters":[],"operationId":"postEmbeddingsGenerate","summary":"Start embedding generation job","description":"Starts a background job to generate embeddings for experiences. Returns immediately with a job ID. Use the status endpoint to check progress. Only processes experiences without embeddings unless force=true.","tags":["embeddings","vector"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"description":"Regenerate embeddings for all experiences (default: false)","type":"boolean"},"limit":{"description":"Limit number of experiences to process","type":"string"},"batchSize":{"description":"Number of experiences to process per batch (default: 10)","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"force":{"description":"Regenerate embeddings for all experiences (default: false)","type":"boolean"},"limit":{"description":"Limit number of experiences to process","type":"string"},"batchSize":{"description":"Number of experiences to process per batch (default: 10)","type":"string"}}}},"text/plain":{"schema":{"type":"object","properties":{"force":{"description":"Regenerate embeddings for all experiences (default: false)","type":"boolean"},"limit":{"description":"Limit number of experiences to process","type":"string"},"batchSize":{"description":"Number of experiences to process per batch (default: 10)","type":"string"}}}}}},"responses":{"200":{}}}},"/embeddings/status/{jobId}":{"get":{"parameters":[{"description":"Job ID returned from /generate endpoint","schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"operationId":"getEmbeddingsStatusByJobId","summary":"Get embedding generation job status","description":"Check the status and progress of an embedding generation job. Returns job details including total, processed, success count, and error count.","tags":["embeddings","vector"],"responses":{"200":{}}}},"/embeddings/jobs":{"get":{"operationId":"getEmbeddingsJobs","summary":"List all embedding generation jobs","description":"Get a list of all embedding generation jobs and their statuses.","tags":["embeddings","vector"],"responses":{"200":{}}}},"/embeddings/ingest":{"post":{"parameters":[],"operationId":"postEmbeddingsIngest","summary":"Ingest experiences into embedding service","description":"Fetches experiences from the local database and ingests them into the external embedding service. This must be done before generating embeddings. Returns statistics about the ingestion process.","tags":["embeddings","vector"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limit":{"description":"Limit number of experiences to ingest (default: all)","type":"string"},"generateEmbeddings":{"description":"Generate embeddings immediately after ingestion (default: true)","type":"boolean"},"batchSize":{"description":"Number of experiences to process per batch (default: 100)","type":"string"},"cityCode":{"description":"Filter by city code (e.g. LONDON, DUBAI). Only ingest experiences from this city.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"limit":{"description":"Limit number of experiences to ingest (default: all)","type":"string"},"generateEmbeddings":{"description":"Generate embeddings immediately after ingestion (default: true)","type":"boolean"},"batchSize":{"description":"Number of experiences to process per batch (default: 100)","type":"string"},"cityCode":{"description":"Filter by city code (e.g. LONDON, DUBAI). Only ingest experiences from this city.","type":"string"}}}},"text/plain":{"schema":{"type":"object","properties":{"limit":{"description":"Limit number of experiences to ingest (default: all)","type":"string"},"generateEmbeddings":{"description":"Generate embeddings immediately after ingestion (default: true)","type":"boolean"},"batchSize":{"description":"Number of experiences to process per batch (default: 100)","type":"string"},"cityCode":{"description":"Filter by city code (e.g. LONDON, DUBAI). Only ingest experiences from this city.","type":"string"}}}}}},"responses":{"200":{}}}},"/":{"get":{"operationId":"getIndex","responses":{"200":{}}}},"/health":{"get":{"operationId":"getHealth","responses":{"200":{}}}},"/metrics":{"get":{"operationId":"getMetrics","responses":{"200":{}}}},"/analytics":{"get":{"operationId":"getAnalytics","responses":{"200":{}}}},"/database/stats":{"get":{"operationId":"getDatabaseStats","responses":{"200":{}}}},"/database/optimize":{"post":{"operationId":"postDatabaseOptimize","responses":{"200":{}}}},"/database/indexes":{"post":{"operationId":"postDatabaseIndexes","responses":{"200":{}}}},"/cache/stats":{"get":{"operationId":"getCacheStats","responses":{"200":{}}}},"/cache/clear":{"post":{"operationId":"postCacheClear","responses":{"200":{}}}}},"components":{"schemas":{}}}