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

# Reset Your Account Password Using Email OTP Verification

> Reset your account password in three steps: request a reset email, verify the 6-digit OTP code, then set a new password with the reset token.

Resetting your password is a three-step process designed to prevent account enumeration and protect against brute-force attacks. You request a reset by email, verify the 6-digit one-time passcode (OTP) that arrives in your inbox, and then submit your new password using the short-lived reset token returned by the verify step. All three endpoints are public and do not require an active session.

<Warning>
  **All active sessions are revoked** when you complete a password reset. Every device where you are currently logged in — including the one you are using right now — will be signed out and required to log in again with the new password.
</Warning>

## The Three-Step Reset Flow

<Steps>
  <Step title="Request a reset email">
    Call `POST /auth/password-reset` with your email address. The API always returns `202 Accepted` — even for unknown addresses — to prevent attackers from enumerating registered accounts. If the account exists, the server invalidates any previous reset token and sends a fresh 6-digit OTP valid for **15 minutes**.
  </Step>

  <Step title="Verify the OTP">
    Call `POST /auth/password-reset/otp/verify` with your email and the 6-digit code from the email. On success you receive a single-use reset token (prefixed `rst_`). You have 5 attempts; after 5 wrong codes the OTP is invalidated and you must request a new one.
  </Step>

  <Step title="Set your new password">
    Call `POST /auth/password-reset/verify` with the reset token and your new password. On success the password is updated and all sessions are revoked.
  </Step>
</Steps>

***

## Step 1 — Request a Password Reset

### Endpoint

```http theme={null}
POST https://api.example.com/api/v1/auth/password-reset
```

This endpoint is **public**. No session cookie or CSRF token is required.

### Request Body

<ParamField body="email" type="string" required>
  The email address associated with your account. The response is identical whether or not this address is registered.
</ParamField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -i -X POST https://api.example.com/api/v1/auth/password-reset \
    -H "Content-Type: application/json" \
    -d '{"email": "jane@example.com"}'
  ```

  ```js JavaScript (fetch) theme={null}
  await fetch(
    "https://api.example.com/api/v1/auth/password-reset",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: "jane@example.com" }),
    }
  );
  // Always 202 — do not branch on the body content
  ```

  ```python Python (requests) theme={null}
  import requests

  requests.post(
      "https://api.example.com/api/v1/auth/password-reset",
      json={"email": "jane@example.com"},
  )
  # Always 202
  ```
</CodeGroup>

### Success Response — `202 Accepted`

The response body is empty. If the email is registered, a 6-digit OTP is sent to the inbox. Display a generic "check your email" message to the user regardless of whether the address is known.

### Error Responses

| Status                  | Meaning      | When it occurs                                        |
| ----------------------- | ------------ | ----------------------------------------------------- |
| `429 Too Many Requests` | Rate limited | Too many requests from this IP. Wait before retrying. |

***

## Step 2 — Verify the OTP

### Endpoint

```http theme={null}
POST https://api.example.com/api/v1/auth/password-reset/otp/verify
```

This endpoint is **public**. No session cookie or CSRF token is required.

### Request Body

<ParamField body="email" type="string" required>
  The email address you used in Step 1.
</ParamField>

<ParamField body="code" type="string" required>
  The 6-digit numeric OTP from your email, e.g. `"123456"`. Must match the pattern `^\d{6}$`.
</ParamField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -i -X POST https://api.example.com/api/v1/auth/password-reset/otp/verify \
    -H "Content-Type: application/json" \
    -d '{
      "email": "jane@example.com",
      "code": "123456"
    }'
  ```

  ```js JavaScript (fetch) theme={null}
  const response = await fetch(
    "https://api.example.com/api/v1/auth/password-reset/otp/verify",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        email: "jane@example.com",
        code: "123456",
      }),
    }
  );
  const { data: { token } } = await response.json();
  // Store `token` for Step 3
  ```

  ```python Python (requests) theme={null}
  import requests

  resp = requests.post(
      "https://api.example.com/api/v1/auth/password-reset/otp/verify",
      json={"email": "jane@example.com", "code": "123456"},
  )
  reset_token = resp.json()["data"]["token"]
  ```
</CodeGroup>

### Success Response — `200 OK`

```json theme={null}
{
  "success": true,
  "data": {
    "token": "rst_abc123"
  }
}
```

<ResponseField name="data.token" type="string">
  A single-use reset token prefixed `rst_`. Pass this to Step 3 within 15 minutes before it expires.
</ResponseField>

### Error Responses

| Status                  | Meaning                    | When it occurs                                                                                                   |
| ----------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`       | Validation error           | The `code` field is not a 6-digit string, or `email` is malformed.                                               |
| `404 Not Found`         | No pending reset           | No active reset request exists for this email. Run Step 1 again.                                                 |
| `410 Gone`              | OTP expired or invalidated | The OTP window (15 minutes) has elapsed, or 5 wrong attempts invalidated the code. Request a new OTP via Step 1. |
| `429 Too Many Requests` | Rate limited               | Too many verification attempts. Wait before retrying.                                                            |

<Note>
  The OTP is valid for **15 minutes** from when it was issued and is automatically invalidated after **5 incorrect attempts**. If either limit is reached, go back to Step 1 and request a new OTP — a new reset replaces any previously active code.
</Note>

***

## Step 3 — Complete the Password Reset

### Endpoint

```http theme={null}
POST https://api.example.com/api/v1/auth/password-reset/verify
```

This endpoint is **public**. No session cookie or CSRF token is required.

### Request Body

<ParamField body="token" type="string" required>
  The reset token returned by Step 2, e.g. `rst_abc123`. This token is single-use and expires after 15 minutes.
</ParamField>

<ParamField body="new_password" type="string" required>
  Your new password. Minimum 8 characters; must include at least one uppercase letter, one lowercase letter, one digit, and one special character.
</ParamField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -i -X POST https://api.example.com/api/v1/auth/password-reset/verify \
    -H "Content-Type: application/json" \
    -d '{
      "token": "rst_abc123",
      "new_password": "N3w!Secure99"
    }'
  ```

  ```js JavaScript (fetch) theme={null}
  await fetch(
    "https://api.example.com/api/v1/auth/password-reset/verify",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        token: "rst_abc123",
        new_password: "N3w!Secure99",
      }),
    }
  );
  // 204 No Content on success — redirect to login
  ```

  ```python Python (requests) theme={null}
  import requests

  resp = requests.post(
      "https://api.example.com/api/v1/auth/password-reset/verify",
      json={
          "token": "rst_abc123",
          "new_password": "N3w!Secure99",
      },
  )
  # 204 — all sessions revoked, redirect to login
  ```
</CodeGroup>

### Success Response — `204 No Content`

The password has been updated and all active sessions have been revoked. Redirect the user to the login page and prompt them to log in with their new password.

### Error Responses

| Status            | Meaning                       | When it occurs                                                                                   |
| ----------------- | ----------------------------- | ------------------------------------------------------------------------------------------------ |
| `400 Bad Request` | Validation error              | `new_password` does not meet the complexity requirements, or a required field is missing.        |
| `404 Not Found`   | Token unknown                 | No reset record matches the supplied token.                                                      |
| `410 Gone`        | Token expired or already used | The reset token has already been used, or its 15-minute window has elapsed. Restart from Step 1. |

***

## Complete Flow Example

The following curl sequence demonstrates all three steps end-to-end:

```bash theme={null}
# Step 1 — request reset (always returns 202)
curl -s -X POST https://api.example.com/api/v1/auth/password-reset \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@example.com"}'

# Step 2 — verify OTP and capture reset token
RESET_TOKEN=$(curl -s -X POST \
  https://api.example.com/api/v1/auth/password-reset/otp/verify \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@example.com", "code": "123456"}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['token'])")

# Step 3 — set new password
curl -i -X POST https://api.example.com/api/v1/auth/password-reset/verify \
  -H "Content-Type: application/json" \
  -d "{\"token\": \"$RESET_TOKEN\", \"new_password\": \"N3w!Secure99\"}"
```

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Login" icon="arrow-right-to-bracket" href="/api-reference/auth/login">
    Log in with your new password after the reset completes.
  </Card>

  <Card title="Change Password" icon="lock" href="/api-reference/users/password">
    Change your password while logged in without going through the reset flow.
  </Card>
</CardGroup>
