Overview

📘

Version 2.0 and later

Version 2.0 of the SDK introduces breaking changes that require changes in your application code if you had previously integrated an early version. See the Migration Guide for further details.

Documentation for older versions of the iOS SDK can be found here.

The Knot SDK provides a seamless way for end users to link their merchant accounts to your Android app, serving as the foundation for Knot's merchant connectivity platform. It is a client-side integration, consisting of initializing & configuring the SDK and handling events.

Installation

Follow the best-practice installation approach outlined below, which works seamlessly for both Java and Kotlin projects. Adding Maven Central to your root-level build.gradle file ensures that the Android Gradle plugin (and all other dependencies) are properly resolved and kept up-to-date.

allprojects {
    repositories {
        mavenCentral()
    }
}

Add the Knot SDK to your app

In your module-level Gradle file (typically app/build.gradle), configure your Android settings-such as the minimum SDK version and Java 8 support-to ensure compatibility with the SDK. The Knot SDK requires Android API level 21 or greater.

android {
  defaultConfig {
      minSdkVersion 21 // or greater
  }

  // Enable Java 8 support for KnotAPI SDK
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

Include the Knot SDK dependency

Include the KnotAPI SDK dependency so that Gradle can fetch the SDK from Maven Central.

implementation group: 'com.knotapi.knot', name: 'knotapi-android-sdk', version: '<latest-version>'

Replace <latest-version> with the current version provided by Knot.

Import Knot SDK

import com.knotapi.knot.*;
import com.knotapi.knot.*

Initialization

Your backend will create a session by calling Create Session and provide it to your frontend. To start a Knot session, you must first configure the session with a KnotConfiguration class. The configuration allows you to set the environment, product type, entry point, and other user experience configurations.

📘

Note

It's expected that your integration with Knot will retrieve and pass a new session_id into the SDK on each initialization.

Configure the session

The KnotConfiguration class is used to initialize the SDK with specific parameters.

NameTypeDescription
sessionIdStringThe session ID (provided by your backend).
clientIdStringYour organization’s client ID.
environmentEnvironmentThe desired environment (development or production).
productProductThe Knot product the session will inherit - the same as the type of session created. E.g. card_switcher.
merchantIdsInt[]Optional. A list of merchant ID(s) to display. It is recommended to provide 0 or 1 merchant ID depending on your desired user experience.
useCategoriesBoolOptional. Whether to display merchant categories and therefore group merchants into categories for discoverability. Default: true.
useSearchBoolOptional. Whether to display the search bar, enabling users to search for merchants. Default: `true.
domainURLsString[]Optional. A set of domains for which Knot should explicitly not clear cookies.
entryPointStringOptional. The specific entry point from within your app where you are initializing the Knot SDK (e.g. onboarding).
KnotConfiguration config = new KnotConfiguration(
    "session_12345",                      // sessionId
    "client_67890",                       // clientId
    Environment.production,               // environment
    Knot.Product.card_switcher,           // product
    new int[]{101},                       // merchantIds
    true,                                 // useCategories
    true,                                 // useSearch
    new String[]{"https://example.com"},  // domainUrls
    "onboarding"                          // entryPoint
);
val config = KnotConfiguration(
    "session_12345",                      // sessionId
    "client_67890",                       // clientId
    Environment.PRODUCTION,               // environment
    Knot.Product.card_switcher,           // product
    intArrayOf(101, 102, 103),            // merchantIds
    true,                                 // useCategories
    true,                                 // useSearch
    arrayOf("https://example.com"),       // domainUrls
    "onboarding"                          // entryPoint
)

Open the session

To begin the flow, use the open method with a context, a KnotConfiguration class, and an optional KnotEventDelegate.

Knot.open(context, knotConfiguration, knotEventDelegate);
Knot.open(context, knotConfiguration, knotEventDelegate)
KnotConfiguration config = new KnotConfiguration(
    "session_12345",                      // sessionId
    "client_67890",                       // clientId
    Environment.production,               // environment
    Knot.Product.card_switcher,           // product
    new int[]{101},                       // merchantIds
    true,                                 // useCategories
    true,                                 // useSearch
    new String[]{"https://example.com"},  // domainUrls
    "onboarding"                          // entryPoint
);

Knot.open(context, config, knotEventDelegate);
val config = KnotConfiguration(
    "session_12345",                      // sessionId
    "client_67890",                       // clientId
    Environment.PRODUCTION,               // environment
    Knot.Product.card_switcher,           // product
    intArrayOf(101, 102, 103),            // merchantIds
    true,                                 // useCategories
    true,                                 // useSearch
    arrayOf("https://example.com"),       // domainUrls
    "onboarding"                          // entryPoint
)

Knot.open(context, config, knotEventDelegate)

Single Merchant Flow

If you decide to use List Merchants to retrieve a list of merchants, list them in your app, and then open the SDK with a single merchant, you can do so by passing a merchant ID when configuring the session in the KnotConfiguration. More in Retrieving & Listing Merchants. The merchant ID is the same across all environments.

Although available, it is not recommended that you provide a long list of merchants in order to remove a few, but rather "hide" certain merchants that you desire from your Customer Dashboard.

Entry Points

In your app's user experience, you may choose to integrate Knot in one or multiple places (e.g. from different tabs or screens). How users behave when interacting with Knot from each of these "entry points" may vary and it will be useful for you to be able to differentiate these groups of users by entry point in order to assess the value of each entry point.

You can provide a value for the entry point in when when configuring the session in the KnotConfiguration. This value will be returned in the AUTHENTICATED webhook.

Categories & Search

Users are presented with a list of merchants in the SDK (unless you provide a single merchant as described above). Accompanying the list is a set of categories and a search experience. Each of these components is visible to users by default (as set in Knot's backend).

You can choose to remove either of them by setting useCategories: false and useSearch: false in KnotConfiguration. This is not recommended.

Events

To receive updates from the SDK, implement KnotEventDelegate in your class.

// Initialize your event delegate
KnotEventDelegate eventDelegate = new KnotEventDelegate() {
    @Override
    public void onSuccess(String merchant) {
        // Handle successful operation
    }

    @Override
    public void onError(KnotError knotError) {
        // Handle error operation using knotError
    }

    @Override
    public void onExit() {
        // Handle SDK exit event
    }

    @Override
    public void onEvent(KnotEvent knotEvent) {
        // Extract and process event details from KnotEvent
    }
};

// Initialize Knot SDK and set the event delegate instance (assuming you have a KnotConfiguration object)
Knot.open(context, knotConfiguration, eventDelegate)
// Initialize your event delegate
val eventDelegate = object : KnotEventDelegate {
    override fun onSuccess(merchant: String) {
        // Handle successful operation
    }

    override fun onError(knotError: KnotError) {
        // Handle error operation using knotError
    }

    override fun onExit() {
        // Handle SDK exit event
    }

    override fun onEvent(knotEvent: KnotEvent) {
        // Extract and process event details from KnotEvent
    }
}

// Initialize Knot SDK and set the event delegate instance (assuming you have a KnotConfiguration object)
Knot.open(context, knotConfiguration, eventDelegate)

onSuccess

This event is called when a user successfully logged in to the merchant and their card was switched. This event takes a single string argument representing the merchant's name.

onError

This event is called when an error occurs during SDK initialization. It emits a KnotError enum with four possible cases, as described below.

Error CaseDescription
INVALID_SESSIONThe session is invalid.
EXPIRED_SESSIONThe session has expired.
INVALID_CLIENT_IDThe client ID is invalid.
INTERNAL_ERRORAn internal error occurred.
MERCHANT_ID_NOT_FOUNDThe merchant ID is required when product type = transaction_link.
public void onError(KnotError error) {
    switch (error) {
        case INVALID_SESSION:
            Log.e("KnotError", "Error: INVALID_SESSION - " + error.getErrorDescription());
            break;
        case EXPIRED_SESSION:
            Log.e("KnotError", "Error: EXPIRED_SESSION - " + error.getErrorDescription());
            break;
        case INVALID_CLIENT_ID:
            Log.e("KnotError", "Error: INVALID_CLIENT_ID - " + error.getErrorDescription());
            break;
        case INTERNAL_ERROR:
            Log.e("KnotError", "Error: INTERNAL_ERROR - " + error.getErrorDescription());
            break;
        case MERCHANT_ID_NOT_FOUND:
            Log.e("KnotError", "Error: MERCHANT_ID_NOT_FOUND - " +error.getErrorDescription());
            break;
    }
}
fun onError(error: KnotError) {
    when (error) {
        KnotError.INVALID_SESSION -> Log.e("KnotError", "Error: INVALID_SESSION - ${error.errorDescription}")
        KnotError.EXPIRED_SESSION -> Log.e("KnotError", "Error: EXPIRED_SESSION - ${error.errorDescription}")
        KnotError.INVALID_CLIENT_ID -> Log.e("KnotError", "Error: INVALID_CLIENT_ID - ${error.errorDescription}")
        KnotError.INTERNAL_ERROR -> Log.e("KnotError", "Error: INTERNAL_ERROR - ${error.errorDescription}")
    }
}

onExit

This event is called when a user closes the SDK.

onEvent

This event is called when certain events occur in the SDK. With this callback, you will be able to understand how a user is progressing through their lifecycle of authenticating to a merchant. It emits a KnotEvent class as described below.

public void onEvent(KnotEvent knotEvent) {
  // Extract event details from the KnotEvent object
   
  // The type of event that occurred (e.g., "MERCHANT_CLICKED", "AUTHENTICATED")
  String eventType = knotEvent.getEvent();
  
  // The environment the event emitted from
  String environment = knotEvent.getEnvironment();
  
  // The merchant associated with the event
  String merchant = knotEvent.getMerchantName();
  
  // The unique identifier for this specific event instance
  String taskId = knotEvent.getTaskId();
  
  // Additional metadata a key-value map containing extra details related to the event
  Map<String, Object> metadata = knotEvent.getMetaData();
  
  //Additional processing if applicable
}
fun onEvent(knotEvent: KnotEvent) {
    // Extract event details from the KnotEvent object

    // The type of event that occurred (e.g., "MERCHANT_CLICKED", "AUTHENTICATED")
    val eventType: String = knotEvent.event

    // The merchant associated with the event
    val merchant: String = knotEvent.merchantName
  
    // The environment the event emitted from
    val environment = knotEvent.getEnvironment()

    // The unique identifier for this specific event instance
    val taskId: String = knotEvent.taskId

    // Additional metadata - a key-value map containing extra details related to the event
    val metadata: Map<String, Any> = knotEvent.metaData

    // Additional processing if applicable
}

Below is a list of all possible events emitted via the KnotEvent.event property.

NameDescription
REFRESH_SESSION_REQUESTEmitted when the session used to initialize the SDK needs to be refreshed.
MERCHANT_CLICKEDEmitted when a user clicks on a merchant from the merchant list.
LOGIN_STARTEDEmitted when a user submits their credentials to login to the merchant.
AUTHENTICATEDEmitted when a user successfully logs in to the merchant.
OTP_REQUIREDEmitted when a user needs to enter an OTP code to login to the merchant.
SECURITY_QUESTIONS_REQUIREDEmitted when a user needs to enter answers to security questions to login to the merchant.
APPROVAL_REQUIREDEmitted when a user needs to approve the login - often via a push notification or directly in the merchant's mobile app - to login to the merchant.

Other Options

Close the SDK

If you need to explicitly close the SDK, use the below method, otherwise end users will naturally close the SDK as they interact with the interface.

Knot.close();
Knot.close()

Maintain cookies

Knot clears cookies for security purposes. If your app relies on cookies, you can allowlist specific domains using the domainUrls configuration in KnotConfiguration. This is uncommon.

// The allowed domains for cookies to add as a parameter in KnotConfiguration
String[] domainUrls = new String[]{
    "https://example.com",
    "https://secure.example.com",
    "https://auth.example.com"
};
// The allowed domains for cookies to add as a parameter in KnotConfiguration
val domainUrls = arrayOf(
    "https://example.com",
    "https://secure.example.com",
    "https://auth.example.com"
)