{"info":{"_postman_id":"b2c12ab7-f3de-449b-a453-a08c4569ab83","name":"Social Media App","description":"<html><head></head><body><p>Social Media App API Documentation</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"49715513","collectionId":"b2c12ab7-f3de-449b-a453-a08c4569ab83","publishedId":"2sBXqKq1Tv","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-05-04T16:33:54.000Z"},"item":[{"name":"Auth","item":[{"name":"Signup","id":"c82c8727-e7b8-45de-a7f6-ddb2e0db6b7b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userName\": \"Diaa Eldeen\",\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"password123\",\n  \"rePassword\": \"password123\",\n  \"age\": 23,\n  \"phone\": \"01278396490\",\n  \"address\": \"Alexandria\",\n  \"gender\": \"male\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup","description":"<p>Register a new user account.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>userName</td>\n<td>string</td>\n<td>Yes</td>\n<td>3-50 chars. Internally split into firstName + lastName via virtual</td>\n</tr>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>Valid email. Must be unique</td>\n</tr>\n<tr>\n<td>password</td>\n<td>string</td>\n<td>Yes</td>\n<td>Min 8 characters</td>\n</tr>\n<tr>\n<td>rePassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Must match password</td>\n</tr>\n<tr>\n<td>age</td>\n<td>number</td>\n<td>Yes</td>\n<td>18-100</td>\n</tr>\n<tr>\n<td>phone</td>\n<td>string</td>\n<td>No</td>\n<td>Stored encrypted (AES-256)</td>\n</tr>\n<tr>\n<td>address</td>\n<td>string</td>\n<td>No</td>\n<td></td>\n</tr>\n<tr>\n<td>gender</td>\n<td>string</td>\n<td>No</td>\n<td>\"male\" or \"female\". Default: \"male\"</td>\n</tr>\n</tbody>\n</table>\n</div><p>On success: sends OTP confirmation email. OTP expires in 2 minutes. Max 3 OTP attempts within 5 minutes.</p>\n","urlObject":{"path":["auth","signup"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"8ccc51f5-3f17-4107-9244-b4ba0cec6da8","name":"Signup - Success","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userName\": \"Diaa Eldeen\",\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"password123\",\n  \"rePassword\": \"password123\",\n  \"age\": 23,\n  \"phone\": \"01278396490\",\n  \"address\": \"Alexandria\",\n  \"gender\": \"male\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Signup Success\",\n  \"data\": {\n    \"_id\": \"664f1a2b3c4d5e6f7a8b9c0d\",\n    \"firstName\": \"Diaa\",\n    \"lastName\": \"Eldeen\",\n    \"userName\": \"Diaa Eldeen\",\n    \"email\": \"diaaelseady@gmail.com\",\n    \"age\": 23,\n    \"phone\": \"encrypted_string\",\n    \"address\": \"Alexandria\",\n    \"gender\": \"male\",\n    \"role\": \"user\",\n    \"provider\": \"local\",\n    \"confirmed\": false,\n    \"createdAt\": \"2026-01-01T00:00:00.000Z\",\n    \"updatedAt\": \"2026-01-01T00:00:00.000Z\"\n  }\n}"},{"id":"0a973dac-d323-40b2-9b36-6bcc3c9e942f","name":"Signup - Email Already Exists","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userName\": \"Diaa Eldeen\",\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"password123\",\n  \"rePassword\": \"password123\",\n  \"age\": 23\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup"},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Email Already Exist\",\n  \"status\": 409\n}"},{"id":"08843234-2846-4fa8-9a2b-010a2de4410c","name":"Signup - Validation Error","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"not-an-email\",\n  \"password\": \"123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": {\n    \"message\": \"Validation Error\",\n    \"errors\": [\n      { \"field\": \"email\", \"message\": \"Invalid email format\" },\n      { \"field\": \"password\", \"message\": \"Password must be at least 8 characters\" }\n    ]\n  },\n  \"status\": 400\n}"}],"_postman_id":"c82c8727-e7b8-45de-a7f6-ddb2e0db6b7b"},{"name":"Signup With Gmail","id":"06aab6ac-e240-44e6-a13d-472a622c54ef","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"idToken\": \"google_id_token_here\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/gmail","description":"<p>Register or login using a Google account.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>idToken</td>\n<td>string</td>\n<td>Yes</td>\n<td>Google ID token obtained from Google Sign-In on the client</td>\n</tr>\n</tbody>\n</table>\n</div><p>If the email already exists with provider \"local\", the request will be rejected.\nIf the user does not exist, a new account is created with provider \"google\" and confirmed = true.\nReturns a JWT token (1h expiry).</p>\n","urlObject":{"path":["auth","signup","gmail"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"e3b88c4d-c4e0-4aec-b743-21f76513133d","name":"Signup With Gmail - Success","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"idToken\": \"google_id_token_here\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/gmail"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"LogIn Succefully\",\n  \"data\": {\n    \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n  }\n}"},{"id":"42ce22ea-e304-4deb-97cd-3a087e1faf59","name":"Signup With Gmail - Local Account Exists","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"idToken\": \"google_id_token_here\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/gmail"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Please Log In In System Only\",\n  \"status\": 400\n}"}],"_postman_id":"06aab6ac-e240-44e6-a13d-472a622c54ef"},{"name":"Confirm Email","id":"32f43760-4b36-48ff-b557-fdd995f48d4f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"123456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/confirm-email","description":"<p>Confirm the user's email after signup using the OTP sent to their email.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>The email used during signup</td>\n</tr>\n<tr>\n<td>otp</td>\n<td>string</td>\n<td>Yes</td>\n<td>Exactly 6 characters. Received via email. Expires in 2 minutes</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["auth","signup","confirm-email"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"030a561a-45b4-4788-967d-d3d5fa72cee7","name":"Confirm Email - Success","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"123456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/confirm-email"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Email confirmed Succefully!\",\n  \"data\": {}\n}"},{"id":"cbb59d68-c115-48e2-b0ca-066392ffda0b","name":"Confirm Email - OTP Expired","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"123456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/confirm-email"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Otp Expired\",\n  \"status\": 500\n}"},{"id":"5091566e-6c33-4a20-9325-6f0b840f8be0","name":"Confirm Email - Invalid OTP","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"000000\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/confirm-email"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid Otp\",\n  \"status\": 500\n}"}],"_postman_id":"32f43760-4b36-48ff-b557-fdd995f48d4f"},{"name":"Resend OTP","id":"23718944-93c8-4782-98ed-9a3ff9c72d5e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/resend_otp","description":"<p>Resend the email confirmation OTP.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>The email used during signup</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>OTP Rate Limiting:</strong></p>\n<ul>\n<li>OTP expires in 2 minutes. Cannot resend before it expires.</li>\n<li>Max 3 attempts within 5 minutes.</li>\n<li>After 3 failed attempts, the email is blocked for 5 minutes.</li>\n</ul>\n","urlObject":{"path":["auth","signup","resend_otp"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"3be67280-e4a8-4fa6-b9a3-52f786a838b7","name":"Resend OTP - Success","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/resend_otp"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Otp Resend Succefully!\",\n  \"data\": {}\n}"},{"id":"6b3bb1de-6180-4b53-89f7-5d2d31e5e6c5","name":"Resend OTP - Still Active","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/resend_otp"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"You Can Resend Otp After 90 Second\",\n  \"status\": 500\n}"},{"id":"81899282-f579-404d-960c-c1749175ee65","name":"Resend OTP - Blocked","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signup/resend_otp"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"You Have Exceeded The Max Number Of Tries\",\n  \"status\": 500\n}"}],"_postman_id":"23718944-93c8-4782-98ed-9a3ff9c72d5e"},{"name":"Signin","event":[{"listen":"test","script":{"exec":["const res = pm.response.json();","if (res.data && res.data.token) {","  pm.collectionVariables.set('token', res.data.token);","}","if (res.data && res.data.refreshToken) {","  pm.collectionVariables.set('refreshToken', res.data.refreshToken);","}"],"type":"text/javascript","id":"0a02237e-32fa-4d73-9cf2-c6e93997a8c7"}}],"id":"0aa813b0-1f8e-480c-9e1e-5bf4413718cc","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"password123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signin","description":"<p>Login with email and password.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>Valid email</td>\n</tr>\n<tr>\n<td>password</td>\n<td>string</td>\n<td>Yes</td>\n<td>Min 8 characters</td>\n</tr>\n</tbody>\n</table>\n</div><p>User must be confirmed (email verified) and provider must be \"local\".\nReturns <code>token</code> (1h expiry) and <code>refreshToken</code> (1 year expiry).</p>\n<blockquote>\n<p>The test script auto-saves <code>token</code> and <code>refreshToken</code> into collection variables.</p>\n</blockquote>\n","urlObject":{"path":["auth","signin"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"09d5eaf7-f430-4ac7-9901-03024b798015","name":"Signin - Success","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"password123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signin"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"LogIn Succefully\",\n  \"data\": {\n    \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n    \"refreshToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n  }\n}"},{"id":"84116ac5-fb1b-4c3f-a80b-9796af872e6b","name":"Signin - User Not Found or Not Confirmed","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"notfound@example.com\",\n  \"password\": \"password123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signin"},"status":"Conflict","code":409,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"User Not Exist Or Not Confirmed Yet !\",\n  \"status\": 409\n}"},{"id":"f7813c3c-c6ee-4225-a555-6842ec68b9aa","name":"Signin - Invalid Password","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"password\": \"wrongpassword\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/signin"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid Password\",\n  \"status\": 400\n}"}],"_postman_id":"0aa813b0-1f8e-480c-9e1e-5bf4413718cc"},{"name":"Refresh Token","event":[{"listen":"test","script":{"exec":["const res = pm.response.json();","if (res.data) {","  pm.collectionVariables.set('token', res.data);","}"],"type":"text/javascript","id":"61c748b6-b06b-4e3e-b52e-f084878d27fa"}}],"id":"cf00e7a7-d2ea-4e42-ab48-b2d2de53ed86","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"refreshtoken","value":"","description":"<p>The refresh token received from signin</p>\n"}],"url":"http://localhost:3000/auth/refreshToken","description":"<p>Get a new access token using the refresh token.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>refreshtoken</td>\n<td>string</td>\n<td>Yes</td>\n<td>The refresh token from signin (all lowercase key)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Returns a new <code>token</code> with 1h expiry.</p>\n<blockquote>\n<p>The test script auto-saves the new <code>token</code> into collection variables.</p>\n</blockquote>\n","urlObject":{"path":["auth","refreshToken"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"4ab9b5af-049b-4445-8b39-a73db251a4fd","name":"Refresh Token - Success","originalRequest":{"method":"GET","header":[{"key":"refreshtoken","value":""}],"url":"http://localhost:3000/auth/refreshToken"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n}"},{"id":"b343af7a-ce7d-48af-96ba-8e8519786eda","name":"Refresh Token - Token Not Provided","originalRequest":{"method":"GET","header":[],"url":"http://localhost:3000/auth/refreshToken"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Token Not Provided\",\n  \"status\": 401\n}"}],"_postman_id":"cf00e7a7-d2ea-4e42-ab48-b2d2de53ed86"},{"name":"Forget Password","id":"bb9b075a-8098-4b20-91b4-bd672ddbee96","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/forgetPassword","description":"<p>Send an OTP to the user's email to start the password reset flow.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>Must belong to a confirmed local account</td>\n</tr>\n</tbody>\n</table>\n</div><p>OTP expires in 2 minutes. Subject to the same rate limiting as Resend OTP (max 3 attempts, blocked for 5 minutes after exceeding).</p>\n<p><strong>Full Reset Flow:</strong> Forget Password -&gt; Confirm Password (verify OTP) -&gt; Reset Password</p>\n","urlObject":{"path":["auth","forgetPassword"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"7ce64735-c45b-42a3-99f4-c68a1b28b662","name":"Forget Password - Success","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/forgetPassword"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Otp Send Succefully\",\n  \"data\": {}\n}"},{"id":"eb823124-7c36-4417-aced-8779b55bb3fb","name":"Forget Password - User Not Found","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"notfound@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/forgetPassword"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"User Not Exist\",\n  \"status\": 500\n}"}],"_postman_id":"bb9b075a-8098-4b20-91b4-bd672ddbee96"},{"name":"Confirm Password (Verify OTP)","id":"dbc929dd-7c0f-474f-bd40-926c9f60a62b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"123456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/confirmPassword","description":"<p>Verify the OTP received after calling Forget Password. Must be called before Reset Password.</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>The email used in Forget Password</td>\n</tr>\n<tr>\n<td>otp</td>\n<td>string</td>\n<td>Yes</td>\n<td>Exactly 6 characters. Received via email</td>\n</tr>\n</tbody>\n</table>\n</div><p>On success: stores a <code>verified_otp</code> flag in Redis for 5 minutes, required by Reset Password.</p>\n","urlObject":{"path":["auth","confirmPassword"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"766dacf1-9840-4689-af83-cd7ba8ef4ef0","name":"Confirm Password - Success","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"123456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/confirmPassword"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Otp Is Valid\",\n  \"data\": {}\n}"},{"id":"13305b66-5869-4916-9348-054095a66a6f","name":"Confirm Password - Invalid or Expired OTP","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"otp\": \"000000\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/confirmPassword"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid or Expired OTP\",\n  \"status\": 500\n}"}],"_postman_id":"dbc929dd-7c0f-474f-bd40-926c9f60a62b"},{"name":"Reset Password","id":"8d9fa3f1-74e9-4e1d-bf85-79ea99312577","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"newPassword\": \"newpassword123\",\n  \"rePassword\": \"newpassword123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/resetPassword","description":"<p>Reset the user's password. Must be called after Confirm Password (OTP verified).</p>\n<p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>email</td>\n<td>string</td>\n<td>Yes</td>\n<td>The email used throughout the reset flow</td>\n</tr>\n<tr>\n<td>newPassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Min 8 characters</td>\n</tr>\n<tr>\n<td>rePassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Must match newPassword</td>\n</tr>\n</tbody>\n</table>\n</div><p>Requires <code>verified_otp</code> to be set in Redis (expires 5 minutes after Confirm Password).\nOn success: updates the password and sets <code>logOut</code> timestamp to invalidate old sessions.</p>\n","urlObject":{"path":["auth","resetPassword"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"a06acc07-3f3a-4b13-a1f3-3dfc652e37dd","name":"Reset Password - Success","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"newPassword\": \"newpassword123\",\n  \"rePassword\": \"newpassword123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/resetPassword"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Password Reset Succefully\",\n  \"data\": {}\n}"},{"id":"8688a6ad-0c08-46b1-be48-283f5358d0fe","name":"Reset Password - OTP Not Verified","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"newPassword\": \"newpassword123\",\n  \"rePassword\": \"newpassword123\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/resetPassword"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Otp not verified\",\n  \"status\": 500\n}"},{"id":"baf2f06f-d4db-4834-b6e7-9ca37682435c","name":"Reset Password - Passwords Don't Match","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"email\": \"diaaelseady@gmail.com\",\n  \"newPassword\": \"newpassword123\",\n  \"rePassword\": \"differentpassword\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/resetPassword"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": {\n    \"message\": \"Validation Error\",\n    \"errors\": [\n      { \"field\": \"rePassword\", \"message\": \"Passwords don't match\" }\n    ]\n  },\n  \"status\": 400\n}"}],"_postman_id":"8d9fa3f1-74e9-4e1d-bf85-79ea99312577"}],"id":"740e299c-27dd-49c6-8f8a-4c18e31ac5dc","_postman_id":"740e299c-27dd-49c6-8f8a-4c18e31ac5dc","description":""},{"name":"User","item":[{"name":"Get Profile","id":"a6d4d3f2-d641-4876-bc52-d068a1320b7c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"token","value":"","description":"<p>JWT access token from signin</p>\n"}],"url":"http://localhost:3000/user/profile","description":"<p>Get the currently authenticated user's profile.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token from signin</td>\n</tr>\n</tbody>\n</table>\n</div><p>Phone number is automatically decrypted before returning.</p>\n","urlObject":{"path":["user","profile"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"78139c52-c540-4232-a004-a7f2475b54a4","name":"Get Profile - Success","originalRequest":{"method":"GET","header":[{"key":"token","value":""}],"url":"http://localhost:3000/user/profile"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"_id\": \"664f1a2b3c4d5e6f7a8b9c0d\",\n    \"firstName\": \"Diaa\",\n    \"lastName\": \"Eldeen\",\n    \"userName\": \"Diaa Eldeen\",\n    \"email\": \"diaaelseady@gmail.com\",\n    \"age\": 23,\n    \"phone\": \"01278396490\",\n    \"address\": \"Alexandria\",\n    \"gender\": \"male\",\n    \"role\": \"user\",\n    \"provider\": \"local\",\n    \"confirmed\": true,\n    \"createdAt\": \"2026-01-01T00:00:00.000Z\",\n    \"updatedAt\": \"2026-01-01T00:00:00.000Z\"\n  }\n}"},{"id":"5177c26f-4dde-46a4-9ee7-c4ebc7627e14","name":"Get Profile - Unauthorized","originalRequest":{"method":"GET","header":[],"url":"http://localhost:3000/user/profile"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Token Not Provided\",\n  \"status\": 401\n}"}],"_postman_id":"a6d4d3f2-d641-4876-bc52-d068a1320b7c"},{"name":"Update Profile","id":"6ace89eb-cdab-4590-a70e-bfcd56348066","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"token","value":"","description":"<p>JWT access token from signin</p>\n"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstName\": \"Diaa\",\n  \"lastName\": \"Eldeen\",\n  \"age\": 23,\n  \"phone\": \"01278396490\",\n  \"gender\": \"male\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updateProfile","description":"<p>Update the authenticated user's profile information.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>firstName</td>\n<td>string</td>\n<td>Yes</td>\n<td>3-30 chars. Letters, numbers, spaces, - and _ only</td>\n</tr>\n<tr>\n<td>lastName</td>\n<td>string</td>\n<td>Yes</td>\n<td>3-30 chars. Letters, numbers, spaces, - and _ only</td>\n</tr>\n<tr>\n<td>age</td>\n<td>number</td>\n<td>Yes</td>\n<td>Integer, min 18</td>\n</tr>\n<tr>\n<td>phone</td>\n<td>string</td>\n<td>No</td>\n<td>Egyptian number: 010/011/012/015 + 8 digits. Stored encrypted</td>\n</tr>\n<tr>\n<td>gender</td>\n<td>string</td>\n<td>No</td>\n<td>\"male\" or \"female\"</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["user","updateProfile"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"dec98acc-444e-42e4-b068-b0cd6efd61e4","name":"Update Profile - Success","originalRequest":{"method":"PATCH","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstName\": \"Diaa\",\n  \"lastName\": \"Eldeen\",\n  \"age\": 23,\n  \"phone\": \"01278396490\",\n  \"gender\": \"male\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updateProfile"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"_id\": \"664f1a2b3c4d5e6f7a8b9c0d\",\n    \"firstName\": \"Diaa\",\n    \"lastName\": \"Eldeen\",\n    \"userName\": \"Diaa Eldeen\",\n    \"email\": \"diaaelseady@gmail.com\",\n    \"age\": 23,\n    \"phone\": \"encrypted_string\",\n    \"gender\": \"male\",\n    \"role\": \"user\",\n    \"provider\": \"local\",\n    \"confirmed\": true,\n    \"createdAt\": \"2026-01-01T00:00:00.000Z\",\n    \"updatedAt\": \"2026-01-01T00:00:00.000Z\"\n  }\n}"},{"id":"2d80f5ef-ccb4-4eb0-868d-3ef711bb8b8e","name":"Update Profile - Validation Error","originalRequest":{"method":"PATCH","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstName\": \"J\",\n  \"lastName\": \"D\",\n  \"age\": 15\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updateProfile"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": {\n    \"message\": \"Validation Error\",\n    \"errors\": [\n      { \"field\": \"firstName\", \"message\": \"firstName must be at least 3 characters\" },\n      { \"field\": \"age\", \"message\": \"You must be at least 18 years old\" }\n    ]\n  },\n  \"status\": 400\n}"}],"_postman_id":"6ace89eb-cdab-4590-a70e-bfcd56348066"},{"name":"Update Password","id":"9760cbf0-da37-485f-9b99-a73e4ef359dc","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"token","value":"","description":"<p>JWT access token from signin</p>\n"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"oldPassword\": \"password123\",\n  \"newPassword\": \"newpassword456\",\n  \"confirmPassword\": \"newpassword456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updatePassword","description":"<p>Change the authenticated user's password.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>oldPassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Current password for verification</td>\n</tr>\n<tr>\n<td>newPassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Min 8 characters</td>\n</tr>\n<tr>\n<td>confirmPassword</td>\n<td>string</td>\n<td>Yes</td>\n<td>Must match newPassword</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["user","updatePassword"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"4443ce0c-94a8-43ac-83eb-043e2275ba5c","name":"Update Password - Success","originalRequest":{"method":"PATCH","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"oldPassword\": \"password123\",\n  \"newPassword\": \"newpassword456\",\n  \"confirmPassword\": \"newpassword456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updatePassword"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {}\n}"},{"id":"72ecb9a6-76f1-4b3e-9e8d-12d4a0250275","name":"Update Password - Invalid Old Password","originalRequest":{"method":"PATCH","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"oldPassword\": \"wrongpassword\",\n  \"newPassword\": \"newpassword456\",\n  \"confirmPassword\": \"newpassword456\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updatePassword"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid old Password\",\n  \"status\": 500\n}"},{"id":"a2605607-08c2-448a-8f3e-d33b532bbafa","name":"Update Password - Passwords Don't Match","originalRequest":{"method":"PATCH","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"oldPassword\": \"password123\",\n  \"newPassword\": \"newpassword456\",\n  \"confirmPassword\": \"differentpassword\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/user/updatePassword"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": {\n    \"message\": \"Validation Error\",\n    \"errors\": [\n      { \"field\": \"confirmPassword\", \"message\": \"Passwords do not match\" }\n    ]\n  },\n  \"status\": 400\n}"}],"_postman_id":"9760cbf0-da37-485f-9b99-a73e4ef359dc"}],"id":"709fc802-08f5-4fc1-9c9e-542c866158a9","_postman_id":"709fc802-08f5-4fc1-9c9e-542c866158a9","description":""},{"name":"S3","item":[{"name":"Upload Profile Picture (Pre-Signed URL)","id":"9131317f-4660-4d40-9944-c6a7f2ed7390","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"fileName\": \"profile.png\",\n  \"ContentType\": \"image/png\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/uploadProfilePic","description":"<p>Generate a pre-signed URL to upload a profile picture directly to S3.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>fileName</td>\n<td>string</td>\n<td>Yes</td>\n<td>The name of the file to upload (e.g. profile.png)</td>\n</tr>\n<tr>\n<td>ContentType</td>\n<td>string</td>\n<td>Yes</td>\n<td>MIME type of the file (e.g. image/png, image/jpeg, image/webp, image/jpg)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Returns a pre-signed <code>url</code> (valid 60 seconds) to PUT the file directly to S3, and the <code>Key</code> which is saved to the user's profilePic field in DB.</p>\n<p><strong>Supported types:</strong> image/png, image/jpeg, image/webp, image/jpg</p>\n","urlObject":{"path":["auth","uploadProfilePic"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"fb055713-3484-47f7-8a53-825d26db8e57","name":"Upload Profile Picture - Success","originalRequest":{"method":"POST","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"fileName\": \"profile.png\",\n  \"ContentType\": \"image/png\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/uploadProfilePic"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"url\": \"https://s3.amazonaws.com/bucket/socialMedia_app/users/664f.../presigned-url...\",\n    \"Key\": \"social_media/users/664f1a2b3c4d5e6f7a8b9c0d/randomUUID_____profile.png\"\n  }\n}"},{"id":"de123469-f53e-4833-bf5c-de90d4b3efdc","name":"Upload Profile Picture - Unauthorized","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"fileName\": \"profile.png\",\n  \"ContentType\": \"image/png\"\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/uploadProfilePic"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Token Not Provided\",\n  \"status\": 401\n}"}],"_postman_id":"9131317f-4660-4d40-9944-c6a7f2ed7390"},{"name":"Get Picture (Stream)","id":"b1551164-9c60-4530-88ce-e4611fa27781","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"}],"url":"http://localhost:3000/auth/getPictures/social_media/users/664f1a2b/uuid_____profile.png","description":"<p>Stream a file directly from S3 by its Key (path).</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>URL Params:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Param</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>path</td>\n<td>wildcard</td>\n<td>Yes</td>\n<td>The full S3 Key after the base URL (e.g. social_media/users/userId/uuid_____file.png)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Returns the file as a binary stream with correct Content-Type header.</p>\n","urlObject":{"path":["auth","getPictures","social_media","users","664f1a2b","uuid_____profile.png"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"5fc9c464-7305-4412-a8df-a36984e0b1f0","name":"Get Picture - Success","originalRequest":{"method":"GET","header":[{"key":"token","value":""}],"url":"http://localhost:3000/auth/getPictures/social_media/users/664f1a2b/uuid_____profile.png"},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"image/png"}],"cookie":[],"responseTime":null,"body":"(binary image stream)"}],"_postman_id":"b1551164-9c60-4530-88ce-e4611fa27781"},{"name":"Get Pre-Signed Picture URL","id":"1b2a56ee-95b3-479c-a590-7f4c8f8adef4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"}],"url":"http://localhost:3000/auth/getPreSignedPictures/social_media/users/664f1a2b/uuid_____profile.png","description":"<p>Get a temporary pre-signed URL to access a private S3 file.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>URL Params:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Param</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>path</td>\n<td>wildcard</td>\n<td>Yes</td>\n<td>The full S3 Key after the base URL</td>\n</tr>\n</tbody>\n</table>\n</div><p>Returns a pre-signed URL valid for 60 seconds.</p>\n","urlObject":{"path":["auth","getPreSignedPictures","social_media","users","664f1a2b","uuid_____profile.png"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"b5c8333e-646b-4502-aa11-d3133fad90d1","name":"Get Pre-Signed Picture URL - Success","originalRequest":{"method":"GET","header":[{"key":"token","value":""}],"url":"http://localhost:3000/auth/getPreSignedPictures/social_media/users/664f1a2b/uuid_____profile.png"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": \"https://s3.amazonaws.com/bucket/social_media/users/664f.../uuid_____profile.png?X-Amz-Signature=...\"\n}"}],"_postman_id":"1b2a56ee-95b3-479c-a590-7f4c8f8adef4"},{"name":"Get All Files In Folder","id":"c01401fe-aa78-43f8-83ae-2b75bfa9b88c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"}],"url":"http://localhost:3000/auth/pictures?folderName=users/664f1a2b3c4d5e6f7a8b9c0d","description":"<p>List all files inside a specific S3 folder.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Query Params:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Param</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>folderName</td>\n<td>string</td>\n<td>Yes</td>\n<td>Folder path inside the bucket under socialMedia_app/ (e.g. users/userId)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Returns an array of objects each containing the file <code>Key</code>.</p>\n","urlObject":{"path":["auth","pictures"],"host":["http://localhost:3000"],"query":[{"description":{"content":"<p>The folder path inside the S3 bucket (under socialMedia_app/)</p>\n","type":"text/plain"},"key":"folderName","value":"users/664f1a2b3c4d5e6f7a8b9c0d"}],"variable":[]}},"response":[{"id":"de036981-7d46-4cf1-b04c-ff446497c864","name":"Get All Files In Folder - Success","originalRequest":{"method":"GET","header":[{"key":"token","value":""}],"url":{"raw":"http://localhost:3000/auth/pictures?folderName=users/664f1a2b3c4d5e6f7a8b9c0d","host":["http://localhost:3000"],"path":["auth","pictures"],"query":[{"key":"folderName","value":"users/664f1a2b3c4d5e6f7a8b9c0d"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": [\n    { \"Key\": \"socialMedia_app/users/664f1a2b/uuid1_____profile.png\" },\n    { \"Key\": \"socialMedia_app/users/664f1a2b/uuid2_____cover.jpg\" }\n  ]\n}"}],"_postman_id":"c01401fe-aa78-43f8-83ae-2b75bfa9b88c"},{"name":"Delete Single File","id":"6ec7d1f4-e4a1-4cdf-8e13-4c616808bd9f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"}],"url":"http://localhost:3000/auth/picture?Key=socialMedia_app/users/664f1a2b/uuid_____profile.png","description":"<p>Delete a single file from S3 by its Key.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Query Params:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Param</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Key</td>\n<td>string</td>\n<td>Yes</td>\n<td>The full S3 Key of the file to delete</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["auth","picture"],"host":["http://localhost:3000"],"query":[{"description":{"content":"<p>The full S3 Key of the file to delete</p>\n","type":"text/plain"},"key":"Key","value":"socialMedia_app/users/664f1a2b/uuid_____profile.png"}],"variable":[]}},"response":[{"id":"34b29b78-9e45-4c74-b543-236849b2537a","name":"Delete Single File - Success","originalRequest":{"method":"DELETE","header":[{"key":"token","value":""}],"url":{"raw":"http://localhost:3000/auth/picture?Key=socialMedia_app/users/664f1a2b/uuid_____profile.png","host":["http://localhost:3000"],"path":["auth","picture"],"query":[{"key":"Key","value":"socialMedia_app/users/664f1a2b/uuid_____profile.png"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"DeleteMarker\": true,\n    \"VersionId\": \"abc123\"\n  }\n}"}],"_postman_id":"6ec7d1f4-e4a1-4cdf-8e13-4c616808bd9f"},{"name":"Delete Multiple Files","id":"b58c8eb4-dc36-462a-8173-d08a4b3c0956","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"Keys\": [\n    \"socialMedia_app/users/664f1a2b/uuid1_____profile.png\",\n    \"socialMedia_app/users/664f1a2b/uuid2_____cover.jpg\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/pictures","description":"<p>Delete multiple files from S3 in a single request.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Body Fields:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Keys</td>\n<td>string[]</td>\n<td>Yes</td>\n<td>Array of full S3 Keys to delete</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["auth","pictures"],"host":["http://localhost:3000"],"query":[],"variable":[]}},"response":[{"id":"5cac5d9b-b62d-46c6-8c7c-a6362230e4bf","name":"Delete Multiple Files - Success","originalRequest":{"method":"DELETE","header":[{"key":"token","value":""},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"Keys\": [\n    \"socialMedia_app/users/664f1a2b/uuid1_____profile.png\",\n    \"socialMedia_app/users/664f1a2b/uuid2_____cover.jpg\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"http://localhost:3000/auth/pictures"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"Deleted\": [\n      { \"Key\": \"socialMedia_app/users/664f1a2b/uuid1_____profile.png\" },\n      { \"Key\": \"socialMedia_app/users/664f1a2b/uuid2_____cover.jpg\" }\n    ]\n  }\n}"}],"_postman_id":"b58c8eb4-dc36-462a-8173-d08a4b3c0956"},{"name":"Delete Entire Folder","id":"bf1c1aed-98c0-4a86-b591-8895cc209c63","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[{"key":"token","value":"","description":"<p>JWT access token</p>\n"}],"url":"http://localhost:3000/auth/folder?folderName=users/664f1a2b3c4d5e6f7a8b9c0d","description":"<p>Delete an entire S3 folder and all its contents.</p>\n<p><strong>Headers:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>token</td>\n<td>string</td>\n<td>Yes</td>\n<td>JWT access token</td>\n</tr>\n</tbody>\n</table>\n</div><p><strong>Query Params:</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Param</th>\n<th>Type</th>\n<th>Required</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>folderName</td>\n<td>string</td>\n<td>Yes</td>\n<td>The folder path inside socialMedia_app/ to delete (e.g. users/userId)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Internally: lists all files in the folder then deletes them all in one batch request.</p>\n","urlObject":{"path":["auth","folder"],"host":["http://localhost:3000"],"query":[{"description":{"content":"<p>The folder path inside socialMedia_app/ to delete entirely</p>\n","type":"text/plain"},"key":"folderName","value":"users/664f1a2b3c4d5e6f7a8b9c0d"}],"variable":[]}},"response":[{"id":"22bf119a-8172-4055-89b1-ec976fd3e87e","name":"Delete Folder - Success","originalRequest":{"method":"DELETE","header":[{"key":"token","value":""}],"url":{"raw":"http://localhost:3000/auth/folder?folderName=users/664f1a2b3c4d5e6f7a8b9c0d","host":["http://localhost:3000"],"path":["auth","folder"],"query":[{"key":"folderName","value":"users/664f1a2b3c4d5e6f7a8b9c0d"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"done!\",\n  \"data\": {\n    \"Deleted\": [\n      { \"Key\": \"socialMedia_app/users/664f1a2b/uuid1_____profile.png\" },\n      { \"Key\": \"socialMedia_app/users/664f1a2b/uuid2_____cover.jpg\" }\n    ]\n  }\n}"}],"_postman_id":"bf1c1aed-98c0-4a86-b591-8895cc209c63"}],"id":"85132cde-9f62-456f-b9f0-ecf37d0dfc4b","_postman_id":"85132cde-9f62-456f-b9f0-ecf37d0dfc4b","description":""}],"variable":[{"key":"base_url","value":"http://localhost:3000"},{"key":"token","value":""},{"key":"refreshToken","value":""}]}