Layer integration guide
Use Layer to instantly onboard new customers
In this guide, we'll start from scratch and walk through how to use Layer to create a fast, frictionless onboarding experience for your customers.
If you're already familiar with Link, you can skip to Create a Link token.
Get Plaid API keys and complete application and company profile
If you don't already have one, you'll need to create a Plaid developer account. After creating your account, you can find your API keys under the Team Settings menu on the Plaid Dashboard.
You will also need to complete your application profile and company profile in the Dashboard. The information in your profile will be shared with users of your application when they manage their connection on the Plaid Portal.
Install and initialize Plaid libraries
You can use our official server-side client libraries to connect to the Plaid API from your application:
1// Install via npm2npm install --save plaid
After you've installed Plaid's client libraries, you can initialize them by passing in your client_id
, secret
, and the environment you wish to connect to (Sandbox or Production). This will make sure the client libraries pass along your client_id
and secret
with each request, and you won't need to explicitly include them in any other calls.
1// Using Express2const express = require('express');3const app = express();4app.use(express.json());56const { Configuration, PlaidApi, PlaidEnvironments } = require('plaid');78const configuration = new Configuration({9 basePath: PlaidEnvironments.sandbox,10 baseOptions: {11 headers: {12 'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,13 'PLAID-SECRET': process.env.PLAID_SECRET,14 },15 },16});1718const client = new PlaidApi(configuration);
Launch Link
Plaid Link is a drop-in module that provides a secure, elegant flow for Layer. Before initializing Link, you will need to create a new link_token
on the server side of your application. A link_token
is a short-lived, one-time use token that is used to authenticate your app with Link.
You can create one using the /link/token/create
endpoint. Then, on the client side of your application, you'll need to initialize Link with the link_token
that you just created.
Create a Link token
Much like a regular Link flow, the starting point for Layer is a call to /link/token/create
. The products array must contain the layer
product; it may contain other products as well.
1app.post('/api/create_link_token', async function (request, response) {2 // Get the client_user_id by searching for the current user3 const user = await User.find(...);4 const clientUserId = user.id;5 const request = {6 user: {7 // This should correspond to a unique id for the current user.8 client_user_id: clientUserId,9 },10 client_name: 'Plaid Test App',11 products: ['layer'],12 language: 'en',13 webhook: 'https://webhook.example.com',14 redirect_uri: 'https://domainname.com/oauth-page.html',15 country_codes: ['US'],16 };17 try {18 const createTokenResponse = await client.linkTokenCreate(request);19 response.json(createTokenResponse.data);20 } catch (error) {21 // handle error22 }23});
Install the Link SDKs
For instructions on installing Link SDKs, see the Link documentation for your platform: iOS, Android, React Native, or React. Layer is not supported on mobile webview integrations.
Layer requires mobile SDK versions from June 2024 or later. Minimum supported versions are 5.6.0 (iOS), 4.5.0 (Android), and 11.11.0 (React Native).
Create the Link Handler
Basic sample code for creating the Link handler is shown below. For more details, see the Link documentation for your platform: iOS, Android, React Native, or React.
Ensure you are creating a Link token and passing it to the Link SDK as early as possible. The more time between when you create your handler and when you open Link, the better the UX will be for your users.
If you already have an existing Android or React Native integration created prior to June 2024, you will likely need to update your client-side Link opening code to support Layer. If your Android integration does not use a PlaidHandler
or uses OpenPlaidLink
instead of FastOpenPlaidLink
, or if your React Native integration uses PlaidLink
instead of create
and open
, you will need to add a separate handler creation step, as shown in the sample code below. For more details, see React Native: opening Link and Android: opening Link.
Create a LinkTokenConfiguration
Each time you open Link, you will need to get a new link_token
from your server and create a new
LinkTokenConfiguration
object with it.
1val linkTokenConfiguration = linkTokenConfiguration {2 token = "LINK_TOKEN_FROM_SERVER"3}
The Link SDK runs as a separate Activity
within your app. In order to return the result
to your app, it supports both the standard startActivityForResult
and onActivityResult
and the ActivityResultContract
result APIs.
Register a callback for an Activity Result
1private val linkAccountToPlaid =2registerForActivityResult(FastOpenPlaidLink()) {3 when (it) {4 is LinkSuccess -> /* handle LinkSuccess */5 is LinkExit -> /* handle LinkExit */6 }7}
Create a PlaidHandler
1val plaidHandler: PlaidHandler = 2 Plaid.create(application, linkTokenConfiguration)
Open Link
1linkAccountToPlaid.launch(plaidHandler)
Create a Configuration
Once the Link token is passed to your app, you will create an instance of LinkTokenConfiguration
, then create a Handler using Plaid.create()
passing the previously created LinkTokenConfiguration
.
1var linkConfiguration = LinkTokenConfiguration(2 token: "<#LINK_TOKEN_FROM_SERVER#>",3 onSuccess: { linkSuccess in4 // Send the linkSuccess.publicToken to your app server.5 }6)
Create a Handler
A Handler
is a one-time use object used to open a Link session. The Handler
must
be retained for the duration of the Plaid SDK flow. It will also be needed to respond to OAuth Universal Link
redirects. For more details, see the OAuth guide.
1let result = Plaid.create(configuration)2switch result {3 case .failure(let error):4 logger.error("Unable to create Plaid handler due to: \(error)")5 case .success(let handler):6 self.handler = handler7}
Initiate the Link preloading process by invoking the create
function.
1<TouchableOpacity2 style={styles.button}3 onPress={() => {4 create({token: linkToken});5 setDisabled(false);6 }7 }>8 <Text style={styles.button}>Create Link</Text>9</TouchableOpacity>
Call Plaid.create
(or, if using React, usePlaidLink
) when initializing the view that is responsible for loading Plaid.
1// The usePlaidLink hook manages Plaid Link creation2// It does not return a destroy function;3// instead, on unmount it automatically destroys the Link instance4const config: PlaidLinkOptions = {5 onSuccess: (public_token, metadata) => {}6 onExit: (err, metadata) => {}7 onEvent: (eventName, metadata) => {}8 token: 'GENERATED_LINK_TOKEN',9};1011const { open, exit, ready, submit } = usePlaidLink(config);
Submit the user’s phone number
Call the submit
method on the Plaid handler you created earlier with the user's phone number. The semantics depend on the language/platform, but all methods are called submit
.
1val submissionData = SubmissionData(phoneNumber)2plaidHandler.submit(submissionData)
1// Create a model that conforms to the SubmissionData interface2struct PlaidSubmitData: SubmissionData {3 var phoneNumber: String?4}56let data = PlaidSubmitData(phoneNumber: "14155550015")78self.handler.submit(data)
1submit({2 "phone_number": "+14155550123"3})
1handler.submit({2 "phone_number": "+14155550123"3})
Open Layer UI on the LAYER_READY event
Listen to the events on the Plaid handler via onEvent
. For platform-specific details, see the Link documentation for your platform.
If you receive LAYER_READY
, the user is eligible for the Layer flow and you should proceed to open Link according to the Link documentation for your platform.
If you receive LAYER_NOT_AVAILABLE
, the user is not eligible for the Layer flow. You can clean up the handler you created earlier and fall back to whatever non-Layer onboarding flow fits your application (e.g. a traditional Link session, or other custom flow for your app).
1Plaid.setLinkEventListener { event ->2 when(event.eventName) {3 is LAYER_READY -> {4 // open link5 linkAccountToPlaid.launch(plaidHandler)6 }7 is LAYER_NOT_AVAILABLE -> {8 // run fall back flow9 }10 else -> { Log.i("Event", event.toString()) }11}
1var linkSessionID: String?23linkTokenConfiguration.onEvent = { [weak self] linkEvent in4 guard let self = self else { return }5 switch linkEvent.eventName {6 case .layerReady:7 self.handler.open(presentUsing: .viewController(self))8 break9 case .layerNotAvailable:10 // Fall back on non-Layer flows, clean up11 break12 default:13 // Other cases ignored in this use case.14 break15 }16}
1usePlaidEmitter((event: LinkEvent) => {2 switch (event.eventName) {3 case LinkEventName.LAYER_READY:4 // Open Link5 open({...})6 break;7 case LinkEventName.LAYER_NOT_AVAILABLE:8 // Run another fallback flow9 break;10 default:11 // Other cases ignored in this use case12 break;13 }14});
1//Same onEvent handler from Link create sample2onEvent: (eventName, metadata) => {3 switch(eventName) {4 case "LAYER_READY":5 // Open Link6 open({...})7 break;8 case "LAYER_NOT_AVAILABLE":9 // Run another fallback flow10 break;11 default:12 //Other cases ignored in this use case13 break;14}
Get the public token from the onSuccess callback
On successful completion, an onSuccess
callback will be invoked, similar to the standard Link flow. Capture the public_token
from onSuccess
.
1val profileToken = success.publicToken2// Send the public token to your backend
1onSuccess: { linkSuccess in2}3// Send the public token to your backend
1const onSuccess = (success: LinkSuccess) => {2 let publicToken = linkSuccess.publicToken3 // Send the public token to your backend4};
1onSuccess: (public_token) => {2 const publicToken = public_token3 // Send the public token to your backend4};
Get user account data
Call /user_account/session/get
to retrieve user-permissioned identity information as well as Item access tokens. Unlike typical Plaid Link sessions, where you must first exchange your public token for an access token in order to talk to the Plaid API, the /user_account/session/get
endpoint allows you to retrieve user-permissioned identity information as well as Item access tokens in a single call.
1const request: UserAccountSessionGetRequest = {2 public_token: 'profile-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce992d',3};4try {5 const response = await client.userAccountSessionGet(request);6} catch (error) {7 // handle error8}
1{2 "identity": {3 "phone_number": "+14155550015"4 "name": {5 "first_name": "Leslie",6 "last_name": "Knope"7 },8 "address": {9 "street": "123 Main St.",10 "street2": "Apt 123",11 "city": "Pawnee",12 "region": "Indiana",13 "postal_code": "46001",14 "country": "US"15 },16 "email": "leslie@knope.com",17 "date_of_birth": "1979-01-01",18 "ssn": "987654321",19 "ssn_last4": "4321"20 },21 "items": [22 {23 "item_id": <external_item_id>,24 "access_token": "access-token-<UUID>",25 }26 ],27 "request_id": "j0LkqT9OPdVwjwh"28}