Introduction

7 min read



Bank Account Linking connects a user's bank accounts to your product through the same Footprint SDK and vault you use for identity verification. It runs on open banking and data aggregators and reaches over 15,000 financial institutions, cards, investment accounts, and more.

  • One SDK. The SDK that verifies identities also links bank accounts: native iOS and Android, React and web, Flutter, and more.
  • Automatic vaulting. Bank account numbers, ownership data, and more are vaulted when an account is linked. Use the Vault Proxy to execute bank transfers with one of Footprint's partners.
  • Operations in the dashboard. View accounts, balances, and connection states; re-link expired connections automatically; decrypt bank account data; and search through transactions.
  • Risk and fraud signals. When a bank account is linked, Footprint extracts account ownership and financial data and turns it into additional risk and fraud signals for verifying the identity behind the account. Bank account data feeds identity verification, and the reverse, without writing a line of code.
  • Unified APIs. One set of APIs for pulling transaction data.

Link SDK

The Link SDK is a widget for your frontend, wherever it lives: iOS, Android, mobile web, or desktop. It gives users a white-labeled flow for connecting their bank account to your product.

Generate a bank linking session token

Start an onboarding and get its token. In the Footprint dashboard, create a playbook with a bank linking node. Then call POST /onboardings to get an onboarding token, such as obtok_vsd94fc0gksdfsdf824fx9JaGO7sgqHX.

iOS (SwiftUI)

Install the Swift SDK and add the FootprintBankLinking view. Pass the token from the previous step as authToken, and a redirectUri that includes both the scheme and the host of your app, such as 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

Install the Android SDK and launch the flow with the token from the previous step. Call FootprintBankLinking.launch with the authToken, the activity context, and your 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, resume the bank linking session when the OAuth redirect returns. Override onNewIntent in your activity and read the intent extra "FOOTPRINT_BANK_LINKING_STATUS". If the value matches FootprintBankLinkingFlowStatus.PENDING.value, call FootprintBankLinking.resumePendingLinking with the same callbacks:

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

Install @onefootprint/footprint-js version 5.0.0 or higher:

bash
1npm install @onefootprint/footprint-js

Then initialize the onboarding with the token:

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

When the SDK completes and calls the success handler, it passes back a validation_token. Send it to your backend and validate it 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>"}'

The call redeems the token and confirms that the link completed:

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    "id": "bank_link_xyz123...xyz321"
9  }
10  ...
11}

The id under bank_link is what you pass to the bank linking APIs to fetch data about the linked accounts; store it in your own database if you need it later. It is the value of the {link_id} path parameter in the /bank_links/... routes.

A single bank link can connect more than one bank account. The APIs below describe the full data model reachable from a link.

Webhooks

When a bank link is created or changes, Footprint sends the footprint.user.bank_link_updated event. Set up webhooks and read the event payload documentation on the webhooks page of the dashboard.

APIs and vaulting

Footprint provides APIs for bank links, accounts, and transactions, and vaults bank account data automatically 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

The APIs return bank links, their accounts, balances, and transactions. The Bank Linking API reference has the full specification.

Vaulting

Once linked, a bank account's sensitive data is fetched and vaulted under the bank vault field described in Bank account vault fields.

The bank account_id is the alias for the account. If a link has an account with identifier acc_xyz1234, its ACH account number is vaulted under bank.acc_xyz1234.ach_account_number.