Trulioo SDK - Android Guide

The Trulioo Android SDK lets you add identity verification to your Android application. A standard integration collects device intelligence, optionally submits KYC subject data, and returns a terminal result you can act on.

Quick Start

  1. Add the Trulioo dependency to your project.
  2. Set up the SDK host context so it has access to your Application.
  3. Get a shortcode from your backend for the active transaction.
  4. Call Trulioo.initialize(...).
  5. Call Trulioo.sendDeviceInformation(...).
  6. Branch on accepted or failed and log the returned identifiers and debugTrace.

What This SDK Covers

The base Trulioo Android SDK provides three verification flows:

  • Device Intelligence — via sendDeviceInformation(...), collectDeviceIntelligence(...), and getDeviceInformation(...)
  • KYC Data verification — via verifyData(...)
  • eID verification — via prepareEid(...), verifyEid(...), and registerEidAuthTab(...)

Package and Compatibility

PropertyValue
Maven artifactcom.trulioo:trulioo:<version>
Kotlin namespacecom.trulioo.sdk.android
Minimum Android SDK24

Some Trulioo Android releases require an additional runtime dependency. Always follow the dependency instructions published with the specific release you are integrating.


Installation

Add the dependency to your build.gradle.kts:

dependencies {
    implementation("com.trulioo:trulioo:<version>")
    // Add any additional runtime dependency listed in the release instructions for this version.
}

Host Context Setup

The Android SDK requires access to your Application instance for device intelligence. By default, it captures this automatically via AndroidX Startup:

val hostContext = DeviceSdkHostContext.fromRuntime()

If your build disables manifest merging or AndroidX Startup, pass an explicit host context instead:

val hostContext = DeviceSdkHostContext(
    application = application,
    activity = activity,
)

Note: The device-intelligence runtime is initialized using Application, not a short-lived UI context. Using an Activity context without a valid Application is one of the most common setup mistakes on Android.


Initialization

Call Trulioo.initialize(...) before any other SDK operation. Initialization resolves the session, authorizes it against Trulioo APIs, and fetches the configuration for your transaction.

Trulioo.initialize(
    shortcode = shortcode,
    hostContext = DeviceSdkHostContext.fromRuntime(),
    options = TruliooInitializationOptions(
        allowLocalDevelopment = false,
        sdkVersion = BuildConfig.VERSION_NAME,
    ),
    onComplete = { result ->
        // Persist result for later use
    },
    onError = { error ->
        // Initialization failed — no product operations can proceed
    },
)

Initialization options (TruliooInitializationOptions):

OptionDescription
allowLocalDevelopmentEnables local or emulator shortcode testing. Blocked by default.
sdkVersionYour integration's version string. Helps map backend logs and support cases.
appVersionOptional override for app version metadata.
appDomainOptional override for app package or domain metadata.
deviceIntelligencePollingOverride default polling settings for debug collection.

Device Intelligence

Use Device Intelligence to collect device-risk telemetry from the current app session.

Standard Integration (Recommended)

For most integrations, use sendDeviceInformation(...). This submits the device event and returns a terminal result.

val result = Trulioo.sendDeviceInformation(
    initialization = initialized,
    hostContext = DeviceSdkHostContext.fromRuntime(),
    options = DeviceInformationSendOptions(
        reference = DeviceSubjectReference(
            firstName = "Jane",
            lastName = "Doe",
            dateOfBirth = "1990-01-01",
        ),
    ),
)

when (result) {
    is SendDeviceInformationResult.Accepted ->
        Log.d("Trulioo", "device accepted ${result.transactionId} ${result.eventId}")
    is SendDeviceInformationResult.Failed ->
        Log.e("Trulioo", "device failed ${result.error.code} ${result.error.stage} ${result.debugTrace}")
}

Debug Integration

Use collectDeviceIntelligence(...) only when you need the resolved device event and normalized seed for diagnostics.

val debugResult = Trulioo.collectDeviceIntelligence(
    initialization = initialized,
    hostContext = DeviceSdkHostContext.fromRuntime(),
    options = DeviceIntelligenceCollectionOptions(
        polling = DeviceIntelligencePollingOptions(),
        reference = DeviceSubjectReference(firstName = "Jane", lastName = "Doe"),
    ),
)

Log.d("Trulioo", "deviceEvent=${debugResult.deviceEvent}")
Log.d("Trulioo", "deviceSeed=${debugResult.deviceSeed}")

Callback-Only (Normalized Seed)

If you only need the normalized device result in a callback:

Trulioo.getDeviceInformation(
    initialization = initialized,
    onComplete = { device ->
        // device is DeviceSeedResponse?
    },
    onError = { error ->
        // Collection failed
    },
)

Key behaviors to know:

  • sendDeviceInformation(...) is the standard production path.
  • collectDeviceIntelligence(...) is a blocking debug path — do not use it in production unless you specifically need the terminal event.
  • reference is caller-supplied subject data only. The SDK generates device basic information internally — do not attempt to pass those fields yourself.
  • A failed reference submission is recorded in debugTrace but does not fail the device event.
  • DeviceSdkHostContext must resolve to a valid Application before device collection can start.

Note: DeviceInformationSendOptions and DeviceIntelligenceCollectionOptions also accept a userId field. Use this only when your downstream device-intelligence runtime expects a runtime-specific user identifier. It is not a replacement for the Trulioo transaction ID.

Default polling settings:

SettingDefault
maxAttempts32
intervalMs1250ms

To override:

DeviceIntelligenceCollectionOptions(
    polling = DeviceIntelligencePollingOptions(
        maxAttempts = 10,
        intervalMs = 1000,
    ),
)

KYC Data Verification

Use verifyData(...) when your flow has subject data and needs a terminal KYC verification result from the same initialized session.

lifecycleScope.launch {
    val stateJob = launch {
        Trulioo.observeDataState().collect { state ->
            Log.d("Trulioo", "dataState=$state")
        }
    }

    val result = Trulioo.verifyData(
        DataVerificationConfig(
            countryCode = "CA",
            personInfo = PersonInfo(
                firstName = "Jane",
                lastName = "Doe",
                dateOfBirth = "1990-01-01",
            ),
            location = Location(
                buildingNumber = "123",
                streetName = "Example",
                streetType = "Ave",
                city = "Exampleville",
                stateProvinceCode = "BC",
                postalCode = "V0V0V0",
            ),
            communication = Communication(
                emailAddress = "[email protected]",
                mobileNumber = "+12025550123",
            ),
        ),
    )

    stateJob.cancel()

    if (result.outcome == DataOutcome.ACCEPT && result.recordMatch) {
        Log.d("Trulioo", "data verified ${result.transactionId}")
    } else {
        Log.d("Trulioo", "review path $result")
    }
}

Key behaviors to know:

  • verifyData(...) reuses the internally stored initialized session — you do not pass initialized to it directly.
  • The SDK submits PII but does not return PII in DataVerificationResult.
  • Trulioo.observeDataState() exposes the current module state as a StateFlow.
  • Trulioo.resetData() cancels or clears the current data flow if you need to restart it.

eID Verification

Use the eID entrypoints when your flow needs an interactive, provider-backed identity verification from the same initialized session.

Android eID requires a one-time Auth Tab registration in your ComponentActivity before initialization:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Trulioo.registerEidAuthTab(this)
    }
}

Then run the eID flow:

lifecycleScope.launch {
    val stateJob = launch {
        Trulioo.observeEidState().collect { state ->
            Log.d("Trulioo", "eidState=$state")
        }
    }

    val config = EidVerificationConfig(
        transactionId = initialized.configuration.transactionId,
        countryCode = "SE",
    )

    // Pre-warm when the eID screen becomes visible
    Trulioo.prepareEid(config)

    // Launch the interactive provider flow
    val result = Trulioo.verifyEid(
        activity = this@MainActivity,
        config = config,
    )

    stateJob.cancel()

    if (result.outcome == EidOutcome.SUCCESS && result.match) {
        Log.d("Trulioo", "eID verified ${result.transactionId}")
    } else {
        Log.d("Trulioo", "eID not verified $result")
    }
}

Key behaviors to know:

  • registerEidAuthTab(this) must be called in onCreate of your ComponentActivity — this is required before any eID flow.
  • prepareEid(...) pre-warms the eID screen. Call it when the eID screen becomes visible.
  • verifyEid(...) launches the provider flow and waits for a terminal result.
  • transactionId must come from initialized.configuration.transactionId.
  • providerIdentifier is optional — only pass it when your flow needs to pin a specific provider.
  • callbackScheme is optional and only needed when your app uses a custom callback scheme.
  • Trulioo.resetEid() clears interrupted eID state before a restart.

Advanced: Authorized Session Client

After initialization, you can access approved Trulioo routes directly using Trulioo.sessionClient(...). Use this for typed authorized requests or binary uploads.

val sessionClient = Trulioo.sessionClient(
    initialization = initialized,
    allowedAuthorizedPaths = setOf(
        "/vendor/device/session",
        "/vendor/device/upload",
    ),
)

Available operations:

MethodDescription
authorizedPost(endpoint, request)Typed authorized POST
authorizedGet(endpoint)Typed authorized GET
authorizedUpload(endpoint, body, headers, onProgressBytes, timeoutMillis)Binary upload

Typed POST example:

@Serializable
data class StatusRequest(val transactionId: String)

@Serializable
data class StatusResponse(val status: String)

val status = sessionClient.authorizedPost(
    endpoint = AuthorizedPostEndpoint<StatusRequest, StatusResponse>(
        path = "/vendor/device/session",
    ),
    request = StatusRequest(transactionId = "txn-123"),
)

Upload example:

@Serializable
data class UploadResponse(val transactionId: String)

val response = sessionClient.authorizedUpload<UploadResponse>(
    endpoint = AuthorizedUploadEndpoint(path = "/vendor/device/upload"),
    body = imageBytes,
    headers = mapOf("Content-Type" to "image/jpeg"),
)

Rules:

  • Initialize first and reuse the returned session result.
  • Register any routes beyond the base SDK defaults explicitly via allowedAuthorizedPaths.
  • Use approved relative paths only, beginning with /.
  • Prefer the typed endpoint helpers over raw manual HTTP.
  • This is an advanced contract. For standard device intelligence, use sendDeviceInformation(...).

Subject Reference Data

Pass caller-owned subject data using DeviceSubjectReference:

DeviceSubjectReference(
    firstName = "Jane",
    lastName = "Doe",
    dateOfBirth = "1990-01-01",
    phoneNumber = "+15551234567",
    other = listOf(
        DeviceSubjectOtherField(
            customKey = "middleName",
            value = "Ann",
        ),
    ),
)

Do not pass device basic-information fields from your application. The SDK generates those internally.


Results

TruliooInitializationResult contains:

FieldUse
configurationConfirm backend enablement flags for the session
deviceEventSource of truth for terminal device status and failure reason
deviceSeedNormalized device result for UI and app logic
debugTraceDiagnostic timeline for support
baseUrlResolved environment base URL
accessTokenSession access token (managed by the SDK)

Error Handling

Failure typeBehavior
Initialization failureDelivered through the onError callback
Send failureReturns SendDeviceInformationResult.Failed with a stable code, stage, message, and debugTrace
Collection failureThrows DeviceIntelligenceCollectionException — includes a partial initializationResult with debug trace data gathered before failure
Reference submission failureRecorded in debugTrace under device_reference_submit; does not throw

Environments and Shortcodes

Environment is resolved from the shortcode — you do not set it manually.

Shortcode patternEnvironment
defaultProduction
.dv suffixDevelopment
.pr suffixPreview
.local suffix or localLocal
.emulator suffix or emulatorEmulator
local@host:portLocal override
emulator@host:portEmulator override

Supported region prefixes: us, eu, ap / apac, ca

Local and emulator shortcodes are blocked unless allowLocalDevelopment = true is set in initialization options.


Common Mistakes

Using an Activity context without a valid Application. The device-intelligence runtime initializes against Application, not a short-lived UI context. Use DeviceSdkHostContext.fromRuntime() or pass an explicit Application instance.

Assuming initialization also runs device collection. Initialization and collection are separate steps. You must explicitly call sendDeviceInformation(...) after initialization completes.

Passing device basic-information from your app. The SDK generates these fields internally. Supplying them yourself will cause a failure before seed submission.

Treating reference failure as a terminal collection failure. A failed subject reference submission is recorded in debugTrace but does not fail the device event. Check both separately.

Missing the runtime dependency. Some releases require an additional runtime dependency beyond the base artifact. Always check the release notes for your version.

Skipping registerEidAuthTab. Android eID requires this to be called in onCreate of your ComponentActivity. Skipping it will cause the eID flow to fail.


Troubleshooting

Device intelligence is not running:

  1. Confirm configuration.deviceIntelligence?.enabled == true.
  2. Confirm the backend returned a non-empty credentialId.
  3. Confirm the release-specific runtime dependency is on the classpath.
  4. Confirm DeviceSdkHostContext contains a real Application.
  5. Confirm sendDeviceInformation(...) was explicitly called after initialization.
  6. Inspect debugTrace.

Terminal event failed:

  • Inspect deviceEvent.failureReason.
  • Inspect terminal processor status if present.
  • Check whether device_reference_submit failed in debugTrace while the main event still completed — reference failure is not the same as full collection failure.

Diagnostic Checklist

When filing a support issue, include:

  • The shortcode environment (production, development, preview, local, or emulator).
  • App version, Android version, device manufacturer, and device model.
  • Whether DeviceSdkHostContext.fromRuntime() or an explicit host context was used.
  • Whether the required runtime dependency was present for your release.
  • The terminal deviceEvent.status, failureReason, and processor details.
  • transactionId, eventId, and relevant debugTrace entries.
  • Whether subject reference data was provided and whether device_reference_submit appears in debugTrace.
  • Whether a userId was supplied to send or debug collection.

Public API Reference

Main entry points:

Trulioo.initialize(...) · Trulioo.sendDeviceInformation(...) · Trulioo.collectDeviceIntelligence(...) · Trulioo.getDeviceInformation(...) · Trulioo.verifyData(...) · Trulioo.prepareEid(...) · Trulioo.verifyEid(...) · Trulioo.registerEidAuthTab(...) · Trulioo.sessionClient(...)

Key types:

TruliooInitializationOptions · TruliooInitializationResult · DeviceInformationSendOptions · SendDeviceInformationResult · DeviceIntelligenceCollectionOptions · DeviceIntelligencePollingOptions · DeviceSubjectReference · DeviceSubjectOtherField · DeviceSdkHostContext · DeviceIntelligenceCollectionException · DebugTraceEntry · TruliooSessionClient · AuthorizedPostEndpoint · AuthorizedGetEndpoint · AuthorizedUploadEndpoint