# Photo Enrollment

As introduced in the [enrollment section](/consumer/mobile-sdk-guide/enrollment.md):

> enrollment is the process of registering a new user by connecting their facial biometrics to a Keyless account. During this process, a full and unobstructed view of the user's face is required.

If you possess a trusted source, such as an identity document, Keyless allows you to register a new user connecting their facial biometric from the identity document photo. The assumption behind the feature is that the identity document photo fulfills the requirement of a full and unobstructed view of the user's face.

{% hint style="success" %}
To retrieve a document photo Keyless offers the [Keyless Mobile Document SDK](https://docs.keyless.io/mobile-document-sdk) utility.
{% endhint %}

To enroll a user from the photo use the `PhotoEnrollConfig`.

{% tabs %}
{% tab title="Android" %}

```kotlin
// photoBitmap is the bitmap you created from the document photo.
val configuration = PhotoEnrollConfig(photo = photoBitmap)

Keyless.enroll(
  configuration = configuration,
  onCompletion = { result ->
    when (result) {
      is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "Enroll success - userId ${result.value.keylessId}")
      is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "Enroll failure - error code ${result.error.code}")
    }
  }
)
```

{% endtab %}

{% tab title="iOS" %}

```swift
// photoUIImage is the UIImage you created from the document photo.
let configuration = PhotoEnrollConfig(photo: photoUIImage)

Keyless.enroll(
  configuration: configuration,
  onCompletion: { result in
    switch result {
    case .success(let enrollmentSuccess):
        print("Enrollment finished successfully. UserID: \(enrollmentSuccess.keylessId)")
    case .failure(let error):
        print("Enrollment finished with error: \(error.message)
    }
  })
```

{% endtab %}

{% tab title="Flutter" %}

```dart
import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/enrollment_configuration.dart';

// documentImage from eDocument.
final configuration = PhotoEnrollConfig(documentImage: documentImage);

try {
  final result = await Keyless.instance.enroll(configuration);
  print("Enrollment finished successfully. UserID: ${result.keylessId}");
} catch (error) {
  print("Enrollment finished with error: $error");
}
```

{% endtab %}

{% tab title="React Native" %}

```typescript
const config = new PhotoEnrollConfig({
  photoBase64: '<photoBase64>',
});

const result = await Keyless.enroll(config);
result.fold({
  onSuccess(data) {
    logConsole('Enroll result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Enroll result failure ' + JSON.stringify(error, null, 2));
  },
});
```

{% endtab %}
{% endtabs %}

## Photo Enrollment configuration

You can configure the enrollment process with optional parameters in your `PhotoEnrollConfig()` instance.

{% tabs %}
{% tab title="Android" %}

```kotlin
public data class PhotoEnrollConfig(
    public val photo: Bitmap,
    public val temporaryState: String? = null,
    public val operationInfo: OperationInfo? = null,
    public val jwtSigningInfo: JwtSigningInfo? = null
)
```

{% endtab %}

{% tab title="iOS" %}

```swift
public struct PhotoEnrollConfig{
    public let photo: CGImage
    public let operationInfo: Keyless.OperationInfo?
    public let jwtSigningInfo: JwtSigningInfo?
    public let temporaryState: String?
}
```

{% endtab %}

{% tab title="Flutter" %}

```dart
class PhotoEnrollConfig{
  final Uint8List? documentImage;
  final String? temporaryState;
  final OperationInfo? operationInfo;
  final JwtSigningInfo? jwtSigningInfo;
}
```

{% endtab %}

{% tab title="React Native" %}

```typescript

 class PhotoEnrollConfig {
  public readonly photoBase64: string;
  public readonly operationInfo: OperationInfo | null;
  public readonly jwtSigningInfo: JwtSigningInfo | null;
  public readonly clientState: string | null;


```

{% endtab %}
{% endtabs %}

## Photo Enrollment success result

If the Enroll from photo is successful you will find in the `EnrollmentSuccess` containing the corresponding fields you requested during configuration.

{% tabs %}
{% tab title="Android" %}

```kotlin
data class EnrollmentSuccess(
    val signedJwt: String? = null,
) : KeylessSdkSuccess()
```

{% endtab %}

{% tab title="iOS" %}

```swift
public struct EnrollmentSuccess {
    public let signedJwt: String?
}
```

{% endtab %}

{% tab title="Flutter" %}

```dart
class EnrollmentSuccess {
    final String? signedJwt;
}
```

{% endtab %}

{% tab title="React Native" %}

```typescript
 class EnrollmentSuccess {
    public readonly keylessId: string;
    public readonly customSecret: string;
    public readonly enrollmentFrame: string | null;
    public readonly signedJwt: string | null;
    public readonly clientState: string | null;
 }
```

{% endtab %}
{% endtabs %}

If the enrollment is successful the user is enrolled and can [authenticate](/consumer/mobile-sdk-guide/authentication.md) with Keyless from now on.


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keyless.io/consumer/mobile-sdk-reference/photo-enrollment.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
