> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/flutter/face-liveness.md).

# Face Liveness

Install and launch Face Liveness for Flutter. Learn prerequisites, CerttaLivenessConfiguration options, event streams, success and failure results, and error handling.

{% hint style="warning" %}
This guide covers **caf\_sdk 2.4.0** and above (Certta DevX). For the previous `CafSdk` sequential flow, see the [legacy documentation](https://docs.caf.io/caf-sdk/flutter/getting-started-with-the-sdk).
{% endhint %}

## Prerequisites

Before proceeding, ensure the Certta SDK is properly installed. If you haven't done this yet, please refer to our Installation Guide.

{% content-ref url="/pages/8imRjz3wgDSO5c2vhnO5" %}
[Installation Guide](/caf-sdk/flutter/installation-guide.md)
{% endcontent-ref %}

Enable `faceLiveness` (and `faceLivenessUI` if you want the built-in UI) in `caf-modules-config.json`. You must include at least one liveness provider.

## Starting Liveness

To start the Liveness flow, call `certta.liveness.open()` and pass a `CerttaLivenessConfiguration` object. Subscribe to `eventStream` **before** calling `open()` so you do not miss results.

{% hint style="info" %}
Set `useFaceLivenessUi` to `true` to use the built-in Certta UI. When `false`, the SDK runs the headless Face Liveness module.
{% endhint %}

```dart
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:caf_sdk/certta_sdk.dart';

final certta = CerttaSdk();

late final StreamSubscription<CerttaLivenessEvent> _livenessSub;

void listenToLiveness() {
  _livenessSub = certta.liveness.eventStream.listen((event) {
    if (event.success != null) {
      // Handle success — event.success!.response is a JWT
    } else if (event.failed != null) {
      // Handle business failure — see Handling Failures
    } else if (event.error != null) {
      // Handle technical error
    }
  });
}

Future<void> startLiveness() async {
  try {
    await certta.liveness.open(
      const CerttaLivenessConfiguration(
        maxRetryAttempts: 3,
        faceAuthEnabled: false,
        showLoading: true,
        useFaceLivenessUi: true,
      ),
    );
  } on PlatformException catch (e) {
    // Handle BRIDGE_EXCEPTION
  }
}
```

`open()` throws a `PlatformException` with code `BRIDGE_EXCEPTION` when the native mapper rejects the configuration.

### `CerttaLivenessConfiguration` parameters

| Parameter           | Default | Description                                                           |
| ------------------- | ------- | --------------------------------------------------------------------- |
| `maxRetryAttempts`  | `3`     | Maximum retries after a failed capture attempt.                       |
| `faceAuthEnabled`   | `false` | When **enabled**, the SDK performs **face authentication**.           |
| `showLoading`       | `true`  | Shows loading indicators during processing when **true**.             |
| `useFaceLivenessUi` | `false` | If **enabled**, the SDK uses the built-in Certta Face Liveness UI.    |
| `payFaceDebugMode`  | `false` | Enables debug mode for the PayFace (Fortface) provider. **iOS only**. |

## Understanding Liveness events and results

{% hint style="warning" %}
Ensure the JWT response is evaluated on the backend. This process must include validating the token's signature and verifying the `isAlive` and `isMatch` fields. Do not perform these validations on the client side.
{% endhint %}

`CerttaLivenessEvent` has exactly one populated field:

### `success` (`CerttaSuccess`)

The capture and liveness pipeline succeeded. **`response`** is a JWT with the result data from the Liveness execution (for example captured images or validation results).

### `failed` (`CerttaLivenessFailure`)

Liveness ran, but the outcome is a business failure.

| Field         | Description                                                                                         |
| ------------- | --------------------------------------------------------------------------------------------------- |
| `type`        | Failure model: `ImageCaptureFailure` or `FaceRecognitionFailure`.                                   |
| `cause`       | Identifier for diagnostics or UX messaging (for example `TOO_DARK`).                                |
| `description` | Optional human-readable description from the native SDK.                                            |
| `response`    | Signed payload. Present for `FaceRecognitionFailure` when capture succeeded but recognition failed. |

1. **`ImageCaptureFailure`:** problems during capture (environment, timeout, no face, provider-specific failure). There is typically no signed `response`.
2. **`FaceRecognitionFailure`:** capture succeeded, but face recognition / backend did not accept the result.

{% hint style="info" %}
To understand and handle the `cause` of the failure, see [Handling Failures](/caf-sdk/flutter/face-liveness/handling-failures.md).
{% endhint %}

### `error` (`CerttaError`)

Triggered when a technical blocker prevents the SDK from starting or finishing the process, such as denied camera permissions, no internet connection, or hardware initialization failures.

| Field   | Description                                       |
| ------- | ------------------------------------------------- |
| `type`  | Error identifier mapped from the native SDK.      |
| `cause` | Additional context for the failure, when present. |

| Event                 | Typical cause                                                                                                                       |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `InitializationError` | **`configure`** not called, empty token or user ID, or invalid **`maxRetryAttempts`**.                                              |
| `PermissionError`     | Camera (or related) permission denied.                                                                                              |
| `NetworkError`        | Connectivity or server-side issues surfaced as network class errors.                                                                |
| `SecurityError`       | Security checks failed.                                                                                                             |
| `UnknownError`        | Other failures not mapped to a specific case.                                                                                       |
| `Cancelled`           | Occurs when the user abandons the flow before completion, such as by pressing the back button or sending the app to the background. |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.caf.io/caf-sdk/flutter/face-liveness.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
