SDK reference · iOS SDK / iOS Individual Modules

Selfie

The Selfie module captures the user's face with their device's camera and runs configurable liveness, face recognition, and image-quality checks. It can enroll new users so their face can be matched against an ID photo or used for later authentication. It can optionally capture depth and a video-liveness clip via Deepsight, and it backs the Face Match and Face Authentication modules.

For an overview of this module and how it works, see Face Capture.

How you use this module depends on your integration pattern. When the app defines the steps in code, you add the module to an IncdOnboardingFlowConfiguration as shown below; when the flow is defined in Dashboard, you reference it by session token and let the back end drive the steps. See Integration Approaches. For 1:1 and 1:N face login of returning users, iOS uses a separate startFaceLogin flow rather than a mode on this module; see Face Authentication.

Availability: All variants; the -l build adds extra local-liveness options.

Add Selfie Scan

Add the module with addSelfieScan() on your IncdOnboardingFlowConfiguration. Call it with no arguments for the default configuration, or pass options to customize it. Most onboarding flows require Selfie, and some modules depend on ordering; for example, Face Match needs Selfie and an ID or NFC capture added first.

// Default configuration
flowConfig.addSelfieScan()

// Custom configuration
flowConfig.addSelfieScan(
    showTutorials: true,
    lensesCheck: true,
    faceMaskCheck: true,
    closedEyesCheck: true,
    headCoverCheck: true,
    cameraFacing: .front,
    deepsight: DeepsightConfiguration(
        enabled: true,
        modality: .singleFrameWithDepthAndVideo,
        motion: true
    )
)

Selfie ships both a v1 and a v2 capture UI; the SDK selects the active one.

Example

The example below builds a flow with a Selfie module with tutorials shown, starts onboarding, and receives the result through the onSelfieScanCompleted delegate callback.

let flow = IncdOnboardingFlowConfiguration()
flow.addSelfieScan(showTutorials: true)

IncdOnboardingManager.shared.startOnboarding(
    sessionConfig: IncdOnboardingSessionConfiguration(token: "<SESSION_TOKEN>"),
    flowConfig: flow,
    delegate: self
)

// ...

extension MyViewController: IncdOnboardingDelegate {
    func onSelfieScanCompleted(_ result: SelfieScanResult) {
        // Final selfie result
        if let error = result.error {
            // Handle SelfieScanError
        }
    }

    func onSelfieAttemptCompleted(_ result: SelfieScanResult) {
        // Optional: per-attempt result
    }
}

Configuration Options

Pass these parameters to addSelfieScan(). Any parameter left nil falls back to the SDK/back-end default.

These options aren't the only factor. Your backend Flow or Workflow configuration can also determine where liveness and recognition run, as well as the effective Deepsight behavior for a given step.

Option Type Description
showTutorials Bool? Shows a tutorial before capture.
lensesCheck Bool? Enables eyeglasses/contact lenses detection during capture.
faceMaskCheck Bool? Enables face-mask detection during capture.
closedEyesCheck Bool? Enables closed eyes detection during capture.
headCoverCheck Bool? Enables head covering detection during capture.
cameraFacing CameraFacing? .front or .back.
streamFrames Bool? Enables frame streaming during capture.
enableAudioStream Bool? Enables audio streaming during capture.
customLogo UIImage? Displays a custom logo on the capture screen.
deepsight DeepsightConfiguration enabled, modality (.singleFrame, .singleFrameWithDepth, or .singleFrameWithDepthAndVideo), and motion. Defaults to .default (enabled: false, .singleFrame, motion: false).
imageQualitySeverity ImageQualitySeverity .ultraLow (default), .low, .medium, .high, or .ultraHigh.
occlusionCheck OcclusionCheck .disabled (default) or .enabled(severity) where severity is .low (default), .medium, or .high.

The -l build adds a performLocalLiveness parameter to addSelfieScan().

The older requireDepthData and videoLivenessRecording parameters are deprecated. Use deepsight instead. videoLivenessRecording: true maps to DeepsightModality.singleFrameWithDepthAndVideo.

For flows where captured media stays on the device, see Capture-Only Mode.

Result

Selfie delivers a SelfieScanResult to the delegate:

func onSelfieScanCompleted(_ result: SelfieScanResult)   // final result
func onSelfieAttemptCompleted(_ result: SelfieScanResult) // per attempt

Key fields include:

  • spoofAttempt: Bool?: true if a spoof attempt was detected, false if the user appears to be a real person, nil when it couldn't be determined because an unexpected error occurred.
  • image: UIImage?: The captured selfie image.
  • selfieBase64: String?: The Base64-encoded selfie image.
  • selfieEncryptedBase64: String?: The encrypted Base64-encoded selfie image.
  • frameWithDepth: String?: The Base64-encoded frame with depth data (Deepsight).
  • metadata: String?: Proprietary capture metadata.
  • videoFileURL: URL?: The local URL of the video-liveness recording.
  • presignedVideoFileURL: URL?: The URL of the video-liveness file prepared for backend transmission.
  • deviceStats: DeviceStats?: The device state at capture; deviceStats.motionStatus (MotionStatus) is the device-motion assessment.
  • idealCaptureEnvironmentTestResult: Int?: The result of the ideal-capture-environment test.
  • allAttemptsExhausted: Bool: true if no further capture or upload retries are available.
  • faceLoginResult: FaceLoginResult?: Populated for face-login operations. Sub-fields: success: Bool?, customerUUID: String?, interviewId: String?, interviewToken: String?, token: String?, transactionId: String?, hasFaceMask: Bool?, and hasLenses: Bool?.
  • error: SelfieScanError?: Set when the scan did not complete successfully.

Errors

SelfieScanError cases:

  • error(IncdError)
  • permissionsDenied
  • spoofDetected
  • lensesDetected
  • faceMaskDetected
  • tooDark
  • closedEyesDetected
  • headCoverDetected
  • faceNotAligned
  • faceOccluded
  • userCancelled
  • userNotFound
  • noFaceTemplateStored
  • userBlacklisted
  • manualFaceNotFound
  • secondFactorAuthorizationFailed
  • streamAudioPermissionsDenied

Was this page helpful?