Skip to content

BiometridFull - iOS Integration Guide

Overview

BiometridFull is a comprehensive identity verification SDK that provides a complete. It integrates all BiometridStandard modules (Liveness, NFC, AutoCapture) into a single, unified interface. The SDK manages the entire verification process through a web interface while leveraging native device capabilities for biometric operations.

Prerequisites

  • iOS 16.0+
  • Xcode 15+
  • Swift 5.9+
  • Camera, Microphone, and NFC permissions configured in Info.plist

Installation

Starting with 3.3.0, BiometridFull is distributed as a CocoaPods pod with subspecs that mirror the Android bridge structure. The subspecs (Liveness, NFC, AutoCapture, VideoConference, VideoLiveness) exist as semantic markers — declare the ones that match your flow to document intent. On iOS today they all transitively pull in the same Core, which carries the XCFramework and every native step pod. The modular surface is intentional API design; the underlying binary is one XCFramework due to Kotlin/Native framework packaging.

1. CocoaPods setup

Add the following to your Podfile:

platform :ios, '16.0'

source 'https://cdn.cocoapods.org'
source 'https://dl.cloudsmith.io/public/biometrid/mobile/cocoapods/index.git'
source 'https://dl.cloudsmith.io/public/biometrid/face01-liveness/cocoapods/index.git'

target 'YourApp' do
  use_frameworks!
  pod 'BiometridFull', '~> 3.3.0'
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
    end
  end
end

Then run:

pod install

2. Required Info.plist keys

Add the following keys to your Info.plist:

<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>

<key>NSCameraUsageDescription</key>
<string>Camera access is required for identity verification</string>

<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for identity verification</string>

<key>NFCReaderUsageDescription</key>
<string>NFC is required to read identity documents</string>

<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>

<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
</array>

Initialization

import BiometridFull

// 1. Create your callback implementation
class MyBiometridCallback: BiometridFullCallback {
    var url: String = "your-url"
    var app: String = "your-app-id"
    var appUrl: String? = "your-app-url"
    var credential: String = "your-credential"
    var language: SharedLanguage = .english
    var customHeaders: [AnyHashable: Any]? = nil

    func initialized(status: Bool, error: SharedBiometridErrorInfo?) {
        // Handle initialization result
    }

    func processCreated(processId: String) {
        // Handle process creation
    }

    func processUpdated(processId: String, stepId: String, action: String) {
        // Handle step update — process moved to the next step
    }

    func processFinished(processId: String) {
        // Handle process completion
    }

    func error(status: Bool, error: SharedBiometridErrorInfo) {
        // Handle errors
    }
}

// 2. Create the BiometridFull instance
let callback = MyBiometridCallback()
let biometridFull = BiometridFull(callback: callback)

Note: On iOS, BiometridStandard types are prefixed with Shared (e.g., SharedBiometridErrorInfo, SharedLanguage) due to the Kotlin Multiplatform framework export naming convention.

Available Methods

initialize()

Initializes the SDK by connecting to the Biometrid backend and preparing all required services.

func initialize() async throws

This method must be called before start(). It performs backend authentication using the provided url, app, and credential from the callback. The result is delivered through the initialized callback.


start(processId:screenType:)

Starts the identity verification process and presents the WebView interface.

func start(processId: String?, screenType: ScreenType) async throws
Parameter Type Description
processId String? Optional process ID. Pass nil to create a new process, or provide an existing ID to resume.
screenType ScreenType Platform-specific screen context. On iOS, wrap the current UIViewController.

stop()

Stops the current verification process and cleans up all resources.

func stop()

Stops any active WebView sessions, cancels pending native operations (Liveness, NFC, AutoCapture), and releases associated resources. Safe to call at any point.

Callback Protocol

BiometridFullCallback

The callback protocol that must be implemented to receive SDK lifecycle events and provide configuration.

Properties

Property Type Description
url String The Biometrid API base URL (e.g., https://api.biometrid.com/)
app String Your application identifier provided by Biometrid
appUrl String The Biometrid web application URL (e.g., https://app.biometrid.com/)
credential String Your credential key provided by Biometrid
language SharedLanguage The language for the verification interface
customHeaders [AnyHashable: Any]? Optional custom HTTP headers to include in API requests

Methods

Method Description
initialized(status:error:) Called when SDK initialization completes. status is true on success.
processCreated(processId:) Called when a new verification process is created.
processUpdated(processId:stepId:action:) Called when a step is successfully updated and the process moves to the next step.
processFinished(processId:) Called when the verification process completes successfully.
error(status:error:) Called when an error occurs during the verification process.

Data Models

SharedBiometridErrorInfo

class SharedBiometridErrorInfo {
    var code: String?
    var message: String?
    var data: Any?
}
Property Type Description
code String? Error code identifier (e.g., "MBF001")
message String? Human-readable error description
data Any? Optional additional error data

ScreenType

Platform-specific screen context wrapper used to present the verification interface.

// iOS
class ScreenType {
    init(controller: UIViewController)
}
Property Type Description
controller UIViewController The UIViewController used to present the WebView

Enums

SharedLanguage

enum SharedLanguage {
    case english    // "en-GB"
    case portuguese // "pt-PT"
    case french     // "fr-FR"
    case spanish    // "es-ES"
    case italian    // "it-IT"
}

Error Handling

Errors are delivered through the error method of BiometridFullCallback. Each error includes a SharedBiometridErrorInfo object with a code and descriptive message.

Error codes follow the prefix convention:

  • MBF - BiometridFull module errors

Handle errors in the callback:

func error(status: Bool, error: SharedBiometridErrorInfo) {
    let errorCode = error.code ?? "Unknown"
    let errorMessage = error.message ?? "An unknown error occurred"
    // Handle or display the error
}

Usage Example

SwiftUI Integration with ViewModel

import SwiftUI
import BiometridFull

// MARK: - Callback Implementation

class BiometridCallback: BiometridFullCallback {
    var url: String = "your-url"
    var app: String = "your-app-id"
    var appUrl: String? = "your-app-url"
    var credential: String = "your-credential"
    var language: SharedLanguage = .english
    var customHeaders: [AnyHashable: Any]? = nil

    weak var delegate: BiometridDelegate?

    func initialized(status: Bool, error: SharedBiometridErrorInfo?) {
        delegate?.initialized(status: status, error: error)
    }

    func processCreated(processId: String) {
        delegate?.processCreated(processId: processId)
    }

    func processUpdated(processId: String, stepId: String, action: String) {
        delegate?.processUpdated(processId: processId, stepId: stepId, action: action)
    }

    func processFinished(processId: String) {
        delegate?.processFinished(processId: processId)
    }

    func error(status: Bool, error: SharedBiometridErrorInfo) {
        delegate?.error(status: status, error: error)
    }
}

protocol BiometridDelegate: AnyObject {
    func initialized(status: Bool, error: SharedBiometridErrorInfo?)
    func processCreated(processId: String)
    func processUpdated(processId: String, stepId: String, action: String)
    func processFinished(processId: String)
    func error(status: Bool, error: SharedBiometridErrorInfo)
}

// MARK: - ViewModel

class BiometridFullVM: ObservableObject {
    @Published var isInitialized = false
    @Published var isLoading = false
    @Published var errorMessage: String?
    @Published var isProcessCompleted = false

    private lazy var biometridFull: BiometridFull = {
        let callback = BiometridCallback()
        callback.delegate = self
        return BiometridFull(callback: callback)
    }()

    func initialize() async {
        await MainActor.run {
            isLoading = true
            errorMessage = nil
        }

        do {
            try await biometridFull.initialize()
        } catch {
            await MainActor.run {
                errorMessage = "Initialization error: \(error.localizedDescription)"
            }
        }

        await MainActor.run {
            isLoading = false
        }
    }

    func start() async {
        let viewController = await MainActor.run { () -> UIViewController? in
            isLoading = true
            errorMessage = nil
            return findTopMostViewController()
        }

        guard let viewController = viewController else {
            await MainActor.run {
                errorMessage = "Could not find top view controller"
                isLoading = false
            }
            return
        }

        do {
            try await biometridFull.start(
                processId: nil,
                screenType: ScreenType(controller: viewController)
            )
        } catch {
            await MainActor.run {
                errorMessage = "Start error: \(error.localizedDescription)"
            }
        }

        await MainActor.run {
            isLoading = false
        }
    }

    func stop() {
        biometridFull.stop()
    }

    @MainActor
    private func findTopMostViewController() -> UIViewController? {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
              var topController = windowScene.windows.first?.rootViewController else {
            return nil
        }
        while let presented = topController.presentedViewController {
            topController = presented
        }
        return topController
    }
}

extension BiometridFullVM: BiometridDelegate {
    func initialized(status: Bool, error: SharedBiometridErrorInfo?) {
        Task { @MainActor in
            isInitialized = status
            if let error = error {
                errorMessage = error.message
            }
        }
    }

    func processCreated(processId: String) {
        // Store processId if needed
    }

    func processUpdated(processId: String, stepId: String, action: String) {
        // Step updated, process moved to next step
    }

    func processFinished(processId: String) {
        Task { @MainActor in
            isProcessCompleted = true
        }
    }

    func error(status: Bool, error: SharedBiometridErrorInfo) {
        Task { @MainActor in
            errorMessage = error.message
        }
    }
}

SwiftUI View

struct ContentView: View {
    @StateObject private var viewModel = BiometridFullVM()

    var body: some View {
        VStack(spacing: 20) {
            if viewModel.isLoading {
                ProgressView("Loading...")
            }

            if let error = viewModel.errorMessage {
                Text(error)
                    .foregroundColor(.red)
            }

            if viewModel.isProcessCompleted {
                Text("Verification completed!")
                    .foregroundColor(.green)
            }

            Button("Initialize") {
                Task { await viewModel.initialize() }
            }
            .disabled(viewModel.isInitialized || viewModel.isLoading)

            Button("Start Verification") {
                Task { await viewModel.start() }
            }
            .disabled(!viewModel.isInitialized || viewModel.isLoading)
        }
        .padding()
    }
}