Skip to main content

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.

Debuta uses facial verification as a trust layer in two distinct flows: registration (where a face is validated and saved before the account is fully created) and login (where the stored reference photo is compared against a live image as a second factor). All image data is transmitted as a base64-encoded string in the JSON request body — no multipart upload is used for these endpoints.
The facial reference photo is stored as the user’s profile_picture on Cloudinary and marks the account as is_verified: true. While it is visible on the profile, its primary purpose is identity confirmation — it is the photo taken during the verification step and is distinct from any additional photos a user may add to their gallery.

Authentication model

Three of the four endpoints are public (no JWT required) because they are called during the registration and login flows before a session token exists. The PUT /api/facial/update endpoint requires a valid token because it is used from inside the app by an already-authenticated user. POST /api/facial/register is a special case: it is public but accepts an optional JWT header. When called during registration it expects a userId in the request body; when called from a logged-in context (e.g. re-taking the photo from settings) it reads the user from the JWT and ignores userId.

Endpoints

POST /api/facial/verify

Validate that an image contains a human face.

POST /api/facial/register

Save a facial reference photo for a user.

POST /api/facial/login-verify

Compare a live photo against the stored reference.

PUT /api/facial/update

Replace the stored photo (authenticated users only).

POST /api/facial/verify

Validates that the submitted image contains a detectable human face. Called at registration step 2 before the account is created. If the image does not pass validation the client should prompt the user to retake the photo. Authentication: None (public endpoint). Content-Type: application/json

Request body

image
string
required
Base64-encoded image string, with or without a data:image/...;base64, prefix. Minimum decoded size of ~1 KB is enforced; maximum is ~10 MB.

Response 200

{
  "ok": true,
  "message": "Rostro verificado correctamente"
}
{
  "ok": false,
  "message": "No se detectó un rostro. Asegúrate de buena iluminación y que tu cara esté centrada."
}
ok
boolean
true if a valid face was detected; false otherwise.
message
string
Human-readable result description.

Error responses

StatusCondition
400image is missing, not a string, or smaller than 1 KB (invalid base64).
500Internal server error during image processing.

curl example

# Encode an image file to base64 and send it
IMAGE_B64=$(base64 -w 0 /path/to/selfie.jpg)

curl -X POST https://api.debuta.app/api/facial/verify \
  -H "Content-Type: application/json" \
  -d "{\"image\": \"${IMAGE_B64}\"}"

POST /api/facial/register

Uploads the facial reference photo to Cloudinary and saves it as the user’s profile_picture. Also sets is_verified: true on the user document. Accepts two calling modes:
  • Registration flow — no JWT; pass userId in the body.
  • Logged-in update — send a Bearer token; userId in the body is ignored.
Authentication: Optional Bearer JWT. If no token is present, userId must be in the body. Content-Type: application/json

Request body

image
string
required
Base64-encoded image. With or without data:image/...;base64, prefix. Maximum ~10 MB.
userId
string
MongoDB ObjectId of the user. Required when called without a JWT (registration flow). Ignored when a valid token is present.

Response 200

{
  "ok": true,
  "message": "Foto facial guardada correctamente",
  "is_verified": true,
  "profile_picture": "https://res.cloudinary.com/debuta/image/upload/v1/profiles/abc123.jpg"
}
ok
boolean
true on success.
message
string
Confirmation message.
is_verified
boolean
Always true after a successful registration — reflects the updated field on the user document.
profile_picture
string
Public Cloudinary URL of the saved photo.

Error responses

StatusCondition
400image is missing or invalid.
400image exceeds ~10 MB.
400Neither a JWT nor a userId body field was provided.
404User not found for the given userId or token.
502Cloudinary upload failed.

curl examples

# Registration flow — userId in body, no token
IMAGE_B64=$(base64 -w 0 /path/to/selfie.jpg)

curl -X POST https://api.debuta.app/api/facial/register \
  -H "Content-Type: application/json" \
  -d "{
    \"image\": \"${IMAGE_B64}\",
    \"userId\": \"665f000000000000000000aa\"
  }"

# Logged-in update — token in header, no userId needed
curl -X POST https://api.debuta.app/api/facial/register \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{\"image\": \"${IMAGE_B64}\"}"

POST /api/facial/login-verify

Compares a live selfie against the stored facial reference photo for a given email address. Used as a second factor during login after the password has been verified. If the user does not yet have a stored facial photo the endpoint returns ok: true to avoid blocking legacy accounts. Authentication: None (public endpoint). Content-Type: application/json

Request body

correo
string
required
Email address of the user attempting to log in.
image
string
required
Base64-encoded live photo for comparison. Same format rules as /api/facial/verify.

Response 200

{
  "ok": true,
  "message": "Rostro verificado correctamente",
  "hasFacialPhoto": true
}
{
  "ok": false,
  "message": "El rostro no coincide con el registrado. Intenta de nuevo."
}
ok
boolean
true if the face matches (or if no reference photo is stored); false on mismatch.
message
string
Human-readable result.
hasFacialPhoto
boolean
Included on success. false when the user has no stored reference photo and access was allowed unconditionally.

Error responses

StatusCondition
400correo is missing or image is invalid base64.
500Internal server error.
For security, the endpoint never reveals whether an email address exists in the system when returning ok: false. This prevents email enumeration attacks.

curl example

IMAGE_B64=$(base64 -w 0 /path/to/login-selfie.jpg)

curl -X POST https://api.debuta.app/api/facial/login-verify \
  -H "Content-Type: application/json" \
  -d "{
    \"correo\": \"sofia@example.com\",
    \"image\": \"${IMAGE_B64}\"
  }"

PUT /api/facial/update

Replaces the authenticated user’s stored facial reference photo. Functionally identical to calling POST /api/facial/register with a valid token, but the PUT method makes the intent explicit — this route is for updating an existing photo from inside the app (e.g. the Settings screen). Authentication: Bearer JWT required. Content-Type: application/json

Request body

image
string
required
Base64-encoded replacement photo. Maximum ~10 MB.

Response 200

{
  "ok": true,
  "message": "Foto facial guardada correctamente",
  "is_verified": true,
  "profile_picture": "https://res.cloudinary.com/debuta/image/upload/v1/profiles/new456.jpg"
}

Error responses

StatusCondition
400image is missing, invalid, or too large.
401Missing or invalid JWT.
404User record not found.
502Cloudinary upload failed.

curl example

IMAGE_B64=$(base64 -w 0 /path/to/new-selfie.jpg)

curl -X PUT https://api.debuta.app/api/facial/update \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{\"image\": \"${IMAGE_B64}\"}"

Registration flow overview

1

Validate face

Call POST /api/facial/verify with the captured selfie. If ok is false, ask the user to retake the photo.
2

Create account

Submit the registration form (name, email, password, etc.) to POST /api/auth/register. Save the returned userId.
3

Save reference photo

Call POST /api/facial/register with the same selfie base64 and the userId from step 2. The user is now marked is_verified: true.

Build docs developers (and LLMs) love