Overview

📘

Version 1.0 and later

Version 1.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 Link SDK provides a seamless way for end users to link their merchant accounts to your iOS 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

The Knot SDK can be installed using CocoaPods or Swift Package Manager (SPM).

Using CocoaPods

Install CocoaPods.

If you haven't already, install the latest version of CocoaPods.

Create a Podfile.

If you don’t have an existing Podfile, run the following command to create one:

pod init

Add your Podfile.

Add the below line to your Podfile in your iOS project directory:

pod 'KnotSDK'

Using Swift Package Manager (SPM)

To install the Knot SDK using Swift Package Manager, ensure you're using Swift version 5.3 or later.

Go to File, Add Packages

In your Xcode project, go to File, Add Packages.

Enter Knot package URL

In the top right corner of the dialog box, you'll see a search bar. Enter the Knot package URL: https://github.com/millionscard/knot-api-ios. From the results, choose the knot-api-ios package.

Decide your Dependency Rule

It is recommended to opt for Up to Next Major Version. Choose the project you want to integrate with KnotAPI and click on Add Package.

Confirm package dependency

Confirm that the KnotAPI Swift package was added as a package dependency to your project successfully.

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.

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.
entryPointString?Optional. The specific entry point from within your app where you are initializing the Knot SDK (e.g. onboarding).
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.
merchantIds[Int]?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.
let config = KnotConfiguration(
    sessionId: "session_12345",
    clientId: "client_67890",
    environment: .development,
    product: .card_switcher,
    entryPoint: "onboarding",
    useCategories: true,
    useSearch: true,
    merchantIds: [52]
)

Open the session

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

Knot.open(configuration: myConfiguration, delegate: self)
let config = KnotConfiguration(
    sessionId: "session_12345",
    clientId: "client_67890",
    environment: .development,
    entryPoint: "onboarding",
    product: .cardSwitcher,
    useCategories: true,
    useSearch: true,
    merchantIds: [52]
)

Knot.open(configuration: config, delegate: self)

📘

Note on view controller

To ensure seamless integration and avoid any UI issues when embedding the view controller into your UI hierarchy, it's crucial to properly position the view controller within the safe area of your application's interface. This practice helps maintain the accessibility and visibility of the controller across different devices and screen sizes, especially considering the presence of notches, status bars, and navigation elements that might obscure the content.

class MyViewController : UIViewController {

  func configureKnot() {
    let controller = Knot. createKnotViewController(configuration: session, delegate: delegate)
    view.addSubview(controller.view)
    addChild(controller)
  }

  ...
}

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.

class MyViewController: UIViewController, KnotEventDelegate {
    func onSuccess(merchant: String) {
        print("Merchant \(merchant) successfully authenticated.")
    }

    func onError(error: KnotError) {
        print("Error occurred: \(error.errorDescription)")
    }

    func onEvent(event: KnotEvent) {
        print("Received event: \(event.event)")
    }

    func onExit() {
        print("Knot session exited.")
    }
}

onSuccess

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

onError

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

Error CaseDescription
.invalidSessionThe session is invalid.
.expiredSessionThe session has expired.
.invalidClientIdThe client ID is invalid.
.internalErrorAn internal error occurred.
.merchantIdNotFoundThe merchant ID is required when product type = transaction_link.
func onError(error: KnotError) {
    switch error {
    case .invalidSession:
        print("Error: \(error.errorDescription)")
    case .expiredSession:
        print("Error: \(error.errorDescription)")
    case .invalidClientId:
        print("Error: \(error.errorDescription)")
    case .internalError:
        print("Error: \(error.errorDescription)")
    case .merchantIdNotFound:
        print("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.

/// Represents a Knot event received during user interaction within the Knot SDK.
@objc public class KnotEvent {

    /// The environment the event emitted from
    @objc public let environment: Environment
    
    /// The product the event emitted from
    @objc public let product: Product
    
    /// The primary event code.
    @objc public let event: String
    
    /// The merchant associated with the event (if applicable).
    @objc public let merchant: String?
    
    /// Additional metadata related to the event, stored as an Objective-C compatible dictionary.
    @objc public let metaData: NSDictionary
    
    /// The identifier associated with this event.
    @objc public let taskId: String?
    
...
}

The following list contains all possible events emitted in 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

Get current SDK version

If you need to retrieve the current SDK version for your own use case, implement the following:

let sdkVersion = Knot.SDKVersion()
print("Knot SDK Version: \(sdkVersion ?? "Unknown")")

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()