Introduction

Footprint is now excited to offer Bank Account Linking, which works seamlessly with our existing identity and vaulting technologies. Powered by open banking along with the best-in-class data aggregators, Footprint's Bank Account Linking enables you to easily connect your product to 15k+ financial institutions, cards, investment accounts, and more. Bank linking with Footprint comes with a few unqiue benefits

  • Use the same SDK to verify identities and link bank accounts (Native iOS/Android, React/Web, Flutter, and more).
  • Automatic secure vaulting for bank account numbers, ownership data, and more. Utilize the vault proxy to securely, and compliantly execute bank transfers with one of our many partners.
  • Built-in operations support in the Footprint dashboard: view accounts, balances, connection states, automatically re-link expired connections, decrypt bank account data, sift through transactions
  • Strongly integrated with Footprint's Identity, Risk, and Fraud products: when a bank account is linked, Footprint automatically extracts account ownership and financial data to hydrate additional risk and fraud signals for verifying the identity behind the account. Seamlessly use Bank account data in identity verification (and vice-versa) without writing a single line of code.
  • Simple unified APIs for pulling transaction data.

Link SDK

The Link SDK is a widget that integrates with your frontend wherever it lives (iOS, Android, or mobile web, or desktop) to provide users with a simple, beautiful, and whitelabeled experience to connect their bank account to your product.

Generate a bank linking session token

The first step is to start the onboarding and get an onboarding token for bank account linking. Go to the Footprint dashboard and create a Playbook with a bank-linking node. Then get an onboarding token e.g. obtok_vsd94fc0gksdfsdf824fx9JaGO7sgqHX from POST /onboardings.

iOS (Swift UI)

To integrate bank linking into your SwiftUI application, install our Swift SDK and use the FootprintBankLinking view component. Provide the authToken using the token obtained from the previous step, along with a redirectUri that includes both the scheme and host of your application (e.g., a custom URL scheme configured in your app's Info.plist).

swift
1FootprintBankLinking(
2    authToken: authToken,
3    redirectUri: "footprintcomponentsdemo://banklinking",
4    onSuccess: { response in
5        print("Bank linking completed successfully, validation token: \(response.validationToken)")
6    },
7    onError: { error in // Called when an error occurs
8        print("Error occurred during bank linking: \(error)")
9    },
10    onClose: { // Called when user closes the flow or the flow closes due to an error. If the flow closes due to an error, it will also call the onError callback
11        print("Bank linking exited")
12    }
13)

Android

To integrate bank linking into your Android application, install our Android SDK and launch the bank linking flow using the token obtained from the previous step. Use the FootprintBankLinking.launchWithAuthToken method, providing the authToken, activity context, and relevant callbacks:

kotlin
1Button(
2    onClick = {
3        coroutineScope.launch {
4            try {
5                FootprintBankLinking.launch(
6                    obSessionToken = "obtok_VlGKyL3AF7HDQfgx0j223RmNEmwNadRWn7", // Use your auth token here
7                    context = context,
8                    onSuccess = {
9                        val validationToken = it.validationToken
10                        println("Bank linked. Validation token: $validationToken")
11                    },
12                    onError = { error -> // Called when an error occurs
13                        println("Error linking bank: ${error.message}")
14                    },
15                    onClose = { // Called when user closes the flow or the flow closes due to an error. If the flow closes due to an error, it will also call the onError callback
16                        println("User exited bank linking")
17                    },
18                    onEvent = { event -> // Called when an event occurs in the bank linking flow
19                        println(
20                            "Bank linking event: " +
21                                    "name: ${event.name}, " +
22                                    "link type: ${event.meta.linkType}, " +
23                                    "institution name: ${event.meta.institutionName}, " +
24                                    "institution id: ${event.meta.institutionId}, " +
25                                    "timestamp: ${event.meta.timestamp}, " +
26                                    "properties: ${event.properties} "
27                        )
28                    }
29                )
30            } catch (e: FootprintException) {
31                println("Error initializing Footprint SDK: ${e.message}")
32            }
33        }
34    }
35) {
36    Text("Link Bank Account")
37}

Handling Process Death

If Android terminates your app's process during the OAuth flow, you need to resume the bank linking session when the OAuth redirect returns. Override the onNewIntent method in your activity to check for the intent extra "FOOTPRINT_BANK_LINKING_STATUS". If the value matches FootprintBankLinkingFlowStatus.PENDING.value, call FootprintBankLinking.resumePendingLinking with the same callbacks.

Here's an example:

kotlin
1class MainActivity : ComponentActivity() {
2    override fun onCreate(savedInstanceState: Bundle?) {
3        super.onCreate(savedInstanceState)
4
5        setContent {
6            OnboardingComponents(context = this)
7        }
8    }
9
10    private fun handleResumeFootprintBAL(intent: Intent){
11        val balStatus = intent.getStringExtra("FOOTPRINT_BANK_LINKING_STATUS")
12        println("Received new intent with BAL status: $balStatus")
13        if(balStatus != null && balStatus == FootprintBankLinkingFlowStatus.PENDING.value) {
14            FootprintBankLinking.resumePendingLinking(
15                context = this,
16                onSuccess = {
17                    val validationToken = it.validationToken
18                    println("Bank linked. Validation token: $validationToken")
19                },
20                onError = { error ->
21                    println("Error linking bank: ${error.message}")
22                },
23                onClose = {
24                    println("User exited bank linking")
25                },
26                onEvent = { event ->
27                    println(
28                        "Bank linking event: " +
29                                "name: ${event.name}, " +
30                                "link type: ${event.meta.linkType}, " +
31                                "institution name: ${event.meta.institutionName}, " +
32                                "institution id: ${event.meta.institutionId}, " +
33                                "timestamp: ${event.meta.timestamp}, " +
34                                "properties: ${event.properties} "
35                    )
36                }
37            )
38        }
39    }
40
41    override fun onNewIntent(intent: Intent) {
42        super.onNewIntent(intent)
43        handleResumeFootprintBAL(intent)
44    }
45}

Web

Make sure to have the @onefootprint/footprint-js package installed (version 5.0.0 or higher):

bash
1npm install @onefootprint/footprint-js
typescript
1import { onboarding } from "@onefootprint/footprint-js";
2
3onboarding.initialize({
4  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
5  onComplete: (validationToken) => {
6    console.log(validationToken);
7  },
8  onError: (error) => {
9    console.log(error);
10  },
11  onAuth: (validationToken) => {
12    console.log(validationToken);
13  },
14  onCancel: () => {
15    console.log("User canceled the flow");
16  },
17  onClose: () => {
18    console.log("User closed the flow");
19  },
20});

Validation token

After the SDK completes and calls the success completion handler, it will pass back a validation_token to you that you'll need to send to your backend and validate with the Footprint API.

sh
1curl -X POST https://api.onefootprint.com/onboarding/session/validate \
2   -u <API_KEY>: \
3   -d '{"validation_token": "<VALIDATION_TOKEN_FROM_SDK>"}'

This API call redeems the validation token from the SDK and lets you confirm that the link was completed successfully:

json
1{
2  "user": {
3    "fp_id": "fp_id_GSxJr68GAf5jUT3pdL9ndjf7TLkA3GCX",
4    "onboarding_id": "ob_SRFT2a1mN7DAWJ0VPXkiqK",
5    "playbook_key": "pb_test_VMooXd04EUlnu3AvMYKjMW",
6  },
7  "bank_link": {
8    "link_id": "bank_link_xyz123...xyz321"
9  }
10  ...
11}

Use (and store in your own database if needed) the link_id returned above in the bank linking APIs to fetch data about the linked bank account(s).

Note: a single bank link may connect more than one bank accounts, see the APIs linked below for the full data model accessible by a bank link.

Webhooks

When a bank link connection is created or changed, Footprint sends the footprint.user.bank_link_updated event. Setup webhooks and inspect the webhook event payload documentation in the webhooks tab on the dashboard.

APIs and Vaulting

Footprint provides a set of APIs to interact with bank links, accounts, and transactions. Additionally, bank account data is automatically vaulted when the link is established.

Bank linking terminology

Name Description
link A link to an institution for which the user has connected one or more accounts
account A bank account like a checking or savings account connected via a link

APIs

Footprint provides a set of APIs to get information about bank links, associated accounts, balances, and transactions. For the full API specification, take a look at the Bank Linking API reference.

Vaulting

Once linked, a bank account's sensitive data is automatically fetched and vaulted using the bank account data identifier defined in the Bank account vault fields.

The bank account_id is used as the alias for the Bank account. For instance, if a the link has an account with identifier acc_xyz1234, then the ACH account number would be vaulted under data identifier bank.acc_xyz1234.ach_account_number.