{"openapi":"3.1.0","info":{"title":"Audiobook Recommender API","description":"Personal audiobook recommendation engine with semantic search and weighted scoring.\n\nImport your Libation audiobook library and get intelligent recommendations based on:\n- Content similarity (categories, descriptions)\n- Series completion priority\n- Community and personal ratings\n- Semantic vector similarity using BGE embeddings\n\nExternal discovery features find new books via Hardcover GraphQL API with Open Library fallback.\n","version":"v1","contact":{"name":"Haiven Support","url":"https://audiobook-recommender.haiven.site"},"license":{"name":"Internal","url":"https://audiobook-recommender.haiven.site"}},"servers":[{"url":"https://audiobook-recommender.haiven.site","description":"Production server (HTTPS)"},{"url":"http://audiobook-backend:8000","description":"Internal Docker network"}],"tags":[{"name":"Health","description":"Health check and metrics endpoints"},{"name":"Books","description":"Book library management and browsing"},{"name":"Import","description":"Library import from Libation exports"},{"name":"Recommendations","description":"Book recommendation engine"},{"name":"Discovery","description":"External book discovery"}],"paths":{"/health":{"get":{"summary":"Health check endpoint","tags":["Health"],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/metrics":{"get":{"summary":"Prometheus metrics endpoint","tags":["Health"],"responses":{"200":{"description":"Prometheus metrics","content":{"text/plain":{"schema":{"type":"string","example":"# HELP audiobook_books_total Total books in library\n# TYPE audiobook_books_total gauge\naudiobook_books_total 1042\n"}}}}}}},"/api/stats":{"get":{"summary":"Library statistics","tags":["Books"],"responses":{"200":{"description":"Library statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryStats"}}}}}}},"/api/books":{"get":{"summary":"List books with pagination and filters","tags":["Books"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Number of books to return"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search query (title, author, narrator)"},{"name":"status","in":"query","schema":{"type":"string","enum":["finished","unfinished","all"],"default":"all"},"description":"Filter by completion status"},{"name":"series","in":"query","schema":{"type":"string"},"description":"Filter by series name"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"},{"name":"sort","in":"query","schema":{"type":"string","enum":["date_added","rating","title","length"],"default":"date_added"},"description":"Sort field"},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"}],"responses":{"200":{"description":"List of books","content":{"application/json":{"schema":{"type":"object","properties":{"books":{"type":"array","items":{"$ref":"#/components/schemas/Book"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}}},"/api/books/{id}":{"get":{"summary":"Get single book details","tags":["Books"],"parameters":[{"$ref":"#/components/parameters/BookId"}],"responses":{"200":{"description":"Book details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookDetail"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/import":{"post":{"summary":"Import Libation Excel export","tags":["Import"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"Libation Excel export file (.xlsx)"}}}}}},"responses":{"200":{"description":"Import completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"400":{"description":"Invalid file format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/recommend/backlog":{"get":{"summary":"Get weighted recommendations from unfinished books","tags":["Recommendations"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":50},"description":"Number of recommendations to return"},{"name":"include_scores","in":"query","schema":{"type":"boolean","default":true},"description":"Include detailed score breakdown"}],"responses":{"200":{"description":"Recommendations with scores","content":{"application/json":{"schema":{"type":"object","properties":{"recommendations":{"type":"array","items":{"$ref":"#/components/schemas/Recommendation"}}}}}}}}}},"/api/recommend/similar/{id}":{"get":{"summary":"Find books similar to a given book","tags":["Recommendations"],"parameters":[{"$ref":"#/components/parameters/BookId"},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":50},"description":"Number of similar books to return"},{"name":"exclude_finished","in":"query","schema":{"type":"boolean","default":false},"description":"Exclude already finished books"}],"responses":{"200":{"description":"Similar books","content":{"application/json":{"schema":{"type":"object","properties":{"similar_books":{"type":"array","items":{"$ref":"#/components/schemas/SimilarBook"}}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/recommend/chat":{"post":{"summary":"RAG-based conversational recommendations","tags":["Recommendations"],"description":"Optional endpoint for conversational recommendations using local LLM (requires Ollama).\nSend natural language queries like \"What should I listen to if I liked The Expanse?\"\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","description":"Natural language recommendation query","example":"I want something like The Expanse but shorter"},"context_limit":{"type":"integer","default":5,"description":"Number of context books to retrieve"}}}}}},"responses":{"200":{"description":"RAG response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"503":{"description":"RAG mode not available (Ollama not configured)"}}}},"/api/discover/{id}":{"get":{"summary":"Discover related books from external APIs","tags":["Discovery"],"description":"Find books you don't own that are similar to a book in your library.\nUses Hardcover GraphQL API primarily, with Open Library as fallback.\nResults are cached for 30 minutes.\n","parameters":[{"$ref":"#/components/parameters/BookId"},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":50},"description":"Maximum discoveries to return"}],"responses":{"200":{"description":"Discovered books","content":{"application/json":{"schema":{"type":"object","properties":{"discoveries":{"type":"array","items":{"$ref":"#/components/schemas/DiscoveredBook"}},"source":{"type":"string","enum":["hardcover","openlibrary","cached"]}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"parameters":{"BookId":{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Book ID"}},"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"version":{"type":"string"},"database":{"type":"string","enum":["connected","disconnected"]},"embedding_model":{"type":"string"},"books_count":{"type":"integer"}}},"LibraryStats":{"type":"object","properties":{"total_books":{"type":"integer"},"finished":{"type":"integer"},"unfinished":{"type":"integer"},"in_series":{"type":"integer"},"standalone":{"type":"integer"},"unique_authors":{"type":"integer"},"unique_narrators":{"type":"integer"},"unique_series":{"type":"integer"},"unique_categories":{"type":"integer"},"total_hours":{"type":"number"},"embeddings_generated":{"type":"integer"}}},"Book":{"type":"object","properties":{"id":{"type":"integer"},"audible_id":{"type":"string"},"title":{"type":"string"},"authors":{"type":"string"},"narrators":{"type":"string"},"series_name":{"type":"string","nullable":true},"series_order":{"type":"number","nullable":true},"categories":{"type":"string"},"length_minutes":{"type":"integer"},"community_rating":{"type":"number"},"my_rating":{"type":"number","nullable":true},"is_finished":{"type":"boolean"},"date_added":{"type":"string","format":"date"}}},"BookDetail":{"allOf":[{"$ref":"#/components/schemas/Book"},{"type":"object","properties":{"description":{"type":"string"},"cover_url":{"type":"string","format":"uri"},"series_books":{"type":"array","items":{"$ref":"#/components/schemas/Book"},"description":"Other books in the same series"}}}]},"ImportResult":{"type":"object","properties":{"success":{"type":"boolean"},"books_imported":{"type":"integer"},"books_updated":{"type":"integer"},"books_skipped":{"type":"integer"},"embeddings_generated":{"type":"integer"},"duration_seconds":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}}},"Recommendation":{"type":"object","properties":{"book":{"$ref":"#/components/schemas/Book"},"overall_score":{"type":"number","minimum":0,"maximum":100},"score_breakdown":{"type":"object","properties":{"content_score":{"type":"number"},"series_score":{"type":"number"},"rating_score":{"type":"number"},"embedding_score":{"type":"number"}}},"reason":{"type":"string","description":"Human-readable explanation for recommendation"}}},"SimilarBook":{"type":"object","properties":{"book":{"$ref":"#/components/schemas/Book"},"similarity_score":{"type":"number","minimum":0,"maximum":1,"description":"Cosine similarity of embeddings"}}},"ChatResponse":{"type":"object","properties":{"response":{"type":"string","description":"LLM-generated recommendation text"},"context_books":{"type":"array","items":{"$ref":"#/components/schemas/Book"},"description":"Books used as RAG context"},"model":{"type":"string","description":"LLM model used"}}},"DiscoveredBook":{"type":"object","properties":{"title":{"type":"string"},"authors":{"type":"string"},"description":{"type":"string"},"cover_url":{"type":"string","format":"uri"},"series_name":{"type":"string","nullable":true},"series_order":{"type":"number","nullable":true},"average_rating":{"type":"number"},"source":{"type":"string","enum":["hardcover","openlibrary"]},"external_url":{"type":"string","format":"uri","description":"Link to book on source site"}}},"Error":{"type":"object","properties":{"message":{"type":"string"},"detail":{"type":"string"}}}},"responses":{"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Book not found"}}}}}}}}}