IOS

Trulioo KYC Documents SDK — iOS

The KYC Documents SDK delivers a complete, Trulioo-designed document verification UI for iOS. The SDK owns the full capture experience — your application initializes it with a shortcode, launches the hosted flow, and handles the terminal callback.

Need full UI control? If you want to design your own capture experience, see the KYC Documents Capture iOS SDK instead.


Biometric Data Notice

Some US states impose obligations on businesses that collect biometric identifiers or biometric information, which may include facial scan data extracted during a document verification transaction. One such law is the Illinois Biometric Information Privacy Act (BIPA). Businesses subject to BIPA must inform individuals of the purpose of data collection and obtain their consent before proceeding.

Trulioo requires a notice and consent mechanism for all document verification transactions. Customers using our API must confirm via API whether an individual is located in the United States and has consented in the prescribed manner. We strongly encourage all customers to consult with legal counsel to ensure their own compliance.

For more information, refer to our Service Specific Terms for Document Verification.


Quick Start

  1. Add the TruliooKYCDocuments Swift package to your project.
  2. Create a Trulioo instance.
  3. Get a shortcode from your backend for the active transaction.
  4. Call trulioo.initialize(shortcode:completion:) and wait for .authorized.
  5. Launch the hosted flow with trulioo.launch(callbacks:) (SwiftUI) or trulioo.launchController(callbacks:) (UIKit).
  6. Handle the onComplete and onError callbacks.
  7. Call trulioo.reset() when the flow is done.

What This SDK Covers

The SDK owns the full document verification experience. Your application owns initialization, launch timing, and the terminal result.

Your application ownsThe SDK owns
The shortcodeAuthorization of the active Docs transaction
SwiftUI or UIKit presentation stateHosted document and selfie capture UI
Completion, error, retry, and navigation behaviorTransaction-scoped selection and capture rules
Deciding when to call reset()Hosted-flow completion and structured error callbacks

Package and Compatibility

PropertyValue
GitHub repositoryhttps://github.com/Trulioo/kyc-documents.git
Swift package productTruliooKYCDocuments
Minimum iOS version15.0
DistributionSwift Package Manager

The package includes the hosted KYC Docs UI flow for iPhone and resolves its Trulioo and TruliooKYCDocumentsCapture dependencies through the package release metadata.


Installation

Add the package to your Package.swift:

dependencies: [
    .package(url: "https://github.com/Trulioo/kyc-documents.git", from: "X.Y.Z")
]

For beta builds, pin to the prerelease tag explicitly:

dependencies: [
    .package(url: "https://github.com/Trulioo/kyc-documents.git", exact: "X.Y.Z-beta.N")
]

Link the product to your target:

.target(
    name: "YourApp",
    dependencies: [
        .product(name: "TruliooKYCDocuments", package: "kyc-documents")
    ]
)

Then import the module:

import TruliooKYCDocuments

SwiftUI Integration Example

import SwiftUI
import TruliooKYCDocuments

struct HostedDocsView: View {
    @State private var trulioo = Trulioo()
    @State private var isLaunching = false
    @State private var transactionId: String?
    @State private var errorMessage: String?

    let shortcode: String

    var body: some View {
        Group {
            if isLaunching {
                trulioo.launch(
                    callbacks: TruliooCallbacks(
                        onComplete: { value in
                            transactionId = value
                            isLaunching = false
                            trulioo.reset()
                        },
                        onError: { result in
                            if case let .error(message, _, _, _) = result {
                                errorMessage = message
                            } else {
                                errorMessage = String(describing: result)
                            }
                            isLaunching = false
                            trulioo.reset()
                        }
                    )
                )
                .ignoresSafeArea()
            } else {
                VStack(spacing: 16) {
                    Button("Start verification") {
                        trulioo.initialize(shortcode: shortcode) { result in
                            switch result {
                            case .authorized(let transactionId):
                                self.transactionId = transactionId
                                self.isLaunching = true
                            case .error(let message, _, _, _):
                                self.errorMessage = message
                            case .complete:
                                self.errorMessage = "Unexpected completion during initialize."
                            }
                        }
                    }

                    if let transactionId {
                        Text("Initialized transaction: \(transactionId)")
                    }

                    if let errorMessage {
                        Text(errorMessage)
                    }
                }
            }
        }
    }
}

UIKit Integration Example

import TruliooKYCDocuments
import UIKit

final class DocsHostViewController: UIViewController {
    private let trulioo = Trulioo()

    func startVerification(shortcode: String) {
        trulioo.initialize(shortcode: shortcode) { [weak self] result in
            guard let self else { return }

            switch result {
            case .authorized:
                let controller = self.trulioo.launchController(
                    callbacks: TruliooCallbacks(
                        onComplete: { _ in
                            self.dismiss(animated: true)
                            self.trulioo.reset()
                        },
                        onError: { _ in
                            self.dismiss(animated: true)
                            self.trulioo.reset()
                        }
                    )
                )
                controller.modalPresentationStyle = .fullScreen
                self.present(controller, animated: true)

            case .error(let message, _, _, _):
                print("Initialize failed:", message)

            case .complete:
                print("Unexpected completion during initialize.")
            }
        }
    }
}

How the Launch Flow Works

  1. Create a Trulioo instance.
  2. Call initialize(shortcode:completion:) — this authorizes the transaction and loads configuration.
  3. Wait for .authorized(transactionId:) before proceeding.
  4. Call launch(callbacks:) (SwiftUI) or launchController(callbacks:) (UIKit).
  5. The SDK runs the hosted document and selfie capture experience.
  6. Wait for onComplete or onError.
  7. Call reset().

Do not call launch(...) or launchController(...) before initialization returns .authorized. The host application does not manage camera rendering — the hosted flow owns that UI internally.


Handling Results

Use TruliooCallbacks to react to the launched flow:

let callbacks = TruliooCallbacks(
    onComplete: { transactionId in
        // Terminal success
        print("Completed transaction:", transactionId ?? "missing")
    },
    onError: { result in
        // Structured product error
        print("Hosted flow error:", result)
    }
)

Result types:

ResultWhen it is returned
TruliooResult.authorized(transactionId:)Initialization succeeded — the flow is ready to launch
TruliooResult.complete(transactionId:)The hosted flow completed successfully
TruliooResult.error(message:details:code:transactionId:)The hosted flow ended with a structured product error

Call reset() after either onComplete or onError once your application is done with the transaction.


Desktop-to-Mobile

The iOS Docs SDK supports desktop-to-mobile flows when the transaction is configured for cross-device handoff. In this flow, the user starts on desktop, scans a QR code with their iPhone, and the hosted Docs flow continues the document and selfie steps on the mobile device.

Desktop-to-mobile behavior is configured through the Trulioo transaction, not through a separate iOS SDK flag.


Customization

The hosted Docs SDK does not accept host-side theme or locale objects through the public iOS launch surface. These behaviors are controlled by the transaction configuration associated with the shortcode:

  • Locale and branding
  • Available countries and document types
  • Capture-step requirements
  • Desktop-to-mobile enablement

To change these behaviors, update the transaction configuration in the Trulioo customer handoff flow.


Common Mistakes

Calling launch(...) before initialization returns .authorized. Always wait for the .authorized result before presenting the hosted flow.

Not calling reset() after the flow completes or fails. Call reset() in both onComplete and onError before starting a new transaction.

Expecting to render Capture cameras directly. The Docs SDK owns the hosted capture UI. If you need to compose your own camera UI, use the KYC Documents Capture iOS SDK instead.

Presenting the UIKit controller before initialization completes. Only call launchController(callbacks:) inside the .authorized case of the initialization callback.


Troubleshooting

Initialization fails immediately: Verify the shortcode is valid and belongs to the expected environment.

The hosted UI does not appear: Confirm launch(...) or launchController(...) is only called after initialization returns .authorized.

The flow completes but the host screen does not update: Handle onComplete and dismiss or swap screens in your application — the SDK does not navigate for you.

The flow returns an error: Log the message, code, and transactionId from the error result before deciding whether to retry.


Diagnostic Checklist

When filing a support issue, include:

  • Docs SDK version.
  • iPhone model and iOS version.
  • The shortcode environment used (production, development, preview).
  • Whether the host used SwiftUI or UIKit launch.
  • Whether the flow was pure mobile or desktop-to-mobile.
  • Whether initialization reached .authorized(transactionId:).
  • The final callback result and transaction ID, if available.
  • Whether reset() was called before retrying the transaction.