{"openapi":"3.0.0","paths":{"/api":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["Root"]}},"/api/auth/login":{"get":{"operationId":"AuthController_login","parameters":[],"responses":{"302":{"description":"Redirects user to Auth0 login"}},"summary":"Start Auth0 login flow","tags":["Auth"]}},"/api/auth/signup":{"get":{"operationId":"AuthController_signup","parameters":[],"responses":{"302":{"description":"Redirects user to Auth0 signup"}},"summary":"Start Auth0 signup flow","tags":["Auth"]}},"/api/auth/setup":{"get":{"operationId":"AuthController_setup","parameters":[],"responses":{"302":{"description":"Redirects user to Auth0 signup"}},"summary":"Alias for signup flow","tags":["Auth"]}},"/api/auth/callback":{"get":{"operationId":"AuthController_callback","parameters":[{"name":"code","required":true,"in":"query","schema":{"type":"string"}},{"name":"state","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects authenticated user to app"},"400":{"description":"Invalid state, code, or callback"}},"summary":"Handle Auth0 callback and create session","tags":["Auth"]}},"/api/auth/logout":{"post":{"operationId":"AuthController_logoutPost","parameters":[],"responses":{"302":{"description":"Logs out and redirects to frontend"},"401":{"description":"No session found"}},"security":[{"session":[]}],"tags":["Auth"]},"get":{"operationId":"AuthController_logoutGet","parameters":[],"responses":{"302":{"description":"Logs out and redirects to frontend"},"401":{"description":"No session found"}},"security":[{"session":[]}],"tags":["Auth"]}},"/api/auth/me":{"get":{"operationId":"AuthController_me","parameters":[],"responses":{"401":{"description":"No valid session found"}},"security":[{"session":[]}],"summary":"Get current authenticated user","tags":["Auth"]}},"/api/books":{"post":{"operationId":"BookController_createBook","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBookDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookReadDto"}}}}},"security":[{"session":[]}],"tags":["Books"]},"get":{"operationId":"BookController_getBooks","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BookWithProgressReadDto"}}}}}},"security":[{"session":[]}],"tags":["Books"]}},"/api/books/recent":{"get":{"operationId":"BookController_getRecentBooks","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentBookReadDto"}}}}}},"security":[{"session":[]}],"summary":"Get recently added books for the current user","tags":["Books"]}},"/api/books/search":{"get":{"operationId":"BookController_searchBooks","parameters":[{"name":"query","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookSearchResponseDto"}}}},"400":{"description":"Query parameter is required"}},"security":[{"session":[]}],"summary":"Search books in Google Books API","tags":["Books"]}},"/api/books/webpage/lookup":{"get":{"operationId":"BookController_lookupWebpage","parameters":[{"name":"url","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebpageLookupResponseDto"}}}},"404":{"description":"URL not in library"}},"security":[{"session":[]}],"summary":"Check whether a web page URL is already saved by the user","tags":["Books"]}},"/api/books/webpage":{"post":{"operationId":"BookController_addWebpage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebpageBookDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebpageBookResponseDto"}}}},"400":{"description":"Invalid or blocked URL"}},"security":[{"session":[]}],"summary":"Add a web page as a quiz source. With `content` (extension capture) the provided text is used; without it the backend fetches the public URL and extracts content server-side.","tags":["Books"]}},"/api/books/{id}/status":{"get":{"operationId":"BookController_getBookStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookStatusReadDto"}}}},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Books"]}},"/api/books/{id}/retry":{"post":{"operationId":"BookController_retryBook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookStatusReadDto"}}}},"400":{"description":"Book is not in a retryable state"},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Books"]}},"/api/books/{id}":{"get":{"operationId":"BookController_getBook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdResponseDto"}}}}},"security":[{"session":[]}],"tags":["Books"]},"delete":{"operationId":"BookController_deleteBook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdResponseDto"}}}},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Books"]}},"/api/books/upload":{"post":{"operationId":"BookController_uploadBook","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/UploadBookRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadBookResponseDto"}}}},"400":{"description":"No file uploaded"}},"security":[{"session":[]}],"tags":["Books"]}},"/api/questions/save_answer":{"post":{"operationId":"QuestionController_saveAnswer","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAnswerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyResponseDto"}}}}},"security":[{"session":[]}],"tags":["Questions"]}},"/api/questions/next/{bookId}":{"post":{"operationId":"QuestionController_nextQuestion","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuestionReadDto"}],"nullable":true}}}},"403":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsufficientCreditsErrorDto"}}}},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Questions"]}},"/api/questions/next/streaming/{bookId}":{"post":{"operationId":"QuestionController_streamQuestion","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"text/event-stream":{"schema":{"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/QuestionReadDto"}]}},"application/json":{"schema":{"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/QuestionReadDto"}]}}}},"400":{"description":"Book ID is required"},"404":{"description":"Book not found"},"409":{"description":"","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/MaxQuestionsReachedErrorDto"}},"application/json":{"schema":{"$ref":"#/components/schemas/MaxQuestionsReachedErrorDto"}}}}},"security":[{"session":[]}],"summary":"Stream next generated question as text. Returns JSON question if pending exists.","tags":["Questions"]}},"/api/questions/{bookId}":{"post":{"operationId":"QuestionController_saveQuestion","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveQuestionDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionReadDto"}}}},"400":{"description":"Book ID is required"}},"security":[{"session":[]}],"tags":["Questions"]}},"/api/questions/stats/{bookId}":{"get":{"operationId":"QuestionController_getStats","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuizStatsResponseDto"}}}},"400":{"description":"Book ID is required"},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Questions"]}},"/api/questions/retake/{bookId}":{"post":{"operationId":"QuestionController_retakeQuiz","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetakeQuizResponseDto"}}}},"400":{"description":"Book ID is required"}},"security":[{"session":[]}],"tags":["Questions"]}},"/api/user-progress/{bookId}":{"get":{"operationId":"UserProgressController_getProgressForBook","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}},{"name":"showIncorrect","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProgressResponseDto"}}}},"400":{"description":"Book ID is required"},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["User Progress"]}},"/api/users/dashboard-stats":{"get":{"operationId":"UserController_getDashboardStats","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardStatsResponseDto"}}}}},"security":[{"session":[]}],"tags":["Users"]}},"/api/users/current_user":{"delete":{"operationId":"UserController_deleteCurrentUser","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponseDto"}}}},"404":{"description":"User not found"}},"security":[{"session":[]}],"tags":["Users"]}},"/api/topic":{"post":{"operationId":"TopicController_createTopic","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTopicDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopicCreateResponseDto"}}}},"400":{"description":"Invalid topic"}},"security":[{"session":[]}],"tags":["Topic"]}},"/api/checkout":{"post":{"operationId":"CheckoutController_createCheckoutSession","parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponseDto"}}}}},"security":[{"session":[]}],"tags":["Checkout"]}},"/api/checkout/success":{"get":{"operationId":"CheckoutController_handleSuccess","parameters":[{"name":"sessionId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects user to frontend after success"},"400":{"description":"Invalid or missing Stripe session"}},"tags":["Checkout"]}},"/api/health":{"get":{"operationId":"HealthController_getHealth","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponseDto"}}}}},"tags":["Health"]}},"/api/quick-start/topics":{"get":{"operationId":"QuickStartController_getTopics","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickStartTopicListResponseDto"}}}}},"security":[{"session":[]}],"tags":["Quick Start"]}},"/api/quick-start/topics/{templateId}/start":{"post":{"operationId":"QuickStartController_startTopic","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickStartTopicStartResponseDto"}}}}},"security":[{"session":[]}],"tags":["Quick Start"]}},"/api/quick-start/topics/{templateId}/dismiss":{"post":{"operationId":"QuickStartController_dismissTopic","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DismissQuickStartTopicDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickStartActionResponseDto"}}}}},"security":[{"session":[]}],"tags":["Quick Start"]}},"/api/mobile-purchases/verify":{"post":{"operationId":"MobilePurchaseController_verify","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMobilePurchaseRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMobilePurchaseResponseDto"}}}},"401":{"description":"Not authenticated"}},"security":[{"session":[]}],"tags":["Mobile Purchases"]}},"/api/review/due":{"get":{"operationId":"ReviewController_getDue","parameters":[{"name":"bookId","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DueReviewsResponseDto"}}}}},"security":[{"session":[]}],"tags":["Review"]}},"/api/review/due/count":{"get":{"operationId":"ReviewController_getDueCount","parameters":[{"name":"bookId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DueCountResponseDto"}}}}},"security":[{"session":[]}],"tags":["Review"]}},"/api/review/schedule/{bookId}":{"get":{"operationId":"ReviewController_getBookSchedule","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookScheduleDto"}}}},"404":{"description":"Book not found"}},"security":[{"session":[]}],"tags":["Review"]}},"/api/review/mute/{bookId}":{"post":{"operationId":"ReviewController_muteBook","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookMuteResponseDto"}}}}},"security":[{"session":[]}],"tags":["Review"]},"delete":{"operationId":"ReviewController_unmuteBook","parameters":[{"name":"bookId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookMuteResponseDto"}}}}},"security":[{"session":[]}],"tags":["Review"]}},"/api/review/preferences":{"get":{"operationId":"ReviewController_getPreferences","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecallPreferencesDto"}}}}},"security":[{"session":[]}],"tags":["Review"]},"patch":{"operationId":"ReviewController_updatePreferences","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRecallPreferencesDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecallPreferencesDto"}}}}},"security":[{"session":[]}],"tags":["Review"]}}},"info":{"title":"Refresher AI API","description":"API documentation for Refresher AI backend","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"schemas":{"BookType":{"type":"string","enum":["book","document","url","topic"]},"CreateBookDto":{"type":"object","properties":{"googleId":{"type":"string"},"authors":{"type":"array","items":{"type":"string"}},"thumbnail":{"type":"string"},"title":{"type":"string"},"pageCount":{"type":"number"},"type":{"allOf":[{"$ref":"#/components/schemas/BookType"}]},"maxNumOfQuestions":{"type":"number"}},"required":["googleId","authors","title","type"]},"BookReadDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"googleId":{"type":"object","nullable":true},"thumbnail":{"type":"object","nullable":true},"authors":{"type":"array","items":{"type":"string"}},"pageCount":{"type":"object","nullable":true},"maxNumOfQuestions":{"type":"object","nullable":true},"filename":{"type":"object","nullable":true},"sourceUrl":{"type":"object","nullable":true},"type":{"allOf":[{"$ref":"#/components/schemas/BookType"}]},"chunks":{"type":"array","items":{"type":"object","additionalProperties":true}},"userIds":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","authors","type","userIds","createdAt","updatedAt"]},"BookWithProgressReadDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"googleId":{"type":"object","nullable":true},"thumbnail":{"type":"object","nullable":true},"authors":{"type":"array","items":{"type":"string"}},"pageCount":{"type":"object","nullable":true},"maxNumOfQuestions":{"type":"object","nullable":true},"filename":{"type":"object","nullable":true},"sourceUrl":{"type":"object","nullable":true},"type":{"allOf":[{"$ref":"#/components/schemas/BookType"}]},"chunks":{"type":"array","items":{"type":"object","additionalProperties":true}},"userIds":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"answeredCount":{"type":"number"},"correctCount":{"type":"number"},"progressPercent":{"type":"number"}},"required":["id","title","authors","type","userIds","createdAt","updatedAt","answeredCount","correctCount","progressPercent"]},"RecentBookReadDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"googleId":{"type":"object","nullable":true},"thumbnail":{"type":"object","nullable":true},"authors":{"type":"array","items":{"type":"string"}},"pageCount":{"type":"object","nullable":true},"maxNumOfQuestions":{"type":"object","nullable":true},"filename":{"type":"object","nullable":true},"sourceUrl":{"type":"object","nullable":true},"type":{"allOf":[{"$ref":"#/components/schemas/BookType"}]},"chunks":{"type":"array","items":{"type":"object","additionalProperties":true}},"userIds":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"answeredCount":{"type":"number"},"correctCount":{"type":"number"},"progressPercent":{"type":"number"}},"required":["id","title","authors","type","userIds","createdAt","updatedAt","answeredCount","correctCount","progressPercent"]},"BookSearchResponseDto":{"type":"object","properties":{"kind":{"type":"string"},"totalItems":{"type":"number"},"items":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"WebpageLookupResponseDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"}},"required":["id","title"]},"WebpageContentDto":{"type":"object","properties":{"title":{"type":"string"},"byline":{"type":"string"},"textContent":{"type":"string","description":"Readable text extracted from the page"}},"required":["textContent"]},"CreateWebpageBookDto":{"type":"object","properties":{"url":{"type":"string","description":"Page URL — stored as reference & dedup key"},"content":{"description":"Extension-extracted content. When absent, the backend fetches the (public) URL and extracts content server-side.","allOf":[{"$ref":"#/components/schemas/WebpageContentDto"}]},"force":{"type":"boolean","description":"Re-add even if this URL was already saved (page changed)"}},"required":["url"]},"WebpageBookResponseDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"existing":{"type":"boolean","description":"True when the URL was already in the library and no new book was created"}},"required":["id","title","existing"]},"BookStatusReadDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","uploading_to_openai","indexing","generating_outline","generating_first_question","ready","failed"]},"statusUpdatedAt":{"type":"object","format":"date-time","nullable":true},"statusError":{"type":"object","nullable":true},"outlineGenerated":{"type":"boolean"},"outlineItemCount":{"type":"number"}},"required":["id","status","outlineGenerated","outlineItemCount"]},"IdResponseDto":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"UploadBookRequestDto":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]},"UploadBookResponseDto":{"type":"object","properties":{"fileUrl":{"type":"string"},"id":{"type":"string"}},"required":["fileUrl","id"]},"QuestionReadDto":{"type":"object","properties":{"id":{"type":"string"},"bookId":{"type":"string"},"question":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"correctAnswer":{"type":"number"},"context":{"type":"object","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","bookId","question","options","correctAnswer","createdAt","updatedAt"]},"SaveAnswerDto":{"type":"object","properties":{"questionId":{"type":"string"},"isCorrect":{"type":"boolean"},"userAnswer":{"type":"number"}},"required":["questionId","isCorrect","userAnswer"]},"EmptyResponseDto":{"type":"object","properties":{}},"InsufficientCreditsErrorDto":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string","example":"INSUFFICIENT_CREDITS"}},"required":["message","code"]},"MaxQuestionsReachedErrorDto":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string","example":"MAX_QUESTIONS_REACHED"}},"required":["message","code"]},"SaveQuestionDto":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"correctAnswer":{"type":"number"},"context":{"type":"string"}},"required":["question","options","correctAnswer","context"]},"QuizStatsResponseDto":{"type":"object","properties":{"successRate":{"type":"number"},"totalCount":{"type":"number"},"wrongCount":{"type":"number"},"correctCount":{"type":"number"},"maxNumOfQuestions":{"type":"number"},"pageCount":{"type":"number"}},"required":["successRate","totalCount","wrongCount","correctCount","maxNumOfQuestions","pageCount"]},"RetakeQuizResponseDto":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"updatedCount":{"type":"number"}},"required":["success","message","updatedCount"]},"UserProgressQuestionDto":{"type":"object","properties":{"id":{"type":"string"},"questionId":{"type":"string"},"question":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"userAnswerIndex":{"type":"number"},"correctAnswerIndex":{"type":"number"},"isCorrect":{"type":"boolean"},"answeredAt":{"type":"string","format":"date-time"}},"required":["id","questionId","question","options","userAnswerIndex","correctAnswerIndex","isCorrect","answeredAt"]},"UserProgressResponseDto":{"type":"object","properties":{"bookId":{"type":"string"},"totalAnswered":{"type":"number"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/UserProgressQuestionDto"}}},"required":["bookId","totalAnswered","questions"]},"DashboardStatsResponseDto":{"type":"object","properties":{"booksCompleted":{"type":"number"},"quizzesTaken":{"type":"number"},"averageScore":{"type":"number"},"streakDays":{"type":"number"}},"required":["booksCompleted","quizzesTaken","averageScore","streakDays"]},"SuccessResponseDto":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"CreateTopicDto":{"type":"object","properties":{"topic":{"type":"string"}},"required":["topic"]},"TopicCreateResponseDto":{"type":"object","properties":{"isValid":{"type":"boolean"},"book":{"$ref":"#/components/schemas/BookReadDto"}},"required":["isValid","book"]},"CheckoutSessionRequestDto":{"type":"object","properties":{"priceId":{"type":"string","description":"Stripe price id for selected credit pack","example":"price_xxx"},"redirectTo":{"type":"string","description":"Where the user should land after a successful or cancelled checkout. Accepts an http(s) URL for web clients, or the mobile custom scheme (e.g. \"refresherai://checkout-success\").","example":"refresherai://checkout-success"}}},"CheckoutSessionResponseDto":{"type":"object","properties":{"sessionId":{"type":"string"},"url":{"type":"object","description":"Direct Stripe Checkout URL — used by mobile clients that open it in the system browser.","nullable":true}},"required":["sessionId"]},"HealthResponseDto":{"type":"object","properties":{"status":{"type":"string","example":"healthy!"}},"required":["status"]},"QuickStartTopicDto":{"type":"object","properties":{"templateId":{"type":"string"},"title":{"type":"string"},"emoji":{"type":"object"}},"required":["templateId","title"]},"QuickStartTopicListResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/QuickStartTopicDto"}}},"required":["items"]},"QuickStartTopicStartResponseDto":{"type":"object","properties":{"bookId":{"type":"string"},"quizUrl":{"type":"string"},"created":{"type":"boolean"}},"required":["bookId","quizUrl","created"]},"DismissQuickStartTopicDto":{"type":"object","properties":{"cooldownDays":{"type":"number","minimum":1,"maximum":90,"default":14}}},"QuickStartActionResponseDto":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"VerifyMobilePurchaseRequestDto":{"type":"object","properties":{"platform":{"type":"string","enum":["ios","android"]},"productId":{"type":"string","example":"refresherai.credits.300"},"transactionId":{"type":"string","description":"Store transaction/order id when available."},"verificationData":{"type":"string","description":"Receipt/token data from the platform purchase object. In production this must be verified with Apple/Google before credits are granted."},"environment":{"type":"string","description":"Testing hint from the mobile app. `storekit_local` is accepted only outside production.","example":"storekit_local"}},"required":["platform","productId"]},"VerifyMobilePurchaseResponseDto":{"type":"object","properties":{"success":{"type":"boolean"},"creditsAdded":{"type":"number"},"totalCredits":{"type":"number"},"alreadyProcessed":{"type":"boolean","description":"True when this transaction had already been processed and no credits were added again."}},"required":["success","creditsAdded","totalCredits","alreadyProcessed"]},"DueReviewDto":{"type":"object","properties":{"cardId":{"type":"string"},"bookId":{"type":"string"},"bookTitle":{"type":"object","nullable":true,"description":"Title of the source book"},"box":{"type":"number","description":"Leitner box (0-4); higher = better retained"},"question":{"$ref":"#/components/schemas/QuestionReadDto"}},"required":["cardId","bookId","bookTitle","box","question"]},"DueReviewsResponseDto":{"type":"object","properties":{"total":{"type":"number"},"reviews":{"type":"array","items":{"$ref":"#/components/schemas/DueReviewDto"}}},"required":["total","reviews"]},"DueCountResponseDto":{"type":"object","properties":{"count":{"type":"number"}},"required":["count"]},"BookScheduleDto":{"type":"object","properties":{"bookId":{"type":"string"},"totalCards":{"type":"number"},"dueCount":{"type":"number"},"matureCount":{"type":"number","description":"Cards in box >= 3 (well retained)"},"nextReviewAt":{"type":"string","nullable":true,"description":"ISO timestamp of the next upcoming review, or null"},"muted":{"type":"boolean","description":"Whether recall emails are muted for this book"}},"required":["bookId","totalCards","dueCount","matureCount","nextReviewAt","muted"]},"BookMuteResponseDto":{"type":"object","properties":{"muted":{"type":"boolean"}},"required":["muted"]},"RecallPreferencesDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"frequency":{"type":"string","enum":["daily","weekly","off"]},"mutedBookIds":{"type":"array","items":{"type":"string"}}},"required":["enabled","frequency","mutedBookIds"]},"UpdateRecallPreferencesDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"frequency":{"type":"string","enum":["daily","weekly","off"]},"mutedBookIds":{"type":"array","items":{"type":"string"}}}}}}}