---
title: "Biometric enrollment (Enrollment) - Rest PKI Core"
description: "Biometric enrollment in Rest PKI Core: registers the user's face with a liveness check and stores it encrypted. See how to create the session."
canonical: "https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions/enrollment"
locale: "en"
product: "Rest PKI Core"
last_updated: "2026-10-12"
---

# Biometric enrollment (Enrollment) - Rest PKI Core

- Registers the user's biometric in the system through a face capture with a liveness check.
- The face image is processed and stored encrypted, to be used later in authentication or identification operations.

## Creating the session
To create an enrollment session, use the `StartEnrollmentSessionAsync` method of the client libs, passing a `StartBioEnrollmentSessionRequest`.

This method makes a `POST` request to `/api/bio/sessions/enrollment` [(Swagger)](https://core.pki.rest/swagger/index.html#operations-BioSessions-post_api_bio_sessions_enrollment).

### Parameters (`StartBioEnrollmentSessionRequest`)
| **Parameter**                          | **Required?**    | **Type** | **Description** |
| -------------------------------------- | ---------------- | -------- | --------------- |
| **ReturnUrl**                          | Conditional*     | String   | URL to redirect the user to after the biometric check. [(see details)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#redirect-flow-returnurl)
| **TrustedOrigin**                      | Conditional*     | String   | URL of your site where the widget is embedded. [(see details)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#embedded-flow-widgettrustedorigin)
| **PlatformPreference**                 | No               | Enum     | Sets the platform preference and the QR code behavior. [(see details)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#general-parameters)
| **SubjectIdentifier**                  | Yes              | String   | External identifier of the user. [(see details)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#user-identifier-subjectidentifier)
| **FaceCaptureProvider**                | No               | Enum     | Sets the biometric provider. [(see details)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#face-capture-session-parameters)
| **CaptureIdentificationDocument**      | No               | Bool     | If enabled, the user must capture an ID document right after the liveness check.
| **DangerousOverrideIfAlreadyEnrolled** | No               | Bool     | Whether the system allows an existing enrollment to be overwritten.

> **Tip**
>
> *You must pass at least one of the two parameters ([see the difference between ReturnUrl and TrustedOrigin](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#frontend-flows)):
> - `ReturnUrl` (for the redirect flow)
> - `TrustedOrigin` (for the widget)

### Response example

The request to `StartEnrollmentSessionAsync` returns the following response:

```json
{
  "sessionType": "Enrollment",
  "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sessionUrl": "string"
}
```

### Frontend integration
Once your backend has obtained the `sessionUrl` from the API, forward it to your frontend. From there, the flow follows the interface you chose:

- **Embedded flow (widget)**: your application passes the URL to the JavaScript component, which starts the capture inside your page.

- **Redirect flow**: your application sends the user to the URL received, where the capture takes place.

> **Tip**
>
> If you are unsure how to implement each model, see [Frontend flows](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions#frontend-flows).

---
## Completing the session

To complete an enrollment session, use the `CompleteEnrollmentSessionAsync` method of the client libs, passing a `CompleteBioSessionRequest`.

This method makes a `POST` request to `/api/bio/sessions/enrollment/completion` [(Swagger)](https://core.pki.rest/swagger/index.html#operations-BioSessions-post_api_bio_sessions_enrollment_completion).

This method is the final step. The ticket can be used only once.

> **Tip**
>
> Call the completion only at the end of the process, sending the ticket you received to validate the result and close the session.

### Response example

```json
{
  "subjectIdentifier": "string",
  "subjectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "livenessStatus": {
    "success": true,
    "attemptCount": 2
  },
  "idCaptureStatus": {
    "success": true,
    "matchedFace": true,
    "matchedFaceLevel": 1
  },
  "failure": "FaceNotFoundWithSufficientQuality",
  "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "success": true,
  "resultDataAvailable": true
}
```

> **Tip**
>
> Note that in this example the `subjectId` was returned because the enrollment was not completed: the failure code tells us that this user
> is already enrolled.

#### Field details

* **subjectIdentifier**: a name or Id that identifies the user of the session.
* **subjectId**: Id of the enrollment.
* **livenessStatus**:
    * **success**: whether the liveness check succeeded.
    * **attemptCount**: number of attempts made by the user.
* **idCaptureStatus**:
    * **success**: whether the document capture succeeded.
    * **matchedFace**: whether the person's face matched the photo on the document.
    * **matchedFaceLevel**: similarity level between the face and the document (`MatchLevel`).
* **failure**: tells whether a failure occurred during the session; see the list of failures below.
* **success**: whether the enrollment session succeeded.
* **resultDataAvailable**: if `true`, you can fetch the photos collected in the session.

##### Failures

| **Enum**                          | **Description**                                    |
| --------------------------------- | -------------------------------------------------- |
| FaceNotFoundWithSufficientQuality | The system could not detect a face sharp enough. It usually happens because of poor lighting, blur or a low-quality camera.
| FaceLiveness2dFailed              | The 2D liveness analysis detected that the face presented is not real.
| FaceCaptureFailed                 | A technical error or interruption happened during the image capture, preventing it from being processed.
| DocumentCaptureFailed             | The image of the ID document could not be captured or processed.
| FaceIdentityVerificationFailed    | The external identity verification failed.
| DuplicatesFound                   | During an enrollment, the system found that this biometric already belongs to another user registered in the database.
| AttemptsLimitReached              | The user exceeded the maximum number of attempts allowed for the biometric capture in the session.
| SessionAborted                    | The session was ended prematurely, by the user or by the system, before the process was completed.

## Checking the status

You can check the current state of a session at any time using its `sessionId`. This is useful to monitor whether the user has started the
session, or whether it has expired, even before it is completed.

> **Tip**
>
> Use `GetEnrollmentSessionStatusAsync` to follow the progress of an active session by its `sessionId`.

The response of this endpoint is exactly the same as the [response example of `CompleteEnrollmentSessionAsync`](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/bio-sessions/enrollment#response-example-1).

**Demos and samples**

- Live demo: [Enroll and authenticate your face](https://try.lacunasoftware.com/en/lacuna-bio/enroll-and-authenticate-your-face)
