> For the complete documentation index, see [llms.txt](https://even-financial.gitbook.io/developer-center/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://even-financial.gitbook.io/developer-center/marketplace-integrations/mobile-sdks/credit-cards/kotlin.md).

# Kotlin

## Overview

The Credit Cards vertical is delivered through the Engine Mobile SDK for Android. This guide covers installation, prerequisites, the core configuration props (`channel`, `zone`, `productTypes`), a basic usage example, prefilling lead data, client tags, and event handlers.

You'll need the correct `channel` and `zone` values for your integration. Ask your Partner Manager to provide these values for Credit Cards.

{% hint style="info" %}
Before you start, request an API token from your Partner Manager. It authenticates with the Engine API and is required to use the Prefill API. You may want multiple tokens depending on how many entry points your app has into the SDK.
{% endhint %}

## Requirements

* Android project built with Gradle
* `minSdk` 24 or higher

## Install

The SDK is published to GitHub Packages, so a GitHub Personal Access Token (PAT) is required to download it.

**1. Create a GitHub PAT**

In GitHub, go to **Settings → Developer settings → Personal access tokens** and create a token with at least the `read:packages` scope. When authenticating, use your GitHub **username** and the **PAT** as the password (not your GitHub login password).

**2. Store credentials outside the repo**

Either store them user-level in `~/.gradle/gradle.properties`:

```properties
gpr.user=YOUR_GITHUB_USERNAME
gpr.token=YOUR_GITHUB_PAT
```

or as environment variables:

```bash
export GPR_USER=YOUR_GITHUB_USERNAME
export GPR_TOKEN=YOUR_GITHUB_PAT
```

**3. Add the GitHub Packages repository**

Add the `maven` block inside `dependencyResolutionManagement.repositories` in `settings.gradle.kts`:

```kotlin
dependencyResolutionManagement {
    // Forces all repos here (not in app/build.gradle.kts)
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()

        // Private GitHub Packages — where kotlin-engine-sdk is hosted
        maven {
            // Local label for logs/errors only; not sent to GitHub
            name = "GhPkgA"
            url = uri("https://maven.pkg.github.com/MoneyLion/engine-mobile-native-sdk")
            credentials {
                username = providers.gradleProperty("gpr.user")
                    .orElse(providers.environmentVariable("GPR_USER"))
                    .get()
                password = providers.gradleProperty("gpr.token")
                    .orElse(providers.environmentVariable("GPR_TOKEN"))
                    .get()
            }
        }
    }
}
```

**4. Add the dependency**

Add this line inside `dependencies { ... }` in `app/build.gradle.kts`.

```kotlin
dependencies {
    implementation("com.engine.mobile.sdk:kotlin-engine-sdk:1.+")
}
```

**5. Sync / verify**

```bash
./gradlew :app:dependencies --configuration releaseRuntimeClasspath
```

Confirm `com.engine.mobile.sdk:kotlin-engine-sdk` resolves to the latest `1.x` release in the tree.

## Initialize

Import the SDK where you render the Engine flow:

```kotlin
import com.engine.mobile.sdk.EngineSDK
import com.engine.mobile.sdk.generated.models.ProductType
```

## Basic Example

`EngineSDK` extends `FrameLayout`, so construct it in code and add it to any container. Use `listOf(ProductType.credit_card)` for `productTypes` to render the Credit Cards flow. Your `channel` and `zone` values are provided by your Partner Manager.

```kotlin
val sdk = EngineSDK(
    context = this,
    channel = "your-channel",
    zone = "your-zone",
    productTypes = listOf(ProductType.credit_card),
    onExit = {
        // handle exit / navigation
    },
    // ...optional event handlers, see Event Handlers
)

container.addView(sdk)
```

## Properties

<table><thead><tr><th width="220">Prop</th><th width="220">Type</th><th width="130">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>channel</code></td><td><code>String</code></td><td>Yes</td><td>Identifies your integration in Engine. Provided by your Partner Manager (e.g. <code>"direct"</code>).</td></tr><tr><td><code>zone</code></td><td><code>String</code></td><td>Yes</td><td>Identifies the placement or distribution surface for the SDK. Provided by your Partner Manager (e.g. <code>"marketplace"</code>).</td></tr><tr><td><code>productTypes</code></td><td><code>List&#x3C;ProductType></code></td><td>Yes</td><td>Import the <code>ProductType</code> from our SDK, and use <code>listOf(ProductType.credit_card)</code> for <code>credit_card</code>.</td></tr><tr><td><code>bearerToken</code></td><td><code>String</code></td><td>For prefill</td><td>API token from your Partner Manager. Required to use the Prefill API. Without it, the standard non-prefilled flow renders.</td></tr><tr><td><code>personalInformation</code></td><td><code>LeadPersonalInformation</code></td><td>No</td><td>Prefill data. See <a href="#prefilling-lead-data">Prefilling Lead Data</a>.</td></tr><tr><td><code>financialInformation</code></td><td><code>LeadFinancialInformation</code></td><td>No</td><td>Prefill data. See <a href="#prefilling-lead-data">Prefilling Lead Data</a>.</td></tr><tr><td><code>creditInformation</code></td><td><code>LeadCreditInformationJson</code></td><td>No</td><td>Prefill data. See <a href="#prefilling-lead-data">Prefilling Lead Data</a>.</td></tr><tr><td><code>creditCardInformation</code></td><td><code>LeadCreditCardInformationJson</code></td><td>No</td><td>Prefill data. See <a href="#prefilling-lead-data">Prefilling Lead Data</a>.</td></tr><tr><td><code>clientTags</code></td><td><code>Map&#x3C;String, List&#x3C;String>></code></td><td>No</td><td>Reporting/attribution tags. See <a href="#client-tags">Client Tags</a>.</td></tr><tr><td><code>onExit</code></td><td><code>(ExitEvent) -> Unit</code></td><td>Yes</td><td>Fired when the user exits the flow.</td></tr><tr><td><code>onInitialize</code>, <code>onCreate</code>, <code>onUpdate</code>, <code>onNavigate</code>, <code>onSubmit</code>, <code>onRateTableRender</code>, <code>onOfferClick</code>, <code>onErrorPageView</code>, <code>onErrorPageRetry</code>, <code>onEmbedError</code>, <code>onEmbedErrorRetry</code></td><td>Callbacks</td><td>No</td><td>Optional tracking hooks. See <a href="#event-handlers">Event Handlers</a>.</td></tr></tbody></table>

## Prefilling Lead Data

Prefill any user data you already have to reduce what the user has to type in-flow. Prefilled data is grouped into typed information objects, each passed as its own argument on `EngineSDK` (e.g. `personalInformation`, `financialInformation`, `creditInformation`, `creditCardInformation`).

{% hint style="info" %}
Prefilling requires a `bearerToken`. Pass only the fields you have — omitted fields are collected from the user in-flow.
{% endhint %}

### Example

```kotlin
val sdk = EngineSDK(
    context = this,
    channel = "your-channel",
    zone = "your-zone",
    bearerToken = "{your_token}",
    productTypes = listOf(ProductType.credit_card),
    personalInformation = LeadPersonalInformation(
        firstName = "Bob",
        lastName = "Dylan",
        email = "bobdylan@gmail.com",
        dateOfBirth = LocalDate(1990, 1, 1),
        primaryPhone = "2325624852",
        address1 = "1600 Pennsylvania Avenue",
        address2 = "Apt 2",
        city = "Washington",
        state = State.DC,
        zipcode = "20500",
    ),
    financialInformation = LeadFinancialInformation(
        annualIncome = 20000,
    ),
    creditInformation = LeadCreditInformationJson(
        providedCreditRating = ProvidedCreditRating.good,
    ),
    creditCardInformation = LeadCreditCardInformationJson(
        cardPurposes = listOf(CardPurpose.balance_transfer, CardPurpose.cash_back),
    ),
    onExit = {},
)
```

### Type Definitions

Every prop and field is optional — pass only what you have.

```kotlin
class LeadPersonalInformation(
    val firstName: String? = null,
    val lastName: String? = null,
    val email: String? = null,
    val dateOfBirth: LocalDate? = null, // kotlinx.datetime.LocalDate
    val primaryPhone: String? = null, // 10 digits, no "+" or "-" chars
    val address1: String? = null,
    val address2: String? = null,     // optional apartment / suite
    val city: String? = null,
    val state: State? = null,         // 2-letter state enum (e.g. State.DC)
    val zipcode: String? = null,
)

class LeadFinancialInformation(
    val annualIncome: Int? = null,   // raw integer value (e.g. 20000)
)

class LeadCreditInformationJson(
    val providedCreditRating: ProvidedCreditRating? = null,
)

class LeadCreditCardInformationJson(
    val cardPurposes: List<CardPurpose>? = null,
)
```

### Enums / Accepted Values

Fields backed by an enum must use a valid value.

```kotlin
enum class CardPurpose {
    balance_transfer,
    cash_back,
    earning_rewards,
    improve_credit,
    low_interest,
    new_to_credit,
    student,
    travel_incentives,
}

enum class ProvidedCreditRating {
    excellent,
    good,
    fair,
    poor,
    limited,
}

// State is a 2-letter US state enum, e.g. State.CA, State.DC, State.NY
```

{% hint style="warning" %}
Do not prefill any fields that are empty or unavailable — omit them so the user is prompted in-flow. Prefilled data must match the type definitions above, and any field backed by an enum must use a valid value. If a value is invalid, that attribute is stripped and the user will have to enter it again manually.
{% endhint %}

## Client Tags

The Engine SDK supports adding your unique Client Tags to track performance of specific campaigns or users. All Client Tag data is attributed to the lead level.

Client Tags are added via the `clientTags` argument on `EngineSDK`, a map of string keys to lists of string values. We strongly recommend including only one element per list for ease of reporting and attribution — if you want two separate tags, include the second tag under a different key. There is no limit to the number of keys.

```kotlin
val sdk = EngineSDK(
    context = this,
    channel = "your-channel",
    zone = "your-zone",
    bearerToken = "{your_token}",
    productTypes = listOf(ProductType.credit_card),
    personalInformation = LeadPersonalInformation(/* ...any data you don't want to ask for again */),
    clientTags = mapOf(
        "clientId" to listOf("client1"),
        "trafficsource" to listOf("email"),
        "campaignId" to listOf("campaign1"),
    ),
    onExit = {},
)
```

{% hint style="info" %}
**Note**: Client Tags are only sent as part of a prefill request. You must provide both a `bearerToken` and prefill data (via the information props such as `personalInformation`). If no prefill data is supplied, the SDK makes no prefill call and any `clientTags` you pass are ignored.
{% endhint %}

### Supported Client Tag Keys for Reporting

If you plan for the Engine team to set up reporting (i.e., you do not plan to hit the Analytics API), these are the only keys that are currently fully supported. If a different key is needed, please reach out to your partner manager.

* agentId
* campaignId
* clientId
* deviceid
* medium
* sourceId
* subid
* subid1
* subid2
* subid3
* target
* trafficsource
* userid

## Event Handlers

`EngineSDK` exposes optional callback arguments that notify your app when key moments occur during the user's journey. Each callback receives an event object containing a `timestamp` (ISO 8601 UTC) and event-specific fields.

All callbacks are optional. Pass any combination when constructing `EngineSDK`. If a callback is not provided, the SDK will still log the event to the debug console in development mode.

```kotlin
val sdk = EngineSDK(
    context = this,
    channel = "your-channel",
    zone = "your-zone",
    productTypes = listOf(ProductType.credit_card),
    onInitialize = { event -> Log.d("Engine", "onInitialize ${event.timestamp}") },
    onCreate = { event -> Log.d("Engine", "onCreate ${event.leadUuid}") },
    onSubmit = { event -> Log.d("Engine", "onSubmit ${event.leadUuid}") },
    onOfferClick = { event -> Log.d("Engine", "onOfferClick ${event.offerUuid}") },
    onExit = {
        // Navigate the user back or perform cleanup
    },
    // ...other callbacks
)
```

### Available Events

| Callback              | Trigger                          |
| --------------------- | -------------------------------- |
| **onInitialize**      | SDK finished loading the embed   |
| **onCreate**          | New lead created                 |
| **onUpdate**          | Lead data updated                |
| **onNavigate**        | Page navigation within the flow  |
| **onSubmit**          | Lead form submitted              |
| **onRateTableRender** | Rate table displayed with offers |
| **onOfferClick**      | User clicked an offer            |
| **onErrorPageView**   | Error page displayed in the flow |
| **onErrorPageRetry**  | User retried from the error page |
| **onExit**            | User exited the SDK              |
| **onEmbedError**      | Web embed failed to load         |
| **onEmbedErrorRetry** | User retried after embed failure |

For Credit Cards, `onRateTableRender` populates `creditCardOffers`, and `onOfferClick` includes card-specific fields such as `financialInstitutionBrandName`, `cardName`, `isITA`, and `cardNetwork`. Every event includes a `timestamp` (ISO 8601 UTC).

## Signing process

The Kotlin SDK is signed with a GPG key (ECDSA, `nistp384`) when it is released. A detached `.asc` signature file is published alongside each of its artifacts in GitHub Packages. This lets you confirm that the artifact was produced by Engine and has not been tampered with.

## Verifying the artifact

1. Fetch the public key and add it to your keyring:

```bash
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 4612FEE50837C6FCE32FCE5CB65F1D6010B0BF5B
```

Confirm the key is now in your keyring:

```bash
gpg --list-keys 4612FEE50837C6FCE32FCE5CB65F1D6010B0BF5B
```

This should show the public key details.

2. Download both the artifact (`{file}.aar`) and its signature (`{file}.aar.asc`) from the [GitHub Packages page](https://github.com/MoneyLion/engine-mobile-native-sdk/packages/3169922).
3. Verify the signature against the artifact:

```bash
gpg --verify {file}.aar.asc {file}.aar
```

You should see `Good signature`, confirming the artifact is authentic and intact.

## Changelog

<details>

<summary>View the full Kotlin Credit Cards SDK changelog</summary>

* Initial release of the Kotlin Engine SDK.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://even-financial.gitbook.io/developer-center/marketplace-integrations/mobile-sdks/credit-cards/kotlin.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
