# QES (Qualified Electronic Signature)

The QES (Qualified Electronic Signature) module shows the user documents to sign, collects their consent, and captures a Qualified Electronic Signature (QES), the highest-assurance electronic signature under the [EU eIDAS Regulation](https://eur-lex.europa.eu/eli/reg/2014/910/oj/eng). A qualified certificate from a Qualified Trust Service Provider (QTSP) backs the signature, making it legally equivalent to a handwritten signature across EU member states.

For an overview of this module and how it works, see [Qualified Electronic Signature](https://developer.incode.com/docs/qualified-electronic-signature).

How you use this module depends on your [integration pattern](https://developer.incode.com/docs/android-common-implementation-patterns#integration-patterns). In Patterns 1 and 2, you add the module to a `FlowConfig` in code as shown on this page. In Pattern 3, you define your modules and configuration in Dashboard as a Flow or Workflow and reference it by ID with `startFlow()` or `startWorkflow()` as shown on [Run Flows Configured in Dashboard](https://developer.incode.com/docs/android-run-flows-configured-online).

## Add QES

1. Add identity check modules before QES. This can include [ID Scan](https://developer.incode.com/docs/android-id-scan) and[ Selfie Scan](https://developer.incode.com/docs/android-selfie-scan)​.
2. Add the module with `addQES(qes)`.

   ```kotlin
   flowConfigBuilder.addQES(qes)
   ```
   ```java
   flowConfigBuilder.addQES(qes);
   ```

### Example

The example below builds a `QES` module that downloads the signed PDF, adds it to the flow, and listens for the result through `onQESCompleted()`.

```kotlin
val qes = QES.Builder()
    .setDownloadDocument(true)
    .build()

val flowConfig = FlowConfig.Builder()
    .addQES(qes)
    .build()

val onboardingListener = object : OnboardingListener() {
    override fun onQESCompleted(qesResult: QESResult) {
        // QES step finished. Process the result.
    }
}

IncodeWelcome.getInstance()
    .startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener)
```
```java
QES qes = new QES.Builder()
    .setDownloadDocument(true)
    .build();

FlowConfig flowConfig = new FlowConfig.Builder()
    .addQES(qes)
    .build();

IncodeWelcome.OnboardingListener onboardingListener = new IncodeWelcome.OnboardingListener() {
    @Override
    public void onQESCompleted(@NonNull QESResult qesResult) {
        // QES step finished. Process the result.
    }
};

IncodeWelcome.getInstance()
    .startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener);
```

## Configuration Options

Configure the module with `QES.Builder`. The table below lists the available option.

| Setting                        | Description                                                                                                                        |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `setDownloadDocument(Boolean)` | If `true`, downloads signed PDFs and shows the Confirmed Signature Details screen at the end of the QES flow. Defaults to `false`. |

For the complete option set, see `QES.Builder` in [API Reference](https://developer.incode.com/docs/android-api-reference).

## Result

QES delivers a `QESResult` to the `onQESCompleted(QESResult)` callback on the `OnboardingListener`. Key fields include:

- `documentSigning`: `true` if the document was signed using a qualified electronic signature.
- `resourcesNotFound`: `true` if the required signing resources could not be found.
- Fields inherited from `BaseResult`:
  - `resultCode`: The `ResultCode` for this result.
  - `error`: When `resultCode` is `ERROR`, the `Throwable` that caused it; otherwise, `null`.
  - `deviceStats`: The `DeviceStats` snapshot of the device state when the result was produced.
  - `motionStatus`: Device motion assessment during capture. One of the following:
    - `UNCLEAR`: Motion could not be determined; the default.
    - `PASS`: Device motion was within acceptable limits.
    - `FAIL`: Excessive device motion was detected.

If the step fails, the error surfaces through `OnboardingListener.onError(Throwable)`. This module does not define a module-specific exception subtype.

For all fields, see `QESResult` in [API Reference](https://developer.incode.com/docs/android-api-reference).
