{"openapi":"3.1.0","info":{"title":"Haiven Intelligence API","description":"Semantic search and intelligence API for AI conversations.\n\nEnables vector-based search over ingested Claude Code, ChatGPT, and Cursor\nconversations stored in Qdrant.\n\n## Features\n- Semantic search using vector similarity\n- Hybrid search combining vector and keyword matching\n- Find similar conversations by ID\n- Rich filtering by source, date, code content, and more\n\n## Authentication\nNo authentication required for internal access.\n","version":"1.0.0","contact":{"name":"Haiven Infrastructure","url":"https://home.haiven.site"}},"servers":[{"url":"https://intelligence.haiven.site","description":"Production (Traefik)"},{"url":"http://haiven-intelligence:8020","description":"Internal (Docker network)"}],"tags":[{"name":"Health","description":"Service health and status"},{"name":"Search","description":"Semantic and hybrid search endpoints"},{"name":"Statistics","description":"Collection statistics and metrics"}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health check","description":"Returns service health status including Qdrant and LiteLLM connectivity","operationId":"healthCheck","responses":{"200":{"description":"Service health status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"status":"healthy","qdrant":{"status":"healthy","collections":5},"litellm":{"status":"healthy"},"version":"1.0.0"}}}}}}},"/stats":{"get":{"tags":["Statistics"],"summary":"Collection statistics","description":"Returns vector counts, source distribution, and date range of indexed conversations","operationId":"getStats","responses":{"200":{"description":"Collection statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"},"example":{"collection":"chats","vectors_count":15420,"indexed_vectors_count":15420,"status":"green","sources":{"claude_code":12000,"chatgpt":3000,"cursor":420},"date_range":{"min":"2024-01-01T00:00:00Z","max":"2024-12-31T23:59:59Z"}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/search/semantic":{"post":{"tags":["Search"],"summary":"Semantic search","description":"Perform semantic search over conversations using vector similarity.\n\nThe query is converted to an embedding and compared against indexed\nconversation chunks using cosine similarity.\n","operationId":"semanticSearch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticSearchRequest"},"example":{"query":"how to implement authentication in FastAPI","limit":10,"filters":{"source":["claude_code"],"has_code":true},"score_threshold":0.5}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"503":{"description":"Embedding service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/search/hybrid":{"post":{"tags":["Search"],"summary":"Hybrid search","description":"Perform hybrid search combining vector similarity and keyword matching.\n\nCombines dense vector similarity with optional keyword query using\nconfigurable weights.\n","operationId":"hybridSearch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HybridSearchRequest"},"example":{"query":"docker networking problems","keyword_query":"bridge network","limit":10,"vector_weight":0.7,"keyword_weight":0.3}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"503":{"description":"Embedding service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/similar/{conversation_id}":{"get":{"tags":["Search"],"summary":"Find similar conversations","description":"Find conversations similar to a given conversation.\n\nComputes the average embedding of all chunks in the source conversation\nand finds nearest neighbors, deduplicated by conversation ID.\n","operationId":"findSimilar","parameters":[{"name":"conversation_id","in":"path","required":true,"description":"UUID of the source conversation","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Maximum number of similar conversations to return","schema":{"type":"integer","minimum":1,"maximum":20,"default":5}},{"name":"exclude_self","in":"query","description":"Whether to exclude the source conversation from results","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Similar conversations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimilarResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"SearchFilters":{"type":"object","description":"Filters for search queries","properties":{"source":{"type":"array","items":{"type":"string","enum":["claude_code","chatgpt","cursor"]},"description":"Filter by source platforms"},"date_from":{"type":"string","format":"date-time","description":"Start date for timestamp filter"},"date_to":{"type":"string","format":"date-time","description":"End date for timestamp filter"},"has_code":{"type":"boolean","description":"Filter conversations containing code blocks"},"has_thinking":{"type":"boolean","description":"Filter conversations with Claude thinking blocks"},"project_path":{"type":"string","description":"Filter by project path (supports wildcards)"},"role":{"type":"array","items":{"type":"string","enum":["user","assistant"]},"description":"Filter by message role"},"tool_names":{"type":"array","items":{"type":"string"},"description":"Filter by tools used in conversation"}}},"SemanticSearchRequest":{"type":"object","required":["query"],"properties":{"query":{"type":"string","minLength":1,"maxLength":2000,"description":"Natural language search query"},"limit":{"type":"integer","minimum":1,"maximum":100,"default":10,"description":"Maximum number of results"},"offset":{"type":"integer","minimum":0,"default":0,"description":"Number of results to skip"},"filters":{"$ref":"#/components/schemas/SearchFilters"},"include_payload":{"type":"boolean","default":true,"description":"Whether to include full payload in results"},"score_threshold":{"type":"number","minimum":0,"maximum":1,"description":"Minimum similarity score (0-1)"}}},"HybridSearchRequest":{"type":"object","required":["query"],"properties":{"query":{"type":"string","minLength":1,"maxLength":2000,"description":"Natural language query (used for vector search)"},"keyword_query":{"type":"string","description":"Optional separate keyword query for text matching"},"limit":{"type":"integer","minimum":1,"maximum":100,"default":10},"offset":{"type":"integer","minimum":0,"default":0},"filters":{"$ref":"#/components/schemas/SearchFilters"},"vector_weight":{"type":"number","minimum":0,"maximum":1,"default":0.7,"description":"Weight for vector search results"},"keyword_weight":{"type":"number","minimum":0,"maximum":1,"default":0.3,"description":"Weight for keyword search results"},"score_threshold":{"type":"number","minimum":0,"maximum":1}}},"SearchResult":{"type":"object","properties":{"chunk_id":{"type":"string","description":"Unique ID of this chunk"},"conversation_id":{"type":"string","description":"ID of the parent conversation"},"message_id":{"type":"string","nullable":true,"description":"ID of the specific message"},"score":{"type":"number","description":"Similarity score (0-1)"},"title":{"type":"string","description":"Conversation title"},"text":{"type":"string","description":"Relevant text snippet (truncated to 500 chars)"},"role":{"type":"string","enum":["user","assistant"],"description":"Message author role"},"source":{"type":"string","enum":["claude_code","chatgpt","cursor"],"description":"Source platform"},"timestamp":{"type":"string","format":"date-time","description":"Message timestamp"},"has_code":{"type":"boolean","default":false,"description":"Whether chunk contains code"},"has_thinking":{"type":"boolean","default":false,"description":"Whether chunk has thinking blocks"},"project_path":{"type":"string","nullable":true,"description":"Associated project directory"},"tool_names":{"type":"array","items":{"type":"string"},"description":"Tools used in this message"}}},"SearchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}},"total":{"type":"integer","description":"Total number of results returned"},"query_embedding_time_ms":{"type":"number","description":"Time to generate query embedding (ms)"},"search_time_ms":{"type":"number","description":"Time to execute search (ms)"},"rerank_time_ms":{"type":"number","nullable":true,"description":"Time for reranking (ms, if enabled)"}}},"SimilarConversation":{"type":"object","properties":{"conversation_id":{"type":"string"},"title":{"type":"string"},"similarity_score":{"type":"number"},"source":{"type":"string","enum":["claude_code","chatgpt","cursor"]},"timestamp":{"type":"string","format":"date-time"},"message_count":{"type":"integer","nullable":true},"preview":{"type":"string","nullable":true,"description":"Text preview (first 200 chars)"}}},"SimilarResponse":{"type":"object","properties":{"source_conversation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"source":{"type":"string"}}},"similar":{"type":"array","items":{"$ref":"#/components/schemas/SimilarConversation"}},"search_time_ms":{"type":"number"}}},"StatsResponse":{"type":"object","properties":{"collection":{"type":"string","description":"Collection name"},"vectors_count":{"type":"integer","description":"Total vectors in collection"},"indexed_vectors_count":{"type":"integer","description":"Indexed vectors (ready for search)"},"status":{"type":"string","description":"Collection status"},"sources":{"type":"object","additionalProperties":{"type":"integer"},"description":"Count of vectors by source"},"date_range":{"type":"object","properties":{"min":{"type":"string","format":"date-time","nullable":true},"max":{"type":"string","format":"date-time","nullable":true}}}}},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"qdrant":{"type":"object","properties":{"status":{"type":"string"},"collections":{"type":"integer"},"error":{"type":"string","nullable":true}}},"litellm":{"type":"object","properties":{"status":{"type":"string"},"error":{"type":"string","nullable":true}}},"version":{"type":"string"}}},"Error":{"type":"object","properties":{"detail":{"type":"string","description":"Error message"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}}}}