> ## Documentation Index
> Fetch the complete documentation index at: https://careerk.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Reset Password

> Reset user password using OTP code

## Endpoint

```
POST /api/v1/auth/reset-password
```

**Base URL**: `http://localhost:3000/api/v1`

<Note>This endpoint is **public** and does not require authentication.</Note>

## Request Body

<ParamField body="email" type="string" required>
  The email address associated with the account. Must match the email used in the forgot password
  request.
</ParamField>

<ParamField body="code" type="string" required>
  The 6-digit OTP code sent to the email. Must be exactly 6 numeric digits.
</ParamField>

<ParamField body="newPassword" type="string" required>
  The new password for the account. Minimum 6 characters.
</ParamField>

## Request Shape

```typescript theme={null}
interface ResetPasswordDto {
  email: string;
  code: string;
  newPassword: string;
}
```

## Response

### Success Response (200 OK)

```typescript theme={null}
interface ResetPasswordResponse {
  success: boolean;
  data: {
    message: string;
  };
  message: string;
  meta: {
    timestamp: string;
    path: string;
    method: string;
  };
}
```

```json theme={null}
{
  "success": true,
  "data": {
    "message": "Password has been reset successfully"
  },
  "message": "Success",
  "meta": {
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/reset-password",
    "method": "POST"
  }
}
```

<ResponseField name="success" type="boolean">
  Indicates if the password reset was successful.
</ResponseField>

<ResponseField name="data" type="object">
  Contains confirmation message.

  <Expandable title="Properties">
    <ResponseField name="message" type="string">
      Success confirmation message.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable success message: "Password has been reset successfully"
</ResponseField>

## What Happens on Password Reset

<Steps>
  <Step title="OTP Verification">
    System verifies the OTP code against the stored value in Redis.
  </Step>

  <Step title="Expiration Check">Ensures the OTP hasn't expired (10-minute validity window).</Step>

  <Step title="Attempt Counter Check">Verifies that maximum attempts (3) haven't been exceeded.</Step>

  <Step title="User Type Detection">
    System determines if the user is a Job Seeker or Company based on stored OTP data.
  </Step>

  <Step title="Password Hashing">New password is securely hashed using bcrypt algorithm.</Step>

  <Step title="Database Update">
    User's password is updated in the database (JobSeeker or Company table).
  </Step>

  <Step title="Session Invalidation">
    All existing refresh tokens are invalidated, logging out all active sessions.
  </Step>

  <Step title="OTP Deletion">Used OTP is immediately deleted from Redis.</Step>

  <Step title="Success Response">Confirmation message is returned to the user.</Step>
</Steps>

## Important: Session Invalidation

<Warning>
  **All Sessions Logged Out**: After a successful password reset, all active sessions are
  automatically terminated. The user must login again with the new password.
</Warning>

This security measure ensures that:

* ✅ Any potentially compromised sessions are invalidated
* ✅ Only the user with the new password can access the account
* ✅ All devices are logged out for security

## Error Responses

### 400 Bad Request - Validation Error

Returned when request validation fails.

```json theme={null}
{
  "success": false,
  "error": {
    "message": [
      "email must be an email",
      "code must be exactly 6 characters long",
      "newPassword must be longer than or equal to 6 characters"
    ],
    "statusCode": 400,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/reset-password",
    "method": "POST",
    "details": "Bad Request"
  }
}
```

**Common validation errors**:

* `email must be an email` - Invalid email format
* `code must be exactly 6 characters long` - Code is not 6 digits
* `newPassword must be longer than or equal to 6 characters` - Password too short

### 401 Unauthorized - Invalid or Expired Code

Returned when OTP is incorrect, expired, or doesn't exist.

```json theme={null}
{
  "success": false,
  "error": {
    "message": "expired reset code",
    "statusCode": 401,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/reset-password",
    "method": "POST",
    "details": "Unauthorized"
  }
}
```

**Possible causes**:

* OTP code is incorrect
* OTP has expired (10 minutes validity)
* OTP was already used
* Email doesn't match the email used in forgot password request
* OTP was never generated for this email
* Maximum verification attempts (3) exceeded

### 401 Unauthorized - User Not Found

Returned when no user exists with the provided email.

```json theme={null}
{
  "success": false,
  "error": {
    "message": "User not found",
    "statusCode": 401,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/reset-password",
    "method": "POST",
    "details": "Unauthorized"
  }
}
```

This can occur if the account was deleted between the forgot password and reset password requests.

### 500 Internal Server Error

Returned when an unexpected error occurs during password reset.

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Password reset failed",
    "statusCode": 500,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/reset-password",
    "method": "POST",
    "details": "Internal Server Error"
  }
}
```

## Validation Rules

| Field       | Type   | Required | Rules                                        |
| ----------- | ------ | -------- | -------------------------------------------- |
| email       | string | Yes      | Must be valid email format                   |
| code        | string | Yes      | Must be exactly 6 digits, numeric only (0-9) |
| newPassword | string | Yes      | Minimum 6 characters (8+ recommended)        |

## Password Requirements

<Info>**Minimum Length**: 6 characters</Info>

<Tip>
  **Recommended**: Use at least 8 characters with a mix of uppercase, lowercase, numbers, and
  special characters for better security.
</Tip>

### Strong Password Guidelines

A strong password should include:

* ✅ At least 8 characters (minimum is 6)
* ✅ Mix of uppercase and lowercase letters
* ✅ At least one number
* ✅ At least one special character (@, #, \$, %, etc.)
* ❌ Avoid common words or patterns
* ❌ Don't reuse old passwords

## OTP Behavior

<Info>
  **OTP Validity**: Each password reset code is valid for **10 minutes** from generation. After
  expiration, users need to request a new code via [Forgot
  Password](/api-reference/auth/forgot-password).
</Info>

<Warning>
  **Maximum Attempts**: Each OTP can be verified a maximum of **3 times**. After 3 failed attempts,
  the code is invalidated and a new request is required.
</Warning>

<Tip>
  **Single Use**: Once the password is successfully reset, the OTP is immediately deleted and cannot
  be reused.
</Tip>

## After Password Reset

Once password is successfully reset:

1. ✅ All active sessions are logged out
2. ✅ All refresh tokens are invalidated
3. ✅ Password is securely updated in the database
4. ✅ OTP code is deleted from Redis
5. ✅ User must login again with the new password

## Next Steps

After successful password reset:

1. **Login** using the [Login](/api-reference/auth/login) endpoint with the new password
2. **Save credentials** securely in your application
3. **Inform user** that all other sessions have been logged out

## Security Notes

<Info>
  **Automatic User Type Detection**: The system automatically determines whether the account is a
  Job Seeker or Company account based on the OTP data. You don't need to specify the user type.
</Info>

<Warning>
  **Case Sensitive Password**: Unlike email, the password is case-sensitive. Make sure users enter
  it exactly as intended.
</Warning>

### Security Features

1. **Bcrypt Hashing** - Passwords are hashed using bcrypt with salt rounds
2. **Session Invalidation** - All existing sessions are terminated
3. **Single-Use OTP** - Each code can only be used once successfully
4. **Time-Limited OTP** - Codes expire after 10 minutes
5. **Attempt Limiting** - Maximum 3 verification attempts per OTP
6. **Secure Storage** - Passwords are never stored in plain text

## Common Issues & Solutions

| Issue                           | Solution                                           |
| ------------------------------- | -------------------------------------------------- |
| "Invalid or expired reset code" | Request a new code via forgot password endpoint    |
| "User not found"                | Verify email address is correct                    |
| OTP expired                     | Codes are valid for 10 minutes - request a new one |
| Too many attempts               | Request a new code after 3 failed attempts         |
| Email doesn't match             | Use the same email from forgot password request    |

## Related Endpoints

* [Forgot Password](/api-reference/auth/forgot-password) - Request password reset code
* [Login](/api-reference/auth/login) - Login with new password after reset
* [Register Job Seeker](/api-reference/auth/register-job-seeker) - Create new job seeker account
* [Register Company](/api-reference/auth/register-company) - Create new company account
