> ## 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.

# Forgot Password

> Request a password reset code via email

## Endpoint

```
POST /api/v1/auth/forgot-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. Works for both job seekers and companies.
</ParamField>

## Request Shape

```typescript theme={null}
interface ForgotPasswordDto {
  email: string;
}
```

## Response

### Success Response (200 OK)

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

```json theme={null}
{
  "success": true,
  "data": {
    "email": "john.doe@example.com"
  },
  "message": "If an account exists with that email, you'll receive a password reset link shortly.",
  "meta": {
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/forgot-password",
    "method": "POST"
  }
}
```

<ResponseField name="success" type="boolean">
  Always `true` for successful requests.
</ResponseField>

<ResponseField name="data" type="object">
  Contains the submitted email address.

  <Expandable title="Properties">
    <ResponseField name="email" type="string">
      The email address that was submitted.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="message" type="string">
  Generic success message that doesn't reveal if the email exists in the system.
</ResponseField>

## Security Behavior

<Warning>
  **Email Enumeration Prevention**: This endpoint always returns the same success response,
  regardless of whether the email exists in the database. This prevents attackers from discovering
  valid email addresses.
</Warning>

### What Actually Happens

<Steps>
  <Step title="Immediate Response">
    API returns success response immediately without waiting for email lookup.
  </Step>

  <Step title="Background Processing">
    System searches for the account in both JobSeeker and Company tables (asynchronously).
  </Step>

  <Step title="Email Exists">
    If account is found: - Generate 6-digit OTP code - Store OTP in Redis with 10-minute expiration -
    Queue password reset email for delivery - Email is sent with the reset code
  </Step>

  <Step title="Email Doesn't Exist">
    If account is not found: - Process silently terminates - No email is sent - User sees same
    response as successful case
  </Step>
</Steps>

## Email Content

If the email exists, the user receives an email containing:

* 6-digit OTP code
* Instructions to use the reset password endpoint
* Expiration notice (10 minutes)
* Security warnings
* Information about account protection

## OTP Details

<Info>
  **OTP Validity**: Each password reset code is valid for **10 minutes** from generation. After
  expiration, users need to request a new code.
</Info>

<Tip>
  **OTP Format**: The code is a 6-digit numeric string (e.g., `123456`). Only numbers are allowed.
</Tip>

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

## Error Responses

### 400 Bad Request - Validation Error

Returned when request validation fails.

```json theme={null}
{
  "success": false,
  "error": {
    "message": ["email must be an email"],
    "statusCode": 400,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/auth/forgot-password",
    "method": "POST",
    "details": "Bad Request"
  }
}
```

**Common validation errors**:

* `email must be an email` - Invalid email format
* `email should not be empty` - Email field is missing

## Validation Rules

| Field | Type   | Required | Rules                      |
| ----- | ------ | -------- | -------------------------- |
| email | string | Yes      | Must be valid email format |

## Rate Limiting Considerations

<Warning>
  **Best Practice**: Implement rate limiting on the client side to prevent abuse. Consider limiting
  requests to 3 attempts per email per hour.
</Warning>

While the API doesn't currently enforce rate limiting, excessive requests may be throttled in the future.

## Response Time

The response is designed to be **consistent** regardless of whether the email exists:

* ✅ Same response time (\~50-100ms)
* ✅ Same HTTP status code (200)
* ✅ Same response structure
* ✅ No indication of email existence

This prevents timing attacks that could reveal valid email addresses.

## Next Steps

After receiving the password reset code via email:

1. **Use the code** with the [Reset Password](/api-reference/auth/reset-password) endpoint
2. **Enter the 6-digit code** along with the email and new password
3. **Wait for confirmation** that password has been reset
4. **Login** with the new password using the [Login](/api-reference/auth/login) endpoint

## Important Notes

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

<Tip>
  **Multiple Requests**: If a user requests a password reset multiple times, each new OTP
  **overwrites** the previous one. Only the most recent OTP is valid.
</Tip>

<Warning>
  **Email Delivery**: Email delivery may take a few seconds to a few minutes depending on email
  provider. If the user doesn't receive the email: - Check spam/junk folder - Verify email address
  is correct - Request a new code after waiting a few minutes
</Warning>

## Security Notes

<Info>
  **Privacy First**: This endpoint is designed with security and privacy in mind. It never reveals
  whether an email address is registered in the system.
</Info>

### Best Practices

1. **Don't reveal email existence** - Use generic success messages
2. **Consistent response times** - Prevent timing attacks
3. **Time-limited OTPs** - Codes expire after 10 minutes
4. **Attempt limiting** - Maximum 3 verification attempts per OTP
5. **Single-use codes** - Each OTP can only be used once successfully

## Related Endpoints

* [Reset Password](/api-reference/auth/reset-password) - Complete password reset with OTP code
* [Login](/api-reference/auth/login) - Login after resetting password
* [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
