{"openapi":"3.1.0","info":{"title":"Novarum Scholar API","version":"0.1.0"},"paths":{"/api/auth/login":{"post":{"summary":"Auth Login","description":"Login with email + password. Sets httpOnly JWT cookie on success.","operationId":"auth_login_api_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"post":{"summary":"Auth Logout","description":"Clear the auth cookie.","operationId":"auth_logout_api_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/reset-request":{"post":{"summary":"Auth Reset Request","description":"Send password reset email.","operationId":"auth_reset_request_api_auth_reset_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/reset-confirm":{"post":{"summary":"Auth Reset Confirm","description":"Confirm password reset with token.","operationId":"auth_reset_confirm_api_auth_reset_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetConfirm"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/me":{"get":{"summary":"Auth Me","description":"Return current subscriber info from JWT.","operationId":"auth_me_api_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/validate-invite":{"post":{"summary":"Validate Invite","description":"Check if an invite code is valid before the user completes signup.","operationId":"validate_invite_api_validate_invite_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/subscribe":{"post":{"summary":"Subscribe","operationId":"subscribe_api_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/announcement":{"get":{"summary":"Get Announcement","description":"Used by scheduler to inject announcement into digest emails.","operationId":"get_announcement_api_announcement_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/create-checkout":{"post":{"summary":"Create Checkout","description":"Create a Stripe Checkout session for paid tier upgrades.","operationId":"create_checkout_api_create_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe-webhook":{"post":{"summary":"Stripe Webhook","description":"Receive and process Stripe webhook events.","operationId":"stripe_webhook_api_stripe_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/invite-codes":{"get":{"summary":"Admin List Codes","operationId":"admin_list_codes_admin_invite_codes_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Admin Create Code","operationId":"admin_create_code_admin_invite_codes_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/invite-codes/{code}":{"delete":{"summary":"Admin Deactivate Code","operationId":"admin_deactivate_code_admin_invite_codes__code__delete","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/invite-codes/seed":{"post":{"summary":"Admin Seed Codes","operationId":"admin_seed_codes_admin_invite_codes_seed_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/subscribers":{"get":{"summary":"Admin List Subscribers","operationId":"admin_list_subscribers_admin_subscribers_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/subscribers/{sub_id}":{"patch":{"summary":"Admin Update Subscriber","operationId":"admin_update_subscriber_admin_subscribers__sub_id__patch","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"integer","title":"Sub Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Delete Subscriber","operationId":"admin_delete_subscriber_admin_subscribers__sub_id__delete","parameters":[{"name":"sub_id","in":"path","required":true,"schema":{"type":"integer","title":"Sub Id"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stats":{"get":{"summary":"Admin Stats","operationId":"admin_stats_admin_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/announcement":{"post":{"summary":"Admin Set Announcement","description":"Note: this updates the in-memory value only. For persistence set ANNOUNCEMENT env var on Render.","operationId":"admin_set_announcement_admin_announcement_post","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/lookup":{"post":{"summary":"Account Lookup","description":"Get subscriber details — JWT auth required.","operationId":"account_lookup_api_account_lookup_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/account/update":{"patch":{"summary":"Account Update","description":"Update keywords and/or schedule — JWT auth required.","operationId":"account_update_api_account_update_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/keyword-config":{"patch":{"summary":"Update Kw Config","description":"Update advanced keyword config — JWT auth required.","operationId":"update_kw_config_api_account_keyword_config_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordConfigRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/cancel":{"post":{"summary":"Account Cancel","description":"Cancel a subscription — JWT auth required.","operationId":"account_cancel_api_account_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/account/cancel-survey":{"post":{"summary":"Account Cancel Survey","description":"Save cancellation survey response — JWT auth required.","operationId":"account_cancel_survey_api_account_cancel_survey_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSurveyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track/open":{"get":{"summary":"Track Open","description":"Email open tracking pixel.","operationId":"track_open_track_open_get","parameters":[{"name":"eid","in":"query","required":false,"schema":{"type":"string","default":"","title":"Eid"}},{"name":"sid","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track/click":{"get":{"summary":"Track Click","description":"Click tracking redirect. Only allows destinations on the academic publisher allowlist.","operationId":"track_click_track_click_get","parameters":[{"name":"url","in":"query","required":false,"schema":{"type":"string","default":"","title":"Url"}},{"name":"eid","in":"query","required":false,"schema":{"type":"string","default":"","title":"Eid"}},{"name":"sid","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Sid"}},{"name":"kw","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kw"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referral/me":{"get":{"summary":"Get Referral Link","description":"Get or create a referral code for the authenticated subscriber.","operationId":"get_referral_link_api_referral_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/account/authors":{"get":{"summary":"Get Authors","description":"Get followed authors — JWT auth required.","operationId":"get_authors_api_account_authors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Follow Author","description":"Follow an author — JWT auth required.","operationId":"follow_author_api_account_authors_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorNameRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Unfollow Author","description":"Unfollow an author — JWT auth required.","operationId":"unfollow_author_api_account_authors_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorNameRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/change-password":{"post":{"summary":"Account Change Password","description":"Change password — requires current password and valid JWT.","operationId":"account_change_password_api_account_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/slack":{"post":{"summary":"Account Slack","description":"Save or remove Slack webhook URL for subscriber.","operationId":"account_slack_api_account_slack_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackWebhookRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/notion":{"post":{"summary":"Account Notion","description":"Save or remove Notion API key + database ID for subscriber.","operationId":"account_notion_api_account_notion_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotionCredentialsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/save-notion":{"get":{"summary":"Api Save Notion","description":"Save an article to the subscriber's Notion database.\nGET (from email link): authenticated by a short-lived signed token (t=<token>).\nPOST (from frontend): authenticated by JWT cookie.","operationId":"api_save_notion_api_save_notion_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Api Save Notion","description":"Save an article to the subscriber's Notion database.\nGET (from email link): authenticated by a short-lived signed token (t=<token>).\nPOST (from frontend): authenticated by JWT cookie.","operationId":"api_save_notion_api_save_notion_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/save-paper":{"post":{"summary":"Api Save Paper","description":"Save a paper for citation tracking — JWT auth required.","operationId":"api_save_paper_api_save_paper_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavePaperAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/feedback":{"post":{"summary":"Api Feedback","operationId":"api_feedback_api_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/summary-cache/{doi_encoded}":{"delete":{"summary":"Admin Invalidate Summary","description":"Manually invalidate a cached summary by DOI. Forces re-summarization next run.","operationId":"admin_invalidate_summary_admin_summary_cache__doi_encoded__delete","parameters":[{"name":"doi_encoded","in":"path","required":true,"schema":{"type":"string","title":"Doi Encoded"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/summary-cache/stats":{"get":{"summary":"Admin Cache Stats","description":"Show summary cache size and recent entries.","operationId":"admin_cache_stats_admin_summary_cache_stats_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/analytics":{"get":{"summary":"Admin Analytics","operationId":"admin_analytics_admin_analytics_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/audit-log":{"get":{"summary":"Admin Audit Log","description":"Return last N admin actions for audit purposes.","operationId":"admin_audit_log_admin_audit_log_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rate-digest":{"get":{"summary":"Rate Digest","description":"Handle 1-5 star digest rating click from email. Returns branded thank-you HTML page.","operationId":"rate_digest_rate_digest_get","parameters":[{"name":"email_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Email Id"}},{"name":"rating","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Rating"}},{"name":"sub","in":"query","required":false,"schema":{"type":"string","default":"","title":"Sub"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/keyword-preview":{"get":{"summary":"Keyword Preview","description":"Return count + sample titles for a keyword from multiple sources (last 30 days).","operationId":"keyword_preview_api_keyword_preview_get","parameters":[{"name":"keyword","in":"query","required":false,"schema":{"type":"string","default":"","title":"Keyword"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/pause-digest":{"post":{"summary":"Pause Digest","description":"Pause digest delivery for 1 or 2 weeks. JWT auth required.","operationId":"pause_digest_pause_digest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/unpause-digest":{"post":{"summary":"Unpause Digest","description":"Resume digest delivery. JWT auth required.","operationId":"unpause_digest_unpause_digest_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/pause-status":{"get":{"summary":"Pause Status","description":"Return current pause status for the authenticated subscriber.","operationId":"pause_status_pause_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/export-csv":{"get":{"summary":"Admin Export Csv","description":"Export all subscribers as CSV. Requires X-Admin-Key header.","operationId":"admin_export_csv_admin_export_csv_get","parameters":[{"name":"x-admin-key","in":"header","required":false,"schema":{"type":"string","default":"","title":"X-Admin-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/unsubscribe":{"post":{"summary":"Unsubscribe","description":"Handles both GET (from email link) and POST (RFC 8058 List-Unsubscribe-Post).\nGET requests MUST include a valid per-subscriber unsubscribe token (token=).\nPOST requests (RFC 8058 one-click) are verified by token or email+token in the body.","operationId":"unsubscribe_unsubscribe_post","parameters":[{"name":"email","in":"query","required":false,"schema":{"type":"string","default":"","title":"Email"}},{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Unsubscribe","description":"Handles both GET (from email link) and POST (RFC 8058 List-Unsubscribe-Post).\nGET requests MUST include a valid per-subscriber unsubscribe token (token=).\nPOST requests (RFC 8058 one-click) are verified by token or email+token in the body.","operationId":"unsubscribe_unsubscribe_get","parameters":[{"name":"email","in":"query","required":false,"schema":{"type":"string","default":"","title":"Email"}},{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/webhook/bounce":{"post":{"summary":"Webhook Bounce","description":"Accepts bounce/complaint notifications from Resend (or any webhook-capable ESP).\nBody: {\"email\": \"...\", \"type\": \"bounce\" | \"complaint\"}\nSecured by X-Webhook-Secret header matching BOUNCE_WEBHOOK_SECRET env var.","operationId":"webhook_bounce_webhook_bounce_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me/keyword-stats":{"get":{"summary":"Api Keyword Stats","description":"Return per-keyword article counts from sent_articles table.","operationId":"api_keyword_stats_api_me_keyword_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me/digests":{"get":{"summary":"Api Digest History","description":"Return last 50 digest sends + next scheduled delivery time.","operationId":"api_digest_history_api_me_digests_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me/suggestions":{"get":{"summary":"Api Get Suggestions","description":"Return the latest keyword suggestions for the authenticated subscriber.","operationId":"api_get_suggestions_api_me_suggestions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me/activate-trial":{"post":{"summary":"Api Activate Trial","description":"Activate a 7-day no-card Scholar trial for free subscribers.","operationId":"api_activate_trial_api_me_activate_trial_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/digest/{email_id}":{"get":{"summary":"View Digest","description":"Public endpoint: render a stored digest HTML by email_id.","operationId":"view_digest_digest__email_id__get","parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/me/trial-status":{"get":{"summary":"Api Trial Status","description":"Return trial status for the authenticated subscriber.","operationId":"api_trial_status_api_me_trial_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/save":{"get":{"summary":"Save Paper Via Email","description":"One-click save from email digest. Token is base64-encoded subscriber email.","operationId":"save_paper_via_email_save_get","parameters":[{"name":"t","in":"query","required":true,"schema":{"type":"string","title":"T"}},{"name":"doi","in":"query","required":true,"schema":{"type":"string","title":"Doi"}},{"name":"title","in":"query","required":false,"schema":{"type":"string","default":"","title":"Title"}},{"name":"link","in":"query","required":false,"schema":{"type":"string","default":"","title":"Link"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/library/save":{"post":{"summary":"Library Save","operationId":"library_save_api_library_save_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/library":{"get":{"summary":"Library Get","operationId":"library_get_api_library_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/library/{paper_id}":{"delete":{"summary":"Library Delete","operationId":"library_delete_api_library__paper_id__delete","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"integer","title":"Paper Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Library Update","operationId":"library_update_api_library__paper_id__patch","parameters":[{"name":"paper_id","in":"path","required":true,"schema":{"type":"integer","title":"Paper Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reader/annotations":{"get":{"summary":"Reader Get Annotations","operationId":"reader_get_annotations_api_reader_annotations_get","parameters":[{"name":"doi","in":"query","required":true,"schema":{"type":"string","title":"Doi"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Reader Save Annotation","operationId":"reader_save_annotation_api_reader_annotations_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/reader/annotations/{ann_id}":{"delete":{"summary":"Reader Delete Annotation","operationId":"reader_delete_annotation_api_reader_annotations__ann_id__delete","parameters":[{"name":"ann_id","in":"path","required":true,"schema":{"type":"integer","title":"Ann Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Reader Update Annotation","operationId":"reader_update_annotation_api_reader_annotations__ann_id__patch","parameters":[{"name":"ann_id","in":"path","required":true,"schema":{"type":"integer","title":"Ann Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/library/export":{"get":{"summary":"Library Export","description":"Export saved papers as BibTeX or RIS.","operationId":"library_export_api_library_export_get","parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"bibtex","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/share-token":{"get":{"summary":"Get My Share Token","description":"Return the subscriber's share token for generating a shareable digest link.","operationId":"get_my_share_token_api_account_share_token_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/shared/{token}":{"get":{"summary":"Get Shared Digest","description":"Public endpoint: return the most recent digest articles for a subscriber\nidentified by their share token. No auth required. Read-only.","operationId":"get_shared_digest_api_shared__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/trending":{"get":{"summary":"Get Trending Endpoint","description":"Public: return currently trending research keywords across Novarum subscribers.","operationId":"get_trending_endpoint_api_trending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/reader/pdf":{"get":{"summary":"Proxy Pdf","description":"Proxy an open-access PDF via Unpaywall for same-origin PDF.js rendering.","operationId":"proxy_pdf_api_reader_pdf_get","parameters":[{"name":"doi","in":"query","required":true,"schema":{"type":"string","title":"Doi"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AccountUpdateRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"keywords":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Keywords"},"schedule":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Schedule"},"delivery_hour":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delivery Hour"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"instant_alerts_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Instant Alerts Enabled"}},"type":"object","required":["email"],"title":"AccountUpdateRequest"},"AuthorNameRequest":{"properties":{"author_name":{"type":"string","title":"Author Name"}},"type":"object","required":["author_name"],"title":"AuthorNameRequest"},"CancelSurveyRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"reason":{"type":"string","title":"Reason"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","default":""}},"type":"object","required":["email","reason"],"title":"CancelSurveyRequest"},"ChangePasswordRequest":{"properties":{"current_password":{"type":"string","maxLength":500,"title":"Current Password"},"new_password":{"type":"string","maxLength":500,"title":"New Password"}},"type":"object","required":["current_password","new_password"],"title":"ChangePasswordRequest"},"CheckoutRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"tier":{"type":"string","title":"Tier"},"success_url":{"type":"string","title":"Success Url","default":"https://novarumscholar.com/signup?success=1"},"cancel_url":{"type":"string","title":"Cancel Url","default":"https://novarumscholar.com/pricing"}},"type":"object","required":["email","tier"],"title":"CheckoutRequest"},"FeedbackRequest":{"properties":{"subscriber_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subscriber Id"},"eid":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Eid","default":""},"doi":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Doi","default":""},"vote":{"type":"string","maxLength":20,"title":"Vote"},"reason":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Reason","default":""},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment","default":""}},"type":"object","required":["vote"],"title":"FeedbackRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InviteCodeRequest":{"properties":{"code":{"type":"string","title":"Code"},"tier":{"type":"string","title":"Tier","default":"researcher"},"max_uses":{"type":"integer","title":"Max Uses","default":50},"note":{"type":"string","title":"Note","default":""},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["code"],"title":"InviteCodeRequest"},"KeywordConfigRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"keyword":{"type":"string","maxLength":200,"title":"Keyword"},"exclusions":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":30},{"type":"null"}],"title":"Exclusions"},"or_terms":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":30},{"type":"null"}],"title":"Or Terms"},"preferred_journals":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":30},{"type":"null"}],"title":"Preferred Journals"},"lookback_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":0.0},{"type":"null"}],"title":"Lookback Days"},"include_methods":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Include Methods"},"exclude_methods":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Exclude Methods"}},"type":"object","required":["email","keyword"],"title":"KeywordConfigRequest"},"LoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","maxLength":500,"title":"Password"}},"type":"object","required":["email","password"],"title":"LoginRequest"},"NotionCredentialsRequest":{"properties":{"api_key":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Api Key","default":""},"database_id":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Database Id","default":""}},"type":"object","title":"NotionCredentialsRequest"},"PasswordResetConfirm":{"properties":{"token":{"type":"string","maxLength":200,"title":"Token"},"password":{"type":"string","maxLength":500,"title":"Password"}},"type":"object","required":["token","password"],"title":"PasswordResetConfirm"},"PasswordResetRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"PasswordResetRequest"},"PauseRequest":{"properties":{"weeks":{"type":"integer","title":"Weeks"}},"type":"object","required":["weeks"],"title":"PauseRequest"},"SavePaperAuthRequest":{"properties":{"doi":{"type":"string","title":"Doi"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","default":""}},"type":"object","required":["doi"],"title":"SavePaperAuthRequest"},"SlackWebhookRequest":{"properties":{"webhook_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Webhook Url","default":""}},"type":"object","title":"SlackWebhookRequest"},"SubscribeRequest":{"properties":{"name":{"type":"string","maxLength":200,"title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"tier":{"type":"string","maxLength":20,"title":"Tier","default":"free"},"keywords":{"items":{"type":"string"},"type":"array","maxItems":15,"title":"Keywords"},"schedule":{"items":{"type":"string"},"type":"array","maxItems":7,"title":"Schedule"},"invite_code":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Invite Code"},"field_of_study":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Field Of Study"},"password":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Password"},"delivery_hour":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delivery Hour","default":9},"timezone":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Timezone","default":"UTC"},"instant_alerts_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Instant Alerts Enabled","default":false}},"type":"object","required":["name","email","keywords","schedule"],"title":"SubscribeRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}