Debuta’s password recovery flow is a three-step process: request a code, verify it, then submit the new password. A random 6-digit code is generated, bcrypt-hashed before storage, and delivered to the user’s inbox via Nodemailer. The code expires after 15 minutes. All three endpoints are public — no JWT is required.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/desarrolladorandres2026-gif/Native-tailwind/llms.txt
Use this file to discover all available pages before exploring further.
For security,
POST /api/password/forgot always returns the same response message regardless of whether the email exists in the database. This prevents account enumeration attacks.The three-step flow
Send a verification code — POST /api/password/forgot
Generates a 6-digit numeric code, bcrypt-hashes it, stores it on the user document with a 15-minute expiry, and sends the plaintext code to the user’s email via Nodemailer.Auth required: NoThis response is returned whether or not the email exists in the system.
Request body
The email address associated with the account. Whitespace is trimmed and the value is normalised to lowercase before the lookup.
Validation
correomust pass a basic email format check (/^[^\s@]+@[^\s@]+\.[^\s@]+$/). Sends400if invalid.- If the email is not found, the endpoint still returns
200with the neutral message below.
Response — 200 OK
Storage details
The following fields are updated on theUsuario document:| Field | Value |
|---|---|
resetPasswordCode | bcrypt hash (cost 10) of the 6-digit code. Field is select: false and never returned in responses. |
resetPasswordExpires | Date.now() + 15 × 60 × 1000 — 15 minutes from request time |
Error responses
| Status | Condition |
|---|---|
400 | correo is missing or fails email format validation |
500 | Internal server error or Nodemailer failure |
curl example
Validate the code — POST /api/password/verify
Checks the submitted code against the stored hash without changing the password. This is the intermediate validation step that unlocks the new-password form in the UI. The code and expiry are not cleared at this stage — they remain valid until
POST /api/password/reset is called.Auth required: NoRequest body
The account’s email address.
The 6-digit code the user received by email. Leading/trailing whitespace is trimmed before comparison.
Validation
The endpoint looks up a user whosecorreo matches and whose resetPasswordExpires is still in the future ($gt: new Date()). If the code has expired, the user document won’t be found and a 400 is returned.Response — 200 OK
Always
true on a 200 response. The app uses this flag to enable the new-password input.Error responses
| Status | Condition |
|---|---|
400 | correo or code missing |
400 | Code has expired (more than 15 minutes since forgot was called) |
400 | Code does not match the stored hash |
500 | Internal server error |
curl example
Reset the password — POST /api/password/reset
Performs a final code validation, sets the new password (the
pre-save hook bcrypt-hashes it automatically), then clears resetPasswordCode and resetPasswordExpires from the document so the code cannot be reused.Auth required: NoRequest body
The account’s email address.
The same 6-digit code from the email. Re-validated here against the stored hash.
The new plaintext password. Minimum 6 characters. The bcrypt
pre-save hook on the Usuario model hashes it before it is persisted.Response — 200 OK
Post-reset state
| Field | After reset |
|---|---|
password | New bcrypt hash |
resetPasswordCode | null |
resetPasswordExpires | null |
Error responses
| Status | Condition |
|---|---|
400 | Any of correo, code, or nuevaPassword is missing |
400 | nuevaPassword is shorter than 6 characters |
400 | Code has expired |
400 | Code does not match the stored hash |
500 | Internal server error |