{"openapi":"3.1.0","info":{"title":"SV Students Recommend API","description":"Practice REST API for SV College students.\n\n**Base URL:** `https://sv-students-recommend.onrender.com`\n\nUse the **POST /auth/login** endpoint to get your Bearer token, then click **Authorize** above to authenticate protected endpoints.","version":"1.0.0"},"paths":{"/auth/register":{"post":{"tags":["Auth"],"summary":"Register a new user account","description":"Create a new account with name, email, and password.\n\n- **name**: Display name shown on comments\n- **email**: Must be a valid email address (unique per account)\n- **password**: Minimum 4 English characters","operationId":"register_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegister"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Log in and receive a Bearer token","description":"Authenticate with email and password.\n\nReturns an **access_token** — copy it to use as your Bearer token\nin protected endpoints or on the Profile page.","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLogin"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"401":{"description":"Invalid email or password."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/recover":{"post":{"tags":["Auth"],"summary":"Send a password reset email","description":"Triggers Supabase to send a password-reset email to the given address.","operationId":"request_password_reset_auth_recover_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/recommendations":{"get":{"tags":["Recommendations"],"summary":"List all recommendations","description":"Returns all recommendations, newest first.\nOptionally filter by **category**: Book, Movie, Series, Activity, Other.","operationId":"list_recommendations_api_recommendations_get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by category","title":"Category"},"description":"Filter by category"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecommendationOut"},"title":"Response List Recommendations Api Recommendations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Recommendations"],"summary":"Create a new recommendation","description":"Create a recommendation. Requires **Bearer token** in the Authorization header.\n\nSend as `multipart/form-data` to include an optional image upload.","operationId":"create_recommendation_api_recommendations_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_recommendation_api_recommendations_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/recommendations/{rec_id}":{"get":{"tags":["Recommendations"],"summary":"Get a single recommendation","operationId":"get_recommendation_api_recommendations__rec_id__get","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Recommendations"],"summary":"Update your recommendation","description":"Update a recommendation you own. Requires **Bearer token**.\nOnly the fields you provide will be updated.","operationId":"update_recommendation_api_recommendations__rec_id__put","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Recommendations"],"summary":"Delete your recommendation","description":"Delete a recommendation you own. Requires **Bearer token**.\nAlso removes the associated image from storage.","operationId":"delete_recommendation_api_recommendations__rec_id__delete","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/recommendations/{rec_id}/comments":{"get":{"tags":["Comments"],"summary":"Get comments for a recommendation","description":"Returns all comments and star ratings for the given recommendation.","operationId":"get_comments_api_recommendations__rec_id__comments_get","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CommentOut"},"title":"Response Get Comments Api Recommendations  Rec Id  Comments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Comments"],"summary":"Add a comment and star rating","description":"Post a comment with a star rating (1–5) on a recommendation.\nRequires **Bearer token**. The commenter's name is taken from their profile.","operationId":"add_comment_api_recommendations__rec_id__comments_post","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/recommendations/{rec_id}/comments/{comment_id}":{"delete":{"tags":["Comments"],"summary":"Delete a comment","description":"Delete a comment. Only the comment's author or an admin may delete it.\nReturns 204 No Content on success.","operationId":"delete_comment_api_recommendations__rec_id__comments__comment_id__delete","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"string","title":"Rec Id"}},{"name":"comment_id","in":"path","required":true,"schema":{"type":"string","title":"Comment Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/profile/me":{"get":{"tags":["Profile"],"summary":"Get current user profile","description":"Returns the authenticated user's profile information.","operationId":"get_profile_api_profile_me_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Profile"],"summary":"Delete your own account","description":"Permanently deletes the authenticated user's account and profile.","operationId":"delete_profile_api_profile_me_delete","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/profile/password":{"put":{"tags":["Profile"],"summary":"Change your password","description":"Updates the authenticated user's password.","operationId":"change_password_api_profile_password_put","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChange"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/profile/token":{"get":{"tags":["Profile"],"summary":"Get your current Bearer token","description":"Returns your current Bearer token.\n\nThis endpoint is provided for API practice — students can call this\nto retrieve their token programmatically, or simply copy it from the\nProfile page in the web UI.","operationId":"get_token_api_profile_token_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users":{"get":{"tags":["Admin"],"summary":"List all users (admin only)","operationId":"list_users_api_admin_users_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/{user_id}/ban":{"post":{"tags":["Admin"],"summary":"Ban a user (admin only)","operationId":"ban_user_api_admin_users__user_id__ban_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/{user_id}/unban":{"post":{"tags":["Admin"],"summary":"Unban a user (admin only)","operationId":"unban_user_api_admin_users__user_id__unban_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/blacklist":{"get":{"tags":["Admin"],"summary":"List blacklisted emails (admin only)","operationId":"list_blacklist_api_admin_blacklist_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Admin"],"summary":"Add email to blacklist (admin only)","operationId":"add_blacklist_api_admin_blacklist_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_blacklist_api_admin_blacklist_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/blacklist/{entry_id}":{"delete":{"tags":["Admin"],"summary":"Remove email from blacklist (admin only)","operationId":"remove_blacklist_api_admin_blacklist__entry_id__delete","parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","title":"Entry Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/settings":{"get":{"tags":["Admin"],"summary":"Get system settings (admin only)","operationId":"get_settings_endpoint_api_admin_settings_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/settings/{key}":{"put":{"tags":["Admin"],"summary":"Update a system setting (admin only)","operationId":"update_setting_api_admin_settings__key__put","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_update_setting_api_admin_settings__key__put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cart":{"get":{"tags":["Cart"],"summary":"Get current user's cart","operationId":"get_cart_api_cart_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Cart"],"summary":"Save current user's cart","operationId":"save_cart_api_cart_put","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_add_blacklist_api_admin_blacklist_post":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"Body_add_blacklist_api_admin_blacklist_post"},"Body_create_recommendation_api_recommendations_post":{"properties":{"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category","default":"Movie"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"recommender_name":{"type":"string","title":"Recommender Name"},"website_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Link"},"image":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Image"}},"type":"object","required":["name","recommender_name"],"title":"Body_create_recommendation_api_recommendations_post"},"Body_update_setting_api_admin_settings__key__put":{"properties":{"value":{"type":"string","title":"Value"}},"type":"object","required":["value"],"title":"Body_update_setting_api_admin_settings__key__put"},"CartBody":{"properties":{"items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"CartBody"},"CommentCreate":{"properties":{"rating":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Rating","description":"Star rating from 1 to 5"},"comment_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment Text"}},"type":"object","required":["rating"],"title":"CommentCreate"},"CommentOut":{"properties":{"id":{"type":"string","title":"Id"},"recommendation_id":{"type":"string","title":"Recommendation Id"},"commenter_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commenter Id"},"commenter_name":{"type":"string","title":"Commenter Name"},"rating":{"type":"integer","title":"Rating"},"comment_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment Text"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","recommendation_id","commenter_name","rating","comment_text","created_at"],"title":"CommentOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PasswordChange":{"properties":{"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["new_password"],"title":"PasswordChange"},"PasswordResetRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"redirect_to":{"type":"string","title":"Redirect To","default":""}},"type":"object","required":["email"],"title":"PasswordResetRequest"},"RecommendationOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url"},"website_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Link"},"recommender_name":{"type":"string","title":"Recommender Name"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"},"comment_count":{"type":"integer","title":"Comment Count","default":0}},"type":"object","required":["id","name","category","description","image_url","website_link","recommender_name","created_by","created_at","updated_at"],"title":"RecommendationOut"},"RecommendationUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"category":{"anyOf":[{"type":"string","enum":["Book","Movie","Series","Activity","Other"]},{"type":"null"}],"title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"recommender_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recommender Name"},"website_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Link"}},"type":"object","title":"RecommendationUpdate"},"UserLogin":{"properties":{"email":{"type":"string","title":"Email","default":""},"password":{"type":"string","title":"Password","default":""}},"type":"object","title":"UserLogin"},"UserOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"access_token":{"type":"string","title":"Access Token"}},"type":"object","required":["id","name","email","access_token"],"title":"UserOut"},"UserRegister":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["name","email","password"],"title":"UserRegister"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}