---
title: Mobile SDK photo enrollment
description: Use a photo (for example, from an identity document) to enroll initial biometric data for a user.
component: recognize
page_id: recognize:mobile-sdk:mobile-sdk-photo-enrollment
canonical_url: https://docs.pingidentity.com/recognize/mobile-sdk/mobile-sdk-photo-enrollment.html
llms_txt: https://docs.pingidentity.com/recognize/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
section_ids:
  photo-enrollment: Photo enrollment
  android: Android
  ios: iOS
  flutter: Flutter
  react-native: React Native
  photo-enrollment-configuration: Photo enrollment configuration
  android-2: Android
  ios-2: iOS
  flutter-2: Flutter
  react-native-2: React Native
  photo-enrollment-success-result: Photo enrollment success result
  android-3: Android
  ios-3: iOS
  flutter-3: Flutter
  react-native-3: React Native
---

# Mobile SDK photo enrollment

[Enrollment](mobile-sdk-enrollment.html) is the process of registering a new user by connecting facial biometrics to a PingOne Recognize account. During this process, a full and unobstructed view of the user's face is required.

If you have a trusted source (for example, an identity document), PingOne Recognize allows you to register a new user using the facial biometric from the document photo. The assumption is that the document photo satisfies the requirement for a full and unobstructed face image.

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

## Photo enrollment

### Android

```kotlin
// photoBitmap is the bitmap 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}")
    }
  }
)
```

### iOS

```swift
// photoUIImage is the UIImage 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)")
    }
  }
)
```

### 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");
}
```

### React Native

```text
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));
  },
});
```

## Photo enrollment configuration

You can configure enrollment with optional parameters in `PhotoEnrollConfig()`.

### 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
)
```

### iOS

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

### Flutter

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

### React Native

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

## Photo enrollment success result

If enroll-from-photo succeeds, the `EnrollmentSuccess` object contains the fields requested in configuration.

### Android

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

### iOS

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

### Flutter

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

### React Native

```text
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;
}
```

If enrollment succeeds, the user is enrolled and can authenticate from that point onward. See [authentication](mobile-sdk-authentication.html).
