
# Document + Face combined validation flow
{{<tags>}}

This guide explains how to run **Document validation** and **Face validation** as **one seamless flow**. The **front image of the captured document** can be extracted and used as the **reference** for the subsequent face (liveness) validation.

## **Overview**

The Truora SDK supports running Document validation and Face validation as a single, seamless user experience. Instead of two independent sessions, the two validations share one `userId`. The front image of the captured document is extracted by Truora and used as the biometric reference for the subsequent face (liveness) check. This eliminates the need to supply a separate reference photo and ensures the liveness comparison is always made against the live document.

## **How it works**

The flow consists of three sequential steps that your app orchestrates:

1. **Run a document validation** with `waitForResults: true` and a `finishViewConfiguration` that hides the finish screen on success but shows it on failure. When the document validation succeeds, the SDK dismisses its finish view and the user continues to the next validation.  
     
2. **Extract the face reference** from the completed document result by calling `getFaceReferenceImage()`. This returns the URL of the front image captured during document scanning.  
     
3. **Run a face validation** using the **same `userId`** and passing the extracted image as `referenceFace`. The SDK uses this image as the enrollment reference for the liveness comparison.

At the end of both steps your app holds two independent `ValidationResult` objects — one for the document, one for the face — both linked to the same `userId`.

## **Flow Diagram**

[Doc and face flow diagram][/images/illustrations/validations_sdk/doc_and_face_flow_diagram.png]

## **Requirements and Constraints**

### **`finishViewConfiguration` and `waitForResults` interaction**

Setting `finishViewConfiguration` implicitly enables result waiting — you do not need to explicitly set `waitForResults: true` alongside it. However, if you explicitly set `waitForResults: false` while also providing a `finishViewConfiguration`, the SDK treats this as a misconfiguration and returns a `TruoraValidationError` with code `20024` (`invalidConfiguration`). Setting `waitForResults: true` forces the `SDK` to show a finish screen for all validation statuses, you need to set the `finishViewConfiguration` explicitly to hide/show certain results

### **Both steps must share the same `userId`**

Use the same `userId` for the document validation and the face validation. The Truora backend links the two validations under the same enrollment session using this identifier.

### **Relation with `api key`**

The same `sdk api key` can be used for both validations, provided that they must have the same `userId` associated with it.

### **Configuration summary**

{{<table "table w-auto small m-auto text-center table-striped table-bordered">}}
| Field | Document step | Face step |
| --- | --- | --- |
| `waitForResults` | `true` required — set explicitly or implied by `finishViewConfiguration` | your choice |
| `finishViewConfiguration` | `success: hide, failure: show` — implicitly enables `waitForResults` | not needed |
| `referenceFace` | — | URL from `getFaceReferenceImage()` |
| `userId` | your user's ID | **same user ID** |
{{</table>}}

## **Examples**

{{<code2 "{\"java\": \"sdk_combined_flow_doc_face_java.java\", \"kotlin\": \"sdk_combined_flow_doc_face_kotlin.kt\", \"swift\": \"sdk_combined_flow_doc_face_swift.swift\", \"dart\": \"sdk_combined_flow_doc_face_dart.dart\", \"typescript\": \"sdk_combined_flow_doc_face_typescript.ts\"}" "Document + Face Combined Flow" >}}