> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/api-rest/identity-api/identity-api-reference/authentication/authenticate-user-v3.md).

# Authenticate User V3

#### Descripción

Este servicio proporciona persistencia de plantillas biométricas y autenticación facial 1:1 contra plantillas almacenadas. Soporta dos modos operativos dentro de un único endpoint, determinados por el cuerpo de la solicitud:

* **Modo Enroll**: Valida la prueba de vida y realiza un matching facial entre una plantilla biométrica proporcionada y una captura en vivo, y luego persiste la plantilla asociada a un `userId`.
* **Modo Authenticate**: Recupera una plantilla previamente almacenada por `userId` y realiza un matching facial 1:1 y validación de prueba de vida contra una nueva captura en vivo.

#### Funcionalidad

* **Enroll**: Se envía el `userId` junto con la plantilla biométrica (`templateRaw`) y la mejor imagen tokenizada (`bestImageToken`). Se valida la prueba de vida y el matching facial. Si ambos son exitosos, se persiste la plantilla asociada al usuario. Si el usuario ya existe, se actualiza la plantilla.
* **Authenticate**: Se envía el `userId` junto con el `bestImageToken` de la sesión actual. Se recupera la plantilla almacenada y se realiza un matching 1:1 contra la captura en vivo. Se devuelve el resultado de autenticación con la puntuación de similitud.

#### Casos de uso

1. **Cliente sin onboarding previo con Facephi**: Durante la recuperación de contraseña, el cliente realiza un onboarding que genera una plantilla biométrica. Esta plantilla se enrolla a través de este endpoint y se asocia a un `userId`. Las futuras recuperaciones de contraseña autentican directamente contra la plantilla almacenada sin repetir el onboarding.
2. **Cliente con onboarding previo con Facephi**: El cliente ya tiene una plantilla almacenada. Las autenticaciones posteriores utilizan el flujo de matching 1:1 contra la plantilla almacenada.

### Integración

Requiere la implementación del **widget Selphi Mobile** o del **widget Selphi Web** para generar el `bestImageToken` y la plantilla biométrica (`templateRaw`).

### Endpoint

```
POST /services/authenticateUser/v3
```

### Headers

| Header       | Tipo   | Obligatorio | Descripción                               |
| ------------ | ------ | ----------- | ----------------------------------------- |
| x-api-key    | String | Sí          | API key del tenant                        |
| Content-Type | String | Sí          | `application/json`                        |
| family       | String | No          | Header de familia requerido para tracking |

> Todas las llamadas a los Endpoints con tracking en Identity Platform deben contener el header `family`.

***

### Modo Enroll

Enrolla o actualiza una plantilla biométrica para un usuario. Requiere que la validación de prueba de vida y el matching facial sean exitosos antes de persistir la plantilla.

La presencia del campo `templateRaw` en el cuerpo de la solicitud activa este modo.

#### Cuerpo de la solicitud

Content-Type: application/json

#### Parámetros

| Parámetro      | Tipo (Contenido) | Obligatorio | Descripción                                                                                                                                                                                                   |
| -------------- | ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userId         | String           | Sí          | Identificador único del usuario. Debe tener al menos 2 caracteres.                                                                                                                                            |
| templateRaw    | String (Base64)  | Sí          | Plantilla biométrica facial generada a partir de la mejor imagen durante el proceso de onboarding. Su presencia activa el **modo enroll**.                                                                    |
| bestImageToken | String (Base64)  | Sí          | Mejor imagen facial tokenizada generada por el widget Selphi. Se utiliza para validación de prueba de vida y matching facial contra el `templateRaw` para verificar que corresponden a la misma persona viva. |
| tracking       | JSON Object      | No          | Objeto que contiene información de tracking.                                                                                                                                                                  |
| extraData      | String (Base64)  | No          | Token generado por el SDK Mobile/Web que contiene información de tracking tokenizada.                                                                                                                         |
| operationId    | String           | No          | Identificador de operación generado por el SDK Mobile/Web.                                                                                                                                                    |

#### Ejemplo de solicitud: Enroll

```json
{
    "userId": "user-001",
    "templateRaw": "BAEBAQIxLiHIhMPQWaUo…",
    "bestImageToken": "BgEBAQJksxGtVd++lRjN…",
    "tracking": {
        "extraData": "BQABAQG2gBNjuHN...",
        "operationId": "123e4567-e89b-12d3-a456-426614174000"
    }
}
```

#### Comportamiento del enroll

1. **Prueba de vida**: Valida que el `bestImageToken` corresponde a una persona viva.
2. **Matching facial**: Realiza un matching 1:1 entre `templateRaw` y `bestImageToken` para verificar que pertenecen a la misma persona.
3. **Persistencia**: Si ambas comprobaciones pasan, consulta el `userId`:
   * Si el usuario **no existe**: crea el usuario y almacena la plantilla.
   * Si el usuario **ya existe**: actualiza la plantilla almacenada con la nueva.
4. **TTL** (si está configurado): El token de la plantilla tiene un tiempo de validez configurable para su uso en el servicio. Una vez expirado, deja de ser válido para el enroll.

***

### Modo Authenticate

Autentica a un usuario comparando una captura en vivo contra su plantilla biométrica previamente almacenada. Este modo se activa cuando `templateRaw` **no** está incluido en el cuerpo de la solicitud.

> **Importante**: El usuario debe haber sido previamente enrollado (a través del modo enroll o del flujo de auto-registro de v1/v2) antes de poder ser autenticado. Intentar autenticar a un usuario no enrollado devuelve un error `User not found`.

#### Parámetros

| Parámetro      | Tipo (Contenido) | Obligatorio | Descripción                                                                                                                                                      |
| -------------- | ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userId         | String           | Sí          | Identificador único del usuario a autenticar. Debe tener al menos 2 caracteres.                                                                                  |
| bestImageToken | String (Base64)  | Sí          | Mejor imagen facial tokenizada de la sesión de autenticación actual. Se utiliza para validación de prueba de vida y matching 1:1 contra la plantilla almacenada. |
| tracking       | JSON Object      | No          | Objeto que contiene información de tracking.                                                                                                                     |
| extraData      | String (Base64)  | No          | Token generado por el SDK Mobile/Web que contiene información de tracking tokenizada.                                                                            |
| operationId    | String           | No          | Identificador de operación generado por el SDK Mobile/Web.                                                                                                       |

#### Ejemplo de solicitud: Authenticate

```json
{
    "userId": "user-001",
    "bestImageToken": "BgEBAQJksxGtVd++lRjN…",
    "tracking": {
        "extraData": "BQABAQG2gBNjuHN...",
        "operationId": "123e4567-e89b-12d3-a456-426614174000"
    }
}
```

#### Comportamiento de la autenticación

1. **Búsqueda de usuario**: Recupera la plantilla almacenada asociada al `userId`.
2. **Comprobación de TTL**: Si la plantilla tiene una expiración configurada y se ha superado, devuelve `Template expired`.
3. **Prueba de vida**: Valida que el `bestImageToken` corresponde a una persona viva.
4. **Matching facial**: Realiza un matching 1:1 entre la plantilla almacenada y el `bestImageToken`.
5. **Resultado**: Devuelve el resultado del matching incluyendo puntuación de similitud, estado de autenticación y diagnóstico de prueba de vida.

***

### Respuestas

#### 200 Éxito

#### Parámetros de respuesta

| Identificador                     | Tipo    | Descripción                                                                                                                                                |
| --------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| serviceResultCode                 | Integer | Código que indica el resultado general de la ejecución del servicio. Ver la tabla de Service Result Code a continuación.                                   |
| serviceResultLog                  | String  | Campo descriptivo del resultado de la ejecución. Vacío en caso de éxito.                                                                                   |
| serviceFacialSimilarityResult     | Float   | Valor que indica la similitud facial entre la plantilla y el bestImageToken. 1.0 = 100%. Solo presente cuando se realiza matching biométrico.              |
| serviceFacialAuthenticationLog    | String  | Campo descriptivo del resultado de la autenticación facial (ej. "Positive", "Negative", "Uncertain"). Solo presente cuando se realiza matching biométrico. |
| serviceFacialAuthenticationResult | Integer | Código que indica el resultado de la autenticación facial. Ver Tabla 2 - Service Facial Authentication Result.                                             |
| serviceLivenessLog                | String  | Campo descriptivo del resultado de la prueba de vida pasiva (ej. "Live", "Spoof"). Solo presente cuando se evalúa la prueba de vida.                       |
| serviceLivenessResult             | Integer | Código que indica el resultado de la evaluación de prueba de vida pasiva. Ver Tabla 3 - Service Liveness Result.                                           |
| timestamp                         | String  | Timestamp (UTC) de la respuesta en formato: YYYY-MM-DDThh:flag\_mm:ssZ                                                                                     |
| transactionId                     | String  | Identificador de transacción asociado a la solicitud procesada por la API.                                                                                 |

#### Service Result Code

El `serviceResultCode` indica el resultado general de la ejecución del servicio:

| serviceResultCode | Descripción                                                                     | Código HTTP |
| ----------------- | ------------------------------------------------------------------------------- | ----------- |
| 0                 | Operación exitosa (enroll completado o usuario autenticado).                    | 200         |
| -101              | El bestImageToken no corresponde a una persona viva.                            | 200         |
| -102              | Autenticación de usuario fallida — match facial negativo.                       | 200         |
| -103              | Usuario no encontrado (solo modo authenticate).                                 | 404         |
| -104              | Plantilla no encontrada — el usuario existe pero no tiene plantilla almacenada. | 404         |
| -105              | Plantilla expirada — TTL superado, la plantilla ya no está disponible.          | 200         |

#### Service Liveness Result

El `serviceLivenessResult` indica el resultado de la evaluación de la prueba de vida pasiva:

<details>

<summary>Service Liveness Result</summary>

<table><thead><tr><th width="101.947998046875">Código</th><th>Resultado</th><th width="251.6302490234375">Descripción</th></tr></thead><tbody><tr><td>0</td><td>None</td><td>No se pudo evaluar la prueba de vida.</td></tr><tr><td>1</td><td>Spoof</td><td>DEPRECADO. Usar 'NoLive' en su lugar.</td></tr><tr><td>2</td><td>Uncertain</td><td>DEPRECADO</td></tr><tr><td>3</td><td>Live</td><td>Se asume que el sujeto está vivo.</td></tr><tr><td>4</td><td>NoneBecauseBadQuality</td><td>No se pudo evaluar la prueba de vida debido a la mala calidad de la imagen.</td></tr><tr><td>5</td><td>NoneBecauseFaceTooClose</td><td>No se pudo evaluar la prueba de vida porque los rostros detectados están muy cerca de los bordes.</td></tr><tr><td>6</td><td>NoneBecauseFaceNotFound</td><td>No se pudo evaluar la prueba de vida porque no se detectaron rostros.</td></tr><tr><td>7</td><td>NoneBecauseFaceTooSmall</td><td>No se pudo evaluar la prueba de vida porque los rostros detectados son muy pequeños.</td></tr><tr><td>8</td><td>NoneBecauseAngleTooLarge</td><td>No se pudo evaluar la prueba de vida porque el ángulo entre rostros excede el límite permitido.</td></tr><tr><td>9</td><td>NoneBecauseImageDataError</td><td>No se pudo evaluar la prueba de vida debido a errores en el formato de la imagen.</td></tr><tr><td>10</td><td>NoneBecauseInternalError</td><td>No se pudo evaluar la prueba de vida debido a un error interno.</td></tr><tr><td>11</td><td>NoneBecauseImagePreprocessError</td><td>No se pudo evaluar la prueba de vida debido a un error en el preprocesamiento de la imagen.</td></tr><tr><td>12</td><td>NoneBecauseTooManyFaces</td><td>No se pudo evaluar la prueba de vida porque se detectaron demasiados rostros en la imagen.</td></tr><tr><td>13</td><td>NoneBecauseFaceTooCloseToBorder</td><td>No se pudo evaluar la prueba de vida porque el rostro está muy cerca del borde.</td></tr><tr><td>14</td><td>NoneBecauseFaceCropped</td><td>No se pudo evaluar la prueba de vida porque el rostro está recortado.</td></tr><tr><td>15</td><td>NoneBecauseLicenseError</td><td>No se pudo evaluar la prueba de vida debido a un error de licencia.</td></tr><tr><td>16</td><td>NoneBecauseFaceOccluded</td><td>No se pudo evaluar la prueba de vida porque el rostro está ocluido.</td></tr><tr><td>17</td><td>NoLive</td><td>No se detectó vida.</td></tr><tr><td>18</td><td>NoneBecauseEyesClosed</td><td>No se pudo evaluar la prueba de vida porque los ojos de la persona están cerrados.</td></tr></tbody></table>

</details>

#### Service Facial Authentication Result

El `serviceFacialAuthenticationResult` indica el resultado de las operaciones de coincidencia facial:

<details>

<summary>Service Facial Authentication Result</summary>

| Código | Resultado                        | Descripción                                                                                                                                                                                           |
| ------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0      | NONE                             | No se pudo realizar la verificación facial.                                                                                                                                                           |
| 1      | NEGATIVE                         | El proceso se ejecutó correctamente. La comparación del patrón facial de los rostros no coincide.                                                                                                     |
| 3      | POSITIVE                         | El proceso se ejecutó correctamente. La comparación del patrón facial de los rostros es positiva. El valor de `serviceFacialSimilarityResult` indica el % de similitud entre las imágenes comparadas. |
| 4      | NONE BECAUSE POSE EXCEED         | No se pudo realizar la verificación facial debido a la posición del rostro.                                                                                                                           |
| 5      | NONE BECAUSE INVALID EXTRACTIONS | No se pudo realizar la verificación facial debido a problemas en la extracción del patrón facial.                                                                                                     |

</details>

#### Ejemplo de respuesta: Enroll exitoso

```json
{
    "serviceResultCode": 0,
    "serviceResultLog": "",
    "serviceFacialSimilarityResult": 0.9812,
    "serviceFacialAuthenticationLog": "Positive",
    "serviceFacialAuthenticationResult": 3,
    "serviceLivenessLog": "Live",
    "serviceLivenessResult": 3,
    "timestamp": "2026-04-20T15:12:07Z",
    "transactionId": "cd13a168-6eb0-4afd-bc88-408ca6a73437"
}
```

#### Ejemplo de respuesta: Autenticación exitosa (match positivo)

```json
{
    "serviceResultCode": 0,
    "serviceResultLog": "",
    "serviceFacialSimilarityResult": 0.9812,
    "serviceFacialAuthenticationLog": "Positive",
    "serviceFacialAuthenticationResult": 3,
    "serviceLivenessLog": "Live",
    "serviceLivenessResult": 3,
    "timestamp": "2026-04-20T15:12:28Z",
    "transactionId": "1ada7f96-44f2-48f1-87a5-0359621ae7a1"
}
```

#### Ejemplo de respuesta: Match negativo

```json
{
    "serviceResultCode": -102,
    "serviceResultLog": "User authentication failed",
    "serviceFacialSimilarityResult": 0.0192,
    "serviceFacialAuthenticationLog": "Negative",
    "serviceFacialAuthenticationResult": 1,
    "serviceLivenessLog": "Live",
    "serviceLivenessResult": 3,
    "timestamp": "2026-04-20T15:34:47Z",
    "transactionId": "d6e29c6c-0da2-4620-9ca7-f483c6950d72"
}
```

#### Ejemplo de respuesta: Usuario no encontrado

```json
{
    "serviceResultCode": -103,
    "serviceResultLog": "User not found",
    "timestamp": "2026-04-20T15:12:29Z",
    "transactionId": "ca61856d-0eb8-49ca-8178-66346e0c75ab"
}
```

#### 400 Bad Request

```json
{
    "status": 400,
    "title": "Bad Request",
    "detail": "Invalid request.",
    "type": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400",
    "errors": [
        "userId is required"
    ]
}
```

#### 401 Unauthorized

```json
{
    "message": "Unauthorized"
}
```

#### 403 Forbidden

```json
{
    "Message": "User is not authorized to access this resource with an explicit deny"
}
```

#### 404 Not Found

```json
{
    "serviceResultCode": -103,
    "serviceResultLog": "User not found",
    "timestamp": "2026-04-20T15:12:29Z",
    "transactionId": "ca61856d-0eb8-49ca-8178-66346e0c75ab"
}
```

#### 502 Bad Gateway

```json
{
    "status": 502,
    "title": "Bad Gateway",
    "detail": "Server got an invalid response.",
    "type": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502"
}
```

#### 504 Gateway Timeout

```json
{
    "message": "Endpoint request timed out"
}
```

***

### Diferencias con v1/v2

| Aspecto                                | v1/v2                        | v3                                                                         |
| -------------------------------------- | ---------------------------- | -------------------------------------------------------------------------- |
| Campo de plantilla en solicitud        | `registeredTemplateRaw`      | `templateRaw`                                                              |
| `merchantReferenceId`                  | Obligatorio                  | No se utiliza                                                              |
| `image` / `template` como input        | Soportado                    | No soportado — solo `templateRaw` + `bestImageToken`                       |
| Auto-registro en primera autenticación | Sí                           | No — requiere enroll explícito                                             |
| Plantilla en la respuesta              | Sí (`registeredTemplateRaw`) | No (no se devuelve por seguridad — evita transferencia innecesaria de PII) |
| Prueba de vida + match en enroll       | N/A                          | Obligatorio antes de persistir                                             |
| TTL / expiración de plantilla          | No soportado                 | Soportado (configurable por tenant mediante `templateTTLSeconds`)          |
| Nuevos códigos de error                | N/A                          | `-104` (Plantilla no encontrada), `-105` (Plantilla expirada)              |

***
