Get started

The packages, the prerequisites and the integration steps of the Folio SDK on iOS, Android and the web, with a minimal app per platform.

Preview

This page describes a pre-release version of the SDK. Names, versions and APIs on this page can change before the release.

This page takes you from an empty app to a first identity verification. It lists what you install on each platform, what you need before you start and the steps in their order. Each step links to the page that describes it in full.

Packages

PlatformPackagesInterface
iOSSwift package FolioSDK with the products FolioSDK, FolioInquiryUI and FolioSDKBinary.Swift and SwiftUI (UIKit through UIHostingController)
Androidid.folio:sdk, which pulls in id.folio:sdk-native and the capture engine of the selfie step.Kotlin, Jetpack Compose
Webnpm package @folio/sdk, which brings the capture engine of the selfie step as a dependency.TypeScript, React

Every package holds the same SDK core and the ready-made inquiry UI of its platform. The type names are the same on every platform: FolioSdk, FolioSdkConfig, InquiryStore, InquiryEntry, InquiryLifecycle and so on. Platforms lists the platform versions and what each platform supports.

A web page that does not bundle the SDK can run the inquiry with one script tag instead. See Inquiry embed.

Before you start

  • Access to the packages. Folio gives you access to the package repository of each platform you build for. The setup guides write their addresses as <ios-package-repository-url>, <android-maven-repository-url> and <web-package-url>, and the release version as <version>.
  • A supported platform version. iOS 15 or later with Xcode 15 or later. Android minSdk 23 or later with Java 17. On the web, React 18 or 19 and a bundler that serves ES modules. See Platforms.
  • An organization. Folio assigns it to your integration. The runtime configuration takes it as organization, which must be non-empty and contain only lowercase letters, digits and hyphens. Your app's identifier, version and build come from the platform. See Configuration.
  • A backend that creates inquiries. The SDK never creates an inquiry. Your backend creates each inquiry and passes the launch code it receives to your app. The launch code is opaque and single-use: the first exchange consumes it, so pass a fresh one for each inquiry, and keep the credentials your backend uses with Folio out of your app.

Integration steps

  1. Install the packages. Add the packages of your platform from the repository Folio gives you: iOS, Android or web.
  2. Configure the platform.
    • iOS: configure your app for the camera, NFC, photos and files as the inquiries you run need. See iOS setup.
    • Android: call XPlatform.init (id.folio.sdk.platform.XPlatform) once per process, from onCreate of your Application subclass. See Android setup.
    • Web: serve the WebAssembly module and its manifest, load it with initializeFolioWasm, forward the /api path and /.well-known/jwks.json of your origin to Folio, import the PlexUI and inquiry stylesheets and serve the illustrations and animations the package ships. See Web setup.
  3. Write an identity record mapper. When a government ID verification succeeds, the SDK calls your IdentityRecordMapper and saves the RecordContent it returns in the vault. The payload is your own JSON document. See Identity records for a complete mapper on each platform; the samples below use that SavedIdentityMapper.
  4. Create the runtime. Create one FolioSdk with FolioSdk.create: create(config:mapper:) in Swift, create(config, mapper) in Kotlin and TypeScript. The call completes when the runtime is ready: it has restored the stored session, or started a new one. On Android, rememberFolioSdk(config, mapper) does this in Compose. See Runtime and stores and Configuration.
  5. Mount stores. The runtime returns no data. Mount the stores you need on it, render their state and send them actions: SessionStore, AuthStore, VaultStore, InquiryStore, MrtdStore, LogsStore, FolioDocumentListStore and FolioDocumentStore. FolioSDKProvider hands the runtime to your views on every platform; on Android the remember<Name>Store() composables and in React the use<Name>Store() hooks mount a store for the lifetime of a view. See Providers.
  6. Run an inquiry. Pass the launch code from your backend to the ready-made inquiry UI as the start entry: .start(launchCode:) in Swift, InquiryEntry.Start(launchCode) in Kotlin and InquiryEntry.start(launchCode) in TypeScript. Watch InquiryUiModel.lifecycle and close the inquiry store when the lifecycle becomes Closed or your view goes away. The inquiry UI never closes the store you give it, on any platform. When the inquiry ends with a redirect, the UI opens it as a universal link, in the same tab on the web, and then closes the inquiry. See Inquiry UI.
  7. Read the result. The verified identity is in InquiryUiModel.identity, and the record your mapper built is in the vault. Read it from VaultStore and decode the payload yourself. See Vault. A document the inquiry issues reaches the vault on its own and shows in FolioDocumentListStore; see Folio documents.

Minimal app

Each sample creates the runtime and shows the inquiry for one launch code. launchCode stands for the launch code your backend passed to your app.

VerifyViewController.swift
import Combine
import SwiftUI
import UIKit
import FolioSDK
import FolioInquiryUI

final class VerifyViewController: UIViewController {
    private var sdk: FolioSdk?
    private var inquiry: InquiryStore?
    private var lifecycle: AnyCancellable?

    func verify(launchCode: String) async throws {
        let config = FolioSdkConfig(
            baseUrl: "https://app.folio.mobi",
            organization: "<organization>",
            development: nil,
            logging: try FolioSdk.loggingConfig(consoleLevel: nil)
        )
        let sdk = try await FolioSdk.create(config: config, mapper: SavedIdentityMapper())
        self.sdk = sdk
        let store = try InquiryStore.mount(runtime: sdk)
        inquiry = store
        try store.dispatch(action: .open(entry: .start(launchCode: launchCode)))
        lifecycle = store.$state
            .map(\.lifecycle)
            .sink { [weak self] lifecycle in
                if case .closed = lifecycle { self?.finish() }
            }
        let platform = InquiryPlatform(nfc: sdk)
        let flow = UIHostingController(rootView: FolioInquiry(store: store, platform: platform))
        flow.modalPresentationStyle = .fullScreen
        present(flow, animated: true)
    }

    private func finish() {
        lifecycle = nil
        dismiss(animated: true)
        inquiry?.close()
        inquiry = nil
    }
}

The SDK reads your app's identifier, version and build from the main bundle. See iOS setup for the inquiry view FolioInquiry in SwiftUI.

Next steps

On this page