# 

## Prerequisites

* The user's login email (username)
* Either the current password or a one-time password (OTP) obtained through the forgot-password flow


## Password requirements

| Rule | Constraint |
|  --- | --- |
| Minimum length | 12 characters |
| Maximum length | 128 characters |
| Format | Use a strong passphrase or complex password |


## Option A: Change password (known current password)

Use this when the user knows their current password and wants to set a new one.

### Step 1: Send the password update

Send `PATCH /v1/users/me/passwords` with Basic Auth (username + current password).

curl
```shell
curl -X PATCH \
  https://api.dev.paradisegateway.net/v1/users/me/passwords \
  -u "john.doe@example.com:current-password-here" \
  -H "Content-Type: application/json" \
  -d '{
    "user_name": "john.doe@example.com",
    "current_password": "Meat-Said-Whispered-Plant6-One",
    "new_password": "Rocky-Change-Thread-Tank1-Slowly"
  }'
```

Python
```python
import requests

resp = requests.patch(
    "https://api.dev.paradisegateway.net/v1/users/me/passwords",
    auth=("john.doe@example.com", "Meat-Said-Whispered-Plant6-One"),
    headers={"Content-Type": "application/json"},
    json={
        "user_name": "john.doe@example.com",
        "current_password": "Meat-Said-Whispered-Plant6-One",
        "new_password": "Rocky-Change-Thread-Tank1-Slowly",
    },
)
print(resp.json())
```

JavaScript
```javascript
const credentials = btoa("john.doe@example.com:Meat-Said-Whispered-Plant6-One");
const resp = await fetch(
  "https://api.dev.paradisegateway.net/v1/users/me/passwords",
  {
    method: "PATCH",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Basic ${credentials}`,
    },
    body: JSON.stringify({
      user_name: "john.doe@example.com",
      current_password: "Meat-Said-Whispered-Plant6-One",
      new_password: "Rocky-Change-Thread-Tank1-Slowly",
    }),
  }
);
console.log(await resp.json());
```

C#
```csharp
using var client = new HttpClient();
var authBytes = System.Text.Encoding.UTF8.GetBytes(
    "john.doe@example.com:Meat-Said-Whispered-Plant6-One");
client.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue(
        "Basic", Convert.ToBase64String(authBytes));

var payload = new
{
    user_name = "john.doe@example.com",
    current_password = "Meat-Said-Whispered-Plant6-One",
    new_password = "Rocky-Change-Thread-Tank1-Slowly"
};
var resp = await client.PatchAsJsonAsync(
    "https://api.dev.paradisegateway.net/v1/users/me/passwords", payload);
Console.WriteLine(await resp.Content.ReadAsStringAsync());
```

Java
```java
HttpClient client = HttpClient.newHttpClient();
String auth = Base64.getEncoder().encodeToString(
    "john.doe@example.com:Meat-Said-Whispered-Plant6-One".getBytes());
String body = """
    {
      "user_name": "john.doe@example.com",
      "current_password": "Meat-Said-Whispered-Plant6-One",
      "new_password": "Rocky-Change-Thread-Tank1-Slowly"
    }
    """;
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(
        "https://api.dev.paradisegateway.net/v1/users/me/passwords"))
    .header("Content-Type", "application/json")
    .header("Authorization", "Basic " + auth)
    .method("PATCH", HttpRequest.BodyPublishers.ofString(body)).build();
HttpResponse<String> resp = client.send(request,
    HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
```

Go
```go
payload := strings.NewReader(`{
  "user_name": "john.doe@example.com",
  "current_password": "Meat-Said-Whispered-Plant6-One",
  "new_password": "Rocky-Change-Thread-Tank1-Slowly"
}`)
req, _ := http.NewRequest("PATCH",
    "https://api.dev.paradisegateway.net/v1/users/me/passwords", payload)
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("john.doe@example.com", "Meat-Said-Whispered-Plant6-One")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
```

PHP
```php
$ch = curl_init("https://api.dev.paradisegateway.net/v1/users/me/passwords");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_USERPWD => "john.doe@example.com:Meat-Said-Whispered-Plant6-One",
    CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
    CURLOPT_POSTFIELDS => json_encode([
        "user_name" => "john.doe@example.com",
        "current_password" => "Meat-Said-Whispered-Plant6-One",
        "new_password" => "Rocky-Change-Thread-Tank1-Slowly",
    ]),
]);
echo curl_exec($ch); curl_close($ch);
```

Ruby
```ruby
require "net/http"; require "json"
uri = URI("https://api.dev.paradisegateway.net/v1/users/me/passwords")
req = Net::HTTP::Patch.new(uri, { "Content-Type" => "application/json" })
req.basic_auth("john.doe@example.com", "Meat-Said-Whispered-Plant6-One")
req.body = {
  user_name: "john.doe@example.com",
  current_password: "Meat-Said-Whispered-Plant6-One",
  new_password: "Rocky-Change-Thread-Tank1-Slowly",
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts resp.body
```

### Response

A `200` response confirms the password was changed.

```json
{
  "status": true,
  "correlation_id": "e5f6a7b8-c9d0-1234-ef01-23456789abcd"
}
```

## Option B: Forgot password (OTP flow)

Use this when the user has forgotten their password. This is a two-step process.

```mermaid
---
config:
  theme: 'neutral'
---
sequenceDiagram
    participant User
    participant App as Your App
    participant API as Reefpay
    App->>API: POST /v1/mfa/challenges (type: forgot_password)
    API-->>User: OTP sent via email
    User->>App: Enters OTP
    App->>API: PATCH /v1/users/me/passwords (with OTP)
    API-->>App: 200 OK — password updated
```

### Step 1: Request a one-time password

Send `POST /v1/mfa/challenges` with `type: forgot_password` and the user's email.

```shell
curl -X POST \
  https://api.dev.paradisegateway.net/v1/mfa/challenges \
  -H "Content-Type: application/json" \
  -d '{
    "user_name": "john.doe@example.com",
    "type": "forgot_password"
  }'
```

Response:

```json
{
  "status": true,
  "correlation_id": "f6a7b8c9-d0e1-2345-f012-3456789abcde"
}
```

The user receives the OTP at their registered email address.

### Step 2: Set new password with OTP

Send `PATCH /v1/users/me/passwords` with the `one_time_password` field instead of `current_password`.

```shell
curl -X PATCH \
  https://api.dev.paradisegateway.net/v1/users/me/passwords \
  -H "Content-Type: application/json" \
  -d '{
    "user_name": "john.doe@example.com",
    "one_time_password": "123456",
    "current_password": "placeholder",
    "new_password": "Hat-Chest-Clock5-Solid-Round"
  }'
```

Response:

```json
{
  "status": true,
  "correlation_id": "a7b8c9d0-e1f2-3456-0123-456789abcdef"
}
```

## Error responses

| Status | Meaning |
|  --- | --- |
| `401` | Current password or OTP is incorrect |
| `404` | User not found |


## Next steps

* [Enable multi-factor authentication](/docs/how-tos/clients-users/enable-mfa)
* [Update user profile](/docs/how-tos/clients-users/update-user)