Plaid Link for Android


Overview

Introduction

Here you find instructions on how to integrate and use Plaid Link for Android. At the center of it lies LinkSdk: an embeddable framework managing the details of linking an account with Plaid.

To get up and running quickly with Plaid Link for Android clone the GitHub repository and try out the example applications, which provide a reference implementation in Java and Kotlin. Youʼll want to sign up for free API keys through our Dashboard to get started.

Examples of Plaid Link for Android

Requirements

  • Install or update Android Studio to version 3.0 or greater
  • Plaid API keys – you’ll need your Plaid client_id and secret to get started
  • Android 5.0 (API level 21) and above

A new version of Link for Android will be released around the 15th of every month and we highly recommend you keep up to date to provide the best Plaid Link experience in your application.

Getting set up

Update your project plugins

In your root-level (project-level) Gradle file ( build.gradle ), add rules to include the Android Gradle plugin. Check that you have Google's Maven repository, as well.

build.gradle (Project-level)

buildscript {
    repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
        jcenter() // Include to import Plaid Link dependencies
    }
    dependencies {
        // ...
    }
}

In your module (app-level) Gradle file (usually app/build.gradle ), add a line to the bottom of the file. The latest version of the Link SDK is Bintray and can be found on Bintray.

build.gradle (App-level)

android {
  defaultConfig {
      minSdkVersion 21 // or greater
      // ...
  }

  // Enable Java 8 support for Link to work
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  // ...
}
dependencies {
  // ...
  implementation 'com.plaid.link:sdk-core:<insert latest version>'
}
Register your app ID

To register your Android app ID:

  1. Log in to the Plaid Dashboard
  2. Navigate to the API pane on the Team Settings page
  3. Configure one or more Android package names (e.g. com.plaid.example )
  4. Save your changes

Your Android app is now set up and ready to start integrating with the Plaid SDK.

To integrate Link inside of your application, follow the steps laid out below:

Create an instance of Plaid Link by calling Plaid.initialize(application). We recommend doing this as early as possible.

MainActivity


import android.app.Application
import com.plaid.link.Plaid

class MyApplication : Application() {

  override fun onCreate() {
    super.onCreate()
    Plaid.intialize(this)
  }

import android.app.Application;
import com.plaid.link.Plaid;

public class MyApplication extends Application {

  @Override
  public void onCreate() {
    super.onCreate();
    Plaid.INSTANCE.intialize(this);
  }
}

Before we can open Link, we need to first create a link_token. A link_token can be configured for different Link flows and is used to control much of Link's behavior. To see how to create a new link_token, visit /link/token/create. Integrating with Android requires creating a link_token with an android_package_name configured.

When you want to open Link, call Plaid.openLink() with the correct parameters for your integration. See the Link parameter reference below for complete documentation on possible configurations. Whenever Link finishes, the result will be delivered back in the OnActivityResult of the calling Activity or Fragment.

MainActivity


import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

import com.plaid.link.Plaid
import com.plaid.link.linkTokenConfiguration
import com.plaid.link.openPlaidLink
import com.plaid.link.configuration.AccountSubtype
import com.plaid.link.configuration.LinkLogLevel
import com.plaid.link.configuration.PlaidEnvironment
import com.plaid.link.configuration.PlaidProduct
import com.plaid.link.event.LinkEvent
import java.util.Locale

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Optional
    Plaid.setLinkEventListener { event -> Log.i("Event", event.toString()) }

    // Open Link – put this inside of a Button / Fab click listener
    this@MainActivity.openPlaidLink(
      linkTokenConfiguration {
        // required
        token = "GENERATED_LINK_TOKEN"

        // optional
        logLevel = LinkLogLevel.WARN // Defaults to ASSERT
        extraParams = mapOf() // Map of additional configs
      }
    );
  }
}

import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;

import com.plaid.link.Plaid
import com.plaid.link.openPlaidLink;
import com.plaid.link.configuration.AccountSubtype;
import com.plaid.link.configuration.LinkTokenConfiguration;
import com.plaid.link.configuration.LinkLogLevel;
import com.plaid.link.configuration.PlaidEnvironment;
import com.plaid.link.configuration.PlaidProduct;
import com.plaid.link.event.LinkEvent;
import java.util.Locale;
import kotlin.Unit;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Optional
    Plaid.setLinkEventListener(linkEvent -> {
      Log.i("Event", linkEvent.toString());
      return Unit.INSTANCE;
    });

    // Open Link – put this inside of a Button / Fab click listener
    Plaid.openLink(
        this,
        new LinkTokenConfiguration.Builder()
            .token("GENERATED_LINK_TOKEN")
            .logLevel(LogLevel.WARN) // Defaults to ASSERT
            .build()
            .toLinkConfiguration()
    );
  }
}

If your integration is still using a public_key to initialize Link, view our migration guide to upgrade to link_tokens. You can also view our maintenance guide to troubleshoot any public_key issues.

Parameter reference

The table below describes the parameters of LinkTokenConfiguration to configure the Link SDK.

ParameterDescription
token
String, required
Specify a link_token to launch Link. The link_token can be configured for different Link flows including the default flow, update mode, and payment_initiation. Visit the /link/token/create endpoint for a complete list of configurations when generating a link_token
logLevel
String, optional
There are various logs within the plaid link sdk. Setting the loglevel will allow you to see those logs at the level you specify (or higher levels).

Supported log levels:
  • ASSERT
  • DEBUG
  • ERROR
  • INFO
  • VERBOSE
  • WARN

The onActivityResult handler is called for the onSuccess and onExit events. Use PlaidLinkResultHandler to parse the result out of the returned intent.

The section on Implementation reference has a detailed overview of each event, its' corresponding response schema.

MainActivity

import com.plaid.link.result.LinkConnection
import com.plaid.link.result.LinkExit
import com.plaid.link.result.PlaidLinkResultHandler

class MainActivity : AppCompatActivity() {

  // configured in the previous step
  override fun onCreate(savedInstanceState: Bundle?) { ... }

  private val resultHandler = PlaidLinkResultHandler(
    onSuccess = { it: LinkConnection ->
      // handle onSuccess
    }
    onExit = { it: LinkExit ->
      // handle onExit
    }
  )

  override fun onActivityResult(
    requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultHandler.onActivityResult(requestCode, resultCode, data)) {
      return
    } else {
      Log.i(TAG, "Not handled")
    }
  }
}

import com.plaid.link.result.LinkConnection;
import com.plaid.link.result.LinkExit;
import com.plaid.link.result.PlaidLinkResultHandler;

public class MainActivity extends AppCompatActivity {

  private PlaidLinkResultHandler plaidLinkResultHandler = new PlaidLinkResultHandler(
      linkConnection -> {
        // Handle onSuccess
        return Unit.INSTANCE;
      },
      LinkExit -> {
        // Handle onExit
        return Unit.INSTANCE;
      }
  );

  // configured in the previous step
  @Override
  public void onCreate() { ... }

  @Override
  protected void onActivityResult(
    int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (!plaidLinkResultHandler.onActivityResult(requestCode, resultCode, data)) {
      Log.i(this.getClass().getSimpleName(), "Not handled");
    }
  }
}

Exchanging Token flow

The Link SDK doesn't directly return an API access_token. Instead, Link hands off a public_token client-side via the onSuccess callback once a user has successfully created an Item. This public_token is ephemeral and expires after 30 minutes. After exchanging the public_token for an access_token, the public_token will become invalidated.

Link also returns an item_id that should be stored with the access_token. The item_id is used to identify an Item in a webhook. The item_id can also be retrieved by making an /item/get request.

See the full API requests and response details in the Exchange Token documentation.

Implementation reference

Handling onSuccess

When a user successfully connects their institution with Plaid, and Item is created, and a public_token is returned which must be exchanged for an access_token.

The onSuccess handler returns a LinkConnection class that includes the public_token, and additional Link metadata in the form of a LinkConnectionMetadata class.

ParameterDescription
linkSessionId
String
A unique identifier associated with a user's actions and events through the Link flow. Include this identifier when opening a support ticket for faster turnaround.
institutionName
String
The full institution name, such as 'Bank of America'
institutionId
String
The institution ID, such as ins_100000
accounts
[Object]
A list of objects with the following properties:
  • accountId: the id of the selected account
  • accountName: the name of the selected account
  • accountNumber: the last 2-4 digits of the selected account
  • accountType: the account type
  • accountSubType: the account subtype
  • verificationStatus: the Item's verficiation status. See below:
When all Auth features are enabled by initializing Link with the user parameters , the accounts object includes an Item's verificationStatus, with available status:
  • pending_automatic_verification: an Item is pending automated microdeposit verfication
  • pending_manual_verification: an Item is pending manual microdeposit verification
  • manually_verified: an Item was successfully manually verified
Checkout the Accounts section for more detailed documentation. To collect accounts data, you must enable the Select Account view via the Plaid Dashboard.
Handling onSuccess

private val handler = PlaidLinkResultHandler (
  onSuccess = {
    // Send public_token to your server, exchange for access_token
    val publicToken = it.publicToken

    val metadata = it.linkConnectionMetadata
    val accountId = metadata.accounts.first().accountId
    val accountName = metadata.accounts.first().accountName
    val accountNumber = metadata.accounts.first().accountNumber
    val accountType = metadata.accounts.first().accountType
    val accountSubType = metadata.accounts.first().accountSubType
    val institutionId = metadata.institutionId
    val institutionName = metadata.institutionName
  }}
  ...
)

private PlaidLinkResultHandler plaidLinkResultHandler =  new PlaidLinkResultHandler(
  linkConnection -> {
      // Send public_token to your server,
      // exchange for access_token
      String publicToken = linkConnection.getPublicToken();

      LinkConnection.LinkConnectionMetadata metadata =
          linkConnection.getLinkConnectionMetadata();
      String accountId =
          metadata.getAccounts().get(0).getAccountId();
      String accountName =
          metadata.getAccounts().get(0).getAccountName();
      String accountNumber =
          metadata.getAccounts().get(0).getAccountNumber();
      String accountType =
          metadata.getAccounts().get(0).getAccountType();
      String accountSubType =
          metadata.getAccounts().get(0).getAccountSubType();
      String institutionId = metadata.getInstitutionId();
      String institutionName = metadata.getInstitutionName();
    return  Unit.INSTANCE;
  },
  ...
);

Handling onExit

The onExit handler is called when a user does not complete the link flow. The LinkExit returned from onExit handler is meant to help you guide your users after they have exited Link. We recommend storing the error and metadata information server-side in a way that can be associated with the user. You’ll also need to include this and any other relevant info in Plaid Support requests for the user.

Link Exit schema

See the full Error documentation for all possible Plaid API errors.

ParameterDescription
displayMessage
String
A user-friendly representation of the error code. null if the error is not related to user action. This may change over time and is not safe for programmatic use.
errorCode
String
The particular error code. Each error_type has a specific set of error_codes. A code of 499 indicates a client-side exception.
errorMessage
String
A developer-friendly representation of the error code.
errorType
String
A broad categorization of the error.
LinkExitMetadata
ParameterDescription
linkSessionId
String
A unique identifier associated with a user's actions and events through the Link flow. Include this identifier when opening a support ticket for faster turnaround.
institutionName
String
The name of the user's selected institution, if available.
institutionId
String
The ID of the user's selected institution, if available.
requestId
String
The request ID for the last request made by Link. This can be shared with Plaid Support to expedite investigation.
status
String
An indication of the point at which the user exited the Link flow. See the Metadata status docs for all possible values.
Handling onExit

private val handler = PlaidLinkResultHandler (
  requestCode = LINK_REQUEST_CODE,
  ...
  onExit = {
    String errorType = it.error?.errorType
    String errorCode = it.error?.errorCode
    String errorMessage = it.error?.errorMessage
    String displayMessage = it.error?.displayMessage
    String institutionId = it.linkExitMetadata.institutionId
    String institutionName = it.linkExitMetadata.institutionName
    String status = it.linkExitMetadata.status
  },
)

  private PlaidLinkResultHandler plaidLinkResultHandler =  new PlaidLinkResultHandler(
    ...
    linkExit -> {
      LinkError error  = linkExit.getError();
      if (error  != null) {
        String errorType = error.getErrorType();
        String errorCode = error.getErrorCode();
        String errorMessage = error.getErrorMessage();
        String displayMessage = error.getDisplayMessage();
      }

      LinkExitMetadata metadata = linkExit.getMetadata();
      String institutionId = metadata.getInstitutionId();
      String institutionName = metadata.getInstitutionName();
      String status = metadata.getExitStatus();
      return  Unit.INSTANCE;}
);

Handling onEvent

The onEvent callback is called at certain points in the Link flow. Unlike the handlers for onSuccess, onExit the onEvent handler is initialized as a global lambda passed to the Plaid class.

OPEN events will be sent immediately upon Link’s opening, and remaining events will be sent by the time onSuccess or onExit is called. If you need the exact time when an event happened, please use the timestamp property.

Event names
EventDescription
ERROR A recoverable error occurred in the Link flow, see the error_code metadata.
EXIT The user has exited without completing the Link flow and the onExit callback is fired.
HANDOFF The user has completed the Link flow and the onSuccess callback is fired.
OPEN The user has opened Link.
OPEN_MY_PLAID The user has opened my.plaid.com. This event is only sent when Link is initialized with assets as a product
SEARCH_INSTITUTION The user has searched for an institution.
SELECT_INSTITUTION The user selected an institution.
SUBMIT_CREDENTIALS The user has submitted credentials.
SUBMIT_MFA The user has submitted MFA.
TRANSITION_VIEW The TRANSITION_VIEW event indicates that the user has moved from one view to the next.
Metadata Schema
FieldDescription
errorCode The error code that the user encountered. Emitted by: EXIT.
errorMessage The error message that the user encountered. Emitted by: EXIT.
errorType The error type](/docs/#errors) that the user encountered. Emitted by: EXIT.
exitStatus The status key indicates the point at which the user exited the Link flow. Emitted by: EXIT.
institutionId The ID of the selected institution. Emitted by: all events.
institutionName The name of the selected institutioninstitutions. Emitted by: all events.
institutionSearchQuery The query used to search for institutions. Emitted by: SEARCH_INSTITUTION.
requestId The request ID for the last request made by Link. This can be shared with Plaid Support to expedite investigation. Emitted by: all events.
linkSessionId The link_session_id is a unique identifier for a single session of Link. It's always available and will stay constant throughout the flow. Emitted by: all events.
mfaType If set, the user has encountered one of the following MFA types: code, device, questions, selections. Emitted by: SUBMIT_MFA and TRANSITION_VIEW when view_name is MFA.
viewName The name of the view that is being transitioned to. Emitted by: TRANSITION_VIEW.
timestamp An ISO 8601 representation of when the event occurred. For example 2017-09-14T14:42:19.350Z. Emitted by: all events.
Metadata viewName
ViewDisplayed when
CONNECTED The user has connected their account.
CONSENT We ask the user to consent to the privacy policy.
CREDENTIAL Asking the user for their account credentials.
ERROR An error has occurred.
EXIT Confirming if the user wishes to close Link.
LOADING Link is making a request to our servers.
MFA The user is asked by the institution for additional MFA authentication.
RECAPTCHA The user was presented with a Google reCAPTCHA to verify they are human.
SELECT_ACCOUNT We ask the user to choose an account.
SELECT_INSTITUTION We ask the user to choose their institution.
Handling onEvent

override fun onCreate(savedInstanceState: Bundle?) {

  Plaid.setLinkEventListener { event ->
    Log.i("Event", it.toString())
  }

}

@Override
protected void onCreate(Bundle savedInstanceState) {

  Plaid.setLinkEventListener(linkEvent -> {
    Log.i("Event", linkEvent.toString());
    return Unit.INSTANCE;
  });

}

Updating Items

To open Link in update mode, generate a new link_token for a given access_token via the /link/token/create request. Everything else about launching Link in update mode is the same as launching Link normally. You just need to pass this generated link_token into the LinkTokenConfiguration builder to initialize Link.

MainActivity

 this@MainActivity.openLink {
  linkTokenConfiguration {
    // Other fields
    token = "<GENERATED_LINK_TOKEN>"
  }
}

Plaid.openLink(
  this,
  new LinkTokenConfiguration.Builder()
  // Other fields
  .token("<#GENERATED_PUBLIC_TOKEN#>")
  .build()
  .toLinkConfiguration()
);

The preferred and recommended method to customize the Link Android SDK is to use the customization feature in the dashboard, Plaid Link for Android will automatically use the values you provide there.

Troubleshooting

Pass a LinkLogLevel value with the LinkTokenConfiguration to get visible logs. The order in terms of verbosity, from least to most is ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept.

LogLevelValueDescription
NONE 0 Not available in the Android SDK.
VERBOSE 2 Show all log messages (the default).
DEBUG 3 Show debug log messages that are useful during development only, as well as the message levels lower in this list.
INFO 4 Show expected log messages for regular usage, as well as the message levels lower in this list.
WARN 5 Show possible issues that are not yet errors, as well as the message levels lower in this list.
ERROR 6 Show issues that have caused errors, as well as the message level lower in this list.
ASSERT 7 Show issues that the developer expects should never happen.

Moving Forward

Migrating to production

Keep building your integration out in our Sandbox and Development API environments. When youʼre ready to go to Production, request access from the Dashboard. While you’re at it, be sure to also take a look at our Privacy Policy.

Getting help

Find answers to common integration and product questions at our Help Center. You can find all the code for this guide, including runnable sample applications, on GitHub.

Weʼre excited to see what you build!