> 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/docs.facephi-en/rest-api/identity-api/identity-api-reference/authentication/authenticate-user-v3.md).

# Authenticate User V3

#### Description

This service provides persistence of Biometric Templates and facial Authentication 1:1 against stored templates. It supports two operational modes within a single Endpoint, determined by the request body:

* **Enroll Mode**: Validates the liveness check and performs facial Matching between a provided Biometric Template and a live capture, then persists the template associated with a `userId`.
* **Authenticate Mode**: Retrieves a previously stored template by `userId` and performs facial Matching 1:1 and liveness check validation against a new live capture.

#### Functionality

* **Enroll**: The `userId` together with the Biometric Template (`templateRaw`) and the best tokenized image (`bestImageToken`). The liveness check and facial Matching are validated. If both are successful, the template associated with the user is persisted. If the user already exists, the template is updated.
* **Authenticate**: The `userId` together with the `bestImageToken` of the current session. The stored template is retrieved and a 1:1 Matching is performed against the live capture. The authentication result is returned with the similarity score.

#### Use cases

1. **Client without prior Onboarding with Facephi**: During password recovery, the client performs an Onboarding that generates a Biometric Template. This template is enrolled through this Endpoint and is associated with a `userId`. Future password recoveries authenticate directly against the stored template without repeating the Onboarding.
2. **Client with prior Onboarding with Facephi**: The client already has a stored template. Subsequent authentications use the 1:1 Matching Flow against the stored template.

### Integration

Requires the implementation of the **Selphi Mobile Widget** or the **Selphi Web Widget** to generate the `bestImageToken` and the Biometric Template (`templateRaw`).

### Endpoint

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

### Headers

| Header       | Type   | Required | Description                         |
| ------------ | ------ | -------- | ----------------------------------- |
| x-api-key    | String | Yes      | Tenant API Key                      |
| Content-Type | String | Yes      | `application/json`                  |
| family       | String | No       | Required family Header for Tracking |

> All calls to the Endpoints with Tracking in Identity Platform must contain the header `family`.

***

### Enroll Mode

Enrolls or updates a Biometric Template for a user. It requires the liveness check validation and facial Matching to be successful before persisting the template.

The presence of the field `templateRaw` in the request body activates this mode.

#### Request body

Content-Type: application/json

#### Parameters

| Parameter      | Type (Content)  | Required | Description                                                                                                                                                                                                |
| -------------- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userId         | String          | Yes      | Unique user identifier. Must have at least 2 characters.                                                                                                                                                   |
| templateRaw    | String (Base64) | Yes      | Facial Biometric Template generated from the best image during the Onboarding process. Its presence activates the **Enroll mode**.                                                                         |
| bestImageToken | String (Base64) | Yes      | Best tokenized facial image generated by the Selphi Widget. It is used for liveness check validation and facial Matching against the `templateRaw` to verify that they correspond to the same live person. |
| tracking       | JSON Object     | No       | Object containing Tracking information.                                                                                                                                                                    |
| extraData      | String (Base64) | No       | Token generated by the SDK Mobile/Web that contains tokenized Tracking information.                                                                                                                        |
| operationId    | String          | No       | Operation identifier generated by the SDK Mobile/Web.                                                                                                                                                      |

#### Request example: Enroll

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

#### Enroll behavior

1. **liveness check**: Validates that the `bestImageToken` corresponds to a live person.
2. **Facial Matching**: Performs a 1:1 Matching between `templateRaw` and `bestImageToken` to verify that they belong to the same person.
3. **Persistence**: If both checks pass, queries the `userId`:
   * If the user **does not exist**: creates the user and stores the template.
   * If the user **already exists**: updates the stored template with the new one.
4. **TTL** (if configured): The template Token has a configurable validity period for use in the service. Once expired, it is no longer valid for Enroll.

***

### Authenticate Mode

Authenticates a user by comparing a live capture against their previously stored Biometric Template. This mode is activated when `templateRaw` **do not** is included in the request body.

> **Important**: The user must have been previously enrolled (through Enroll mode or the v1/v2 self-registration Flow) before they can be authenticated. Attempting to authenticate an unenrolled user returns an error `User not found`.

#### Parameters

| Parameter      | Type (Content)  | Required | Description                                                                                                                                                 |
| -------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userId         | String          | Yes      | Unique identifier of the user to authenticate. Must have at least 2 characters.                                                                             |
| bestImageToken | String (Base64) | Yes      | Best tokenized facial image from the current authentication session. It is used for liveness check validation and 1:1 Matching against the stored template. |
| tracking       | JSON Object     | No       | Object containing Tracking information.                                                                                                                     |
| extraData      | String (Base64) | No       | Token generated by the SDK Mobile/Web that contains tokenized Tracking information.                                                                         |
| operationId    | String          | No       | Operation identifier generated by the SDK Mobile/Web.                                                                                                       |

#### Request example: Authenticate

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

#### Authentication behavior

1. **User lookup**: Retrieves the stored template associated with the `userId`.
2. **TTL check**: If the template has a configured expiration and it has been exceeded, returns `Template expired`.
3. **liveness check**: Validates that the `bestImageToken` corresponds to a live person.
4. **Facial Matching**: Performs a 1:1 Matching between the stored template and the `bestImageToken`.
5. **Result**: Returns the Matching result including similarity score, authentication status, and liveness check diagnosis.

***

### Responses

#### 200 Success

#### Response parameters

| Identifier                        | Type    | Description                                                                                                                                           |
| --------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| serviceResultCode                 | Integer | Code indicating the overall result of the service execution. See the Service Result Code table below.                                                 |
| serviceResultLog                  | String  | Descriptive field for the execution result. Empty in case of success.                                                                                 |
| serviceFacialSimilarityResult     | Float   | Value indicating the facial similarity between the template and the bestImageToken. 1.0 = 100%. Present only when Biometric Matching is performed.    |
| serviceFacialAuthenticationLog    | String  | Descriptive field for the facial Authentication result (e.g. "Positive", "Negative", "Uncertain"). Present only when Biometric Matching is performed. |
| serviceFacialAuthenticationResult | Integer | Code indicating the result of facial Authentication. See Table 2 - Service Facial Authentication Result.                                              |
| serviceLivenessLog                | String  | Descriptive field for the passive liveness check result (e.g. "Live", "Spoof"). Present only when the liveness check is evaluated.                    |
| serviceLivenessResult             | Integer | Code indicating the result of the passive liveness check evaluation. See Table 3 - Service Liveness Result.                                           |
| timestamp                         | String  | Timestamp (UTC) of the response in format: YYYY-MM-DDThh:flag\_mm:ssZ                                                                                 |
| transactionId                     | String  | Transaction identifier associated with the request processed by the API.                                                                              |

#### Service Result Code

The `serviceResultCode` indicates the overall result of the service execution:

| serviceResultCode | Description                                                           | HTTP code |
| ----------------- | --------------------------------------------------------------------- | --------- |
| 0                 | Successful operation (Enroll completed or user authenticated).        | 200       |
| -101              | The bestImageToken does not correspond to a live person.              | 200       |
| -102              | User Authentication failed — negative facial match.                   | 200       |
| -103              | User not found (authenticate mode only).                              | 404       |
| -104              | Template not found — the user exists but has no stored template.      | 404       |
| -105              | Template expired — TTL exceeded, the template is no longer available. | 200       |

#### Service Liveness Result

The `serviceLivenessResult` indicates the result of the passive liveness check evaluation:

<details>

<summary>Service Liveness Result</summary>

<table><thead><tr><th width="101.947998046875">Code</th><th>Result</th><th width="251.6302490234375">Description</th></tr></thead><tbody><tr><td>0</td><td>None</td><td>The liveness check could not be evaluated.</td></tr><tr><td>1</td><td>Spoof</td><td>DEPRECATED. Use 'NoLive' instead.</td></tr><tr><td>2</td><td>Uncertain</td><td>DEPRECATED</td></tr><tr><td>3</td><td>Live</td><td>The subject is assumed to be alive.</td></tr><tr><td>4</td><td>NoneBecauseBadQuality</td><td>The liveness check could not be evaluated due to poor image quality.</td></tr><tr><td>5</td><td>NoneBecauseFaceTooClose</td><td>The liveness check could not be evaluated because the detected faces are too close to the edges.</td></tr><tr><td>6</td><td>NoneBecauseFaceNotFound</td><td>The liveness check could not be evaluated because no faces were detected.</td></tr><tr><td>7</td><td>NoneBecauseFaceTooSmall</td><td>The liveness check could not be evaluated because the detected faces are too small.</td></tr><tr><td>8</td><td>NoneBecauseAngleTooLarge</td><td>The liveness check could not be evaluated because the angle between faces exceeds the allowed limit.</td></tr><tr><td>9</td><td>NoneBecauseImageDataError</td><td>The liveness check could not be evaluated due to image format errors.</td></tr><tr><td>10</td><td>NoneBecauseInternalError</td><td>The liveness check could not be evaluated due to an internal error.</td></tr><tr><td>11</td><td>NoneBecauseImagePreprocessError</td><td>The liveness check could not be evaluated due to an image preprocessing error.</td></tr><tr><td>12</td><td>NoneBecauseTooManyFaces</td><td>The liveness check could not be evaluated because too many faces were detected in the image.</td></tr><tr><td>13</td><td>NoneBecauseFaceTooCloseToBorder</td><td>The liveness check could not be evaluated because the face is too close to the edge.</td></tr><tr><td>14</td><td>NoneBecauseFaceCropped</td><td>The liveness check could not be evaluated because the face is cropped.</td></tr><tr><td>15</td><td>NoneBecauseLicenseError</td><td>The liveness check could not be evaluated due to a license error.</td></tr><tr><td>16</td><td>NoneBecauseFaceOccluded</td><td>The liveness check could not be evaluated because the face is occluded.</td></tr><tr><td>17</td><td>NoLive</td><td>No life was detected.</td></tr><tr><td>18</td><td>NoneBecauseEyesClosed</td><td>The liveness check could not be evaluated because the person's eyes are closed.</td></tr></tbody></table>

</details>

#### Service Facial Authentication Result

The `serviceFacialAuthenticationResult` indicates the result of the facial matching operations:

<details>

<summary>Service Facial Authentication Result</summary>

| Code | Result                           | Description                                                                                                                                                                                                |
| ---- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0    | NONE                             | Facial verification could not be performed.                                                                                                                                                                |
| 1    | NEGATIVE                         | The process was executed successfully. The comparison of the facial pattern of the faces does not match.                                                                                                   |
| 3    | POSITIVE                         | The process was executed successfully. The comparison of the facial pattern of the faces is positive. The value of `serviceFacialSimilarityResult` indicates the % similarity between the compared images. |
| 4    | NONE BECAUSE POSE EXCEED         | Facial verification could not be performed due to the face position.                                                                                                                                       |
| 5    | NONE BECAUSE INVALID EXTRACTIONS | Facial verification could not be performed due to problems in extracting the facial pattern.                                                                                                               |

</details>

#### Response example: Successful Enroll

```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"
}
```

#### Response example: Successful Authentication (positive match)

```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"
}
```

#### Response example: Negative match

```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"
}
```

#### Response example: User not found

```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"
}
```

***

### Differences with v1/v2

| Aspect                                    | v1/v2                         | v3                                                                  |
| ----------------------------------------- | ----------------------------- | ------------------------------------------------------------------- |
| Template field in request                 | `registeredTemplateRaw`       | `templateRaw`                                                       |
| `merchantReferenceId`                     | Required                      | Not used                                                            |
| `image` / `template` as input             | Supported                     | Not supported — only `templateRaw` + `bestImageToken`               |
| Self-registration on first Authentication | Yes                           | No — explicit Enroll required                                       |
| Template in the response                  | Yes (`registeredTemplateRaw`) | No (not returned for security — avoids unnecessary transfer of PII) |
| Liveness check + match on Enroll          | N/A                           | Required before persisting                                          |
| TTL / template expiration                 | Not supported                 | Supported (configurable by tenant via `templateTTLSeconds`)         |
| New error codes                           | N/A                           | `-104` (Template not found), `-105` (Template expired)              |

***
