The ServiciosYa API implements a two-step, OTP-based (one-time password) password reset flow. A user who has forgotten their password requests a numeric code to be sent to their registered email address. They then submit that code together with a new password to complete the reset. The raw OTP is never stored — only a SHA-256 hash is persisted — so a database leak cannot expose the code.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CodexaCP/SERVICIOS-BACK/llms.txt
Use this file to discover all available pages before exploring further.
Password policy
New passwords set through the reset flow (and throughPOST /api/auth/change-password) must satisfy the following rules:
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
- At least one special character
400 Bad Request before the OTP is consumed.
Step 1 — Request an OTP
Send the user’s email address and the company identifier to start the reset flow. Endpoint:POST /api/auth/forgot-passwordAuth: Public (no token required) Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | ✅ | The user’s registered email address |
companyId | integer | ✅ | Tenant identifier. Falls back to 1 if <= 0 |
200 OK — always returned, regardless of whether the email exists
What happens server-side
- The API generates a cryptographically random OTP using
RandomNumberGenerator.GetInt32. - The raw code is SHA-256 hashed with
SHA256.HashData; only the hash is written to the database. - The expiry timestamp is set to
UtcNow + ExpirationMinutes(clamped to the 10–15 minute range). - If the email exists and the rate-limit window has not been exceeded,
PasswordResetNotificationServicesends an HTML email containing the raw OTP.
Rate limiting
| Setting | Default | Description |
|---|---|---|
MaxRequestsPerWindow | 3 | Maximum OTP requests allowed within the window |
RequestWindowMinutes | 15 | Rolling window duration in minutes |
MaxRequestsPerWindow requests within RequestWindowMinutes, the stored procedure silently suppresses new OTP creation (the API still returns 200).
Step 2 — Reset the password
Submit the OTP code received by email together with the new password. Endpoint:POST /api/auth/reset-passwordAuth: Public (no token required) Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | ✅ | Must match the address used in Step 1 |
companyId | integer | ✅ | Same tenant identifier as Step 1 |
otpCode | string | ✅ | The numeric code from the email |
newPassword | string | ✅ | Must satisfy the password policy |
200 OK
Failed-attempt limit
| Setting | Default | Description |
|---|---|---|
MaxAttempts | 5 | Number of incorrect OTP submissions before the code is invalidated |
MaxAttempts failed verifications the OTP record is marked invalid and the user must request a new code.
OTP properties
| Setting | Default | Constraints | Description |
|---|---|---|---|
ExpirationMinutes | 10 | Clamped to 10–15 | Minutes until the OTP expires |
OtpDigits | 6 | Clamped to 6–8 | Length of the generated OTP code |
RandomNumberGenerator.GetInt32 from the System.Security.Cryptography namespace, which produces a cryptographically strong random integer. A 6-digit code has 900,000 possible values; combined with the MaxAttempts limit, brute-force is not feasible within the expiry window.
Configuration
Add the following sections toappsettings.json (or the relevant environment-specific override):
Email.Enabled must be true and Email.Host must be set to a reachable SMTP server for OTP emails to be delivered. When Enabled is false or Host is empty, PasswordResetNotificationService logs a warning and returns without sending — the OTP is still created in the database, but the user will never receive the code.Email configuration fields
| Field | Default | Description |
|---|---|---|
Enabled | false | Master switch. Set to true to enable email sending |
Host | "" | SMTP server hostname |
Port | 587 | SMTP port (587 for STARTTLS, 465 for implicit TLS) |
Username | "" | SMTP authentication username |
Password | "" | SMTP authentication password |
FromAddress | "" | Sender email address |
FromName | "ServiciosYa" | Display name shown in the From header |
EnableSsl | true | Whether to use STARTTLS/SSL for the SMTP connection |
Flow summary
Client calls POST /api/auth/forgot-password
Provides
email and companyId. The API always returns 200.API generates and hashes the OTP
Raw OTP is SHA-256 hashed. Only the hash is stored in the database with an expiry timestamp.
Email is sent (if SMTP is configured)
PasswordResetNotificationService sends an HTML email showing the raw OTP code and its expiry time.User submits OTP via POST /api/auth/reset-password
Provides
email, companyId, otpCode, and newPassword. The API hashes the submitted code and compares it to the stored hash.