APEX Documentation


Plaid Link Auth Flow

Plaid and Apex have partnered to offer secure, frictionless money transfers. Use Plaid Link to instantly authenticate your customer's account and Sentinel, Apex's ACH API, to quickly and easily move money.

This guide is designed for those who already have a ACH-enabled account at Apex. If that's not you, please contact Apex Tech Integration (techintegration@apexclearing.com) to get started.

Try out the demo

Getting Started

You'll first want to familiarize yourself with Plaid Link, a drop-in integration for the Plaid API that handles input validation, error handling, and multi-factor authentication.

Your customers will use Link to authenticate with their financial institution and select the depository account they wish to use for ACH transactions. From there, you'll receive a Plaid access_token and an Apex processor_token.

The access_token allows you to leverage Plaid products such as Info and Income. The processor_token, which allows Apex to securely validate the bank account and perform real-time balance checks, is included in the Sentinel request to create an ACH Relationship ID.


Step 1: Set up your Plaid and Apex accounts



In order to use the Plaid Link + Apex integration, you will need a Plaid account and you must have access to Sentinel, the Apex ACH API. If you do not currently have Sentinel access, please contact Apex Tech Integration (techintegration@apexclearing.com) or your Account Manager.

If you do not have a Plaid account, create one. Your account will be automatically enabled for integration access. If you already have a Plaid account, contact our support team to enable your account.

To verify that your Plaid account is enabled for the integration, go to the Integrations section of the account dashboard. If you see:

your Plaid account is set up for the integration!

If you do not see this view, you're not enabled for the integration. Please contact support for assistance.

Step 2: Get your public_key



Your public_key is available from the Plaid dashboard:

You have three different API keys

View in Dashboard

a non-sensitive, public identifier that is used to initialize Plaid Link

secret client_id

private identifiers that are required for accessing any financial data

these should never be shared in client-side code

Your public_key is a less privileged version of your client_id and secret. It simply associates accounts you create using Plaid Link with your client_id. All Plaid API requests must be made using your private client_id and secret.

Integrating with Link is easy. All it takes is a few lines of client-side JavaScript and a small server-side handler to exchange the Link public_token for a Plaid access_token and an Apex processor_token.

You can either trigger the "Institution Select" view, a general purpose view that lists all Plaid-supported institutions, or trigger a particular institution's login form. See below:

<button id='linkButton'>Open Link - Institution Select</button>
<button id='bofaButton'>Open Link - Bank of America</button>
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
var linkHandler = Plaid.create({
  apiVersion: 'v2',
  selectAccount: true,
  env: 'sandbox',
  clientName: 'Client Name',
  key: '[YOUR PUBLIC_KEY]',
  product: ['auth'],
  onLoad: function() {
    // The Link module finished loading.
  onSuccess: function(public_token, metadata) {
    // The onSuccess function is called when the user has successfully
    // authenticated and selected an account to use.
    // When called, you will send the public_token and the selected
    // account ID, metadata.account_id, to your backend app server.
    // sendDataToBackendServer({
    //   public_token: public_token,
    //   account_id: metadata.account_id
    // });
    console.log('Public Token: ' + public_token);
    console.log('Customer-selected account ID: ' + metadata.account_id);
  onExit: function(err, metadata) {
    // The user exited the Link flow.
    if (err != null) {
      // The user encountered a Plaid API error prior to exiting.
    // metadata contains information about the institution
    // that the user selected and the most recent API request IDs.
    // Storing this information can be helpful for support.

// Trigger the Bank of America login view directly
document.getElementById('bofaButton').onclick = function() {

// Trigger the standard Institution Select view
document.getElementById('linkButton').onclick = function() {

See the parameter reference for complete documentation on possible configurations.

Plaid.create accepts one argument, a configuration Object, and returns an Object with one function, open, and one property, institutions. open accepts either no arguments or an optional institution type. If no argument is provided, the "Institution Select" view is opened. If a valid institution type is provided, the login form for that particular institution is opened.

The exposed institutions property is an Array of Objects in the form:

[{name: 'Bank of America', id: 'ins_1', auth: true, transactions: true},

The institutions property will be populated with all supported institutions for Plaid Auth. Use the institutions property to dynamically generate a list of supported institutions for your Link integration - by doing so, your app will support new institutions automatically.

Step 4: Write server-side handler



The Link module handles the entire onboarding flow securely and quickly, but does not actually retrieve account data for a user. Instead, the Link module returns a public_token and an account_id—a property on the metadata object—via the onSuccess callback.

This public_token must be exchanged for a Plaid access_token using the /exchange_token API endpoint. You will also send the account_id selected by the user to the /exchange_token endpoint. Plaid will automatically create and return a Apex processor_token. The processor_token is specific to your client ID and the provided account ID.

Exchange this public_token for a Plaid access_token using the /item/public_token/exchange API endpoint. Then, generate an Apex processor_token for the Item by calling the /item/processor_token/apex/create endpoint.

# Exchange token
curl -X POST https://sandbox.plaid.com/item/public_token/exchange \
-H 'Content-type: application/json'
-d '{
  "client_id": "[Plaid Client ID]",
  "secret": "[Plaid secret]",
  "public_token": "[Public token]"

# Create bank account token
curl -X POST https://sandbox.plaid.com/processor/apex/processor_token/create \
-H 'Content-type: application/json'
-d '{
  "client_id": "[Plaid Client ID],
  "secret": "[Plaid secret]",
  "access_token": "[Access token]",
  "account_id": "[Account ID]",
// Change `sandbox` to `development` to test with live users and change
// to `production when you're ready to go live!`
var plaid = require('plaid');

var plaidClient = new plaid.Client('[Plaid client ID]',
                                   '[Plaid secret]',
                                   '[Plaid public key]'
plaidClient.exchangePublicToken('[Plaid Link public_token]', function(err, res) {
  var accessToken = res.access_token;
  // Generate a Apex processor_token
  plaidClient.createProcessorToken(accessToken, '[Account ID]', 'apex', function(err, res) {
    var processorToken = res.processor_token;
# Change `sandbox` to `development` to test with live users and change
# to `production` when you're ready to go live!
client = Client('[Plaid client ID]',
                '[Plaid secret]',
                '[Plaid public key]'],

exchange_token_response = client.Item.public_token.exchange('[Plaid Link public_token]')
access_token = exchange_token_response['access_token']

apex_response = client.Processor.apexProcessorTokenCreate(access_token, '[Account ID]'])
processor_token = apex_response['processor_token']
# Change `sandbox` to `development` to test with live users and change
# to `production` when you're ready to go live!
client = Plaid::Client.new(env: :sandbox,
                  client_id: ENV['PLAID_CLIENT_ID'],
                  secret: ENV['PLAID_SECRET'],
                  public_key: ENV['PLAID_PUBLIC_KEY'])

exchange_token_response = client.item.public_token.exchange('[Plaid Link public_token]')
access_token = exchange_response['access_token']

apex_response = client.processor.apexProcessorTokenCreate(access_token, '[Account ID'])
processor_token = apex_response['processor_token']
// Change `sandbox` to `development` to test with live users and change
// to `production` when you're ready to go live!
PlaidClient plaidClient = PlaidClient.newBuilder()
  .clientIdAndSecret("[Plaid client ID]", "[Plaid secret]")
  .publicKey("[Plaid public key]")
  .sandboxBaseUrl() // Use the Sandbox. Can also be `developmentBaseUrl()` or `productionBaseUrl()`

Response<ItemPublicTokenExchangeResponse> exchangeResponse = plaidClient.service()
    .itemPublicTokenExchange(new ItemPublicTokenExchangeRequest("[Plaid Link public_token]")).execute();

if (exchangeResponse.isSuccessful()) {
  String accessToken = exchangeResponse.body().getAccessToken();
  Response<ItemApexProcessorTokenCreateResponse> apexResponse =
      client().service().itemApexProcessorTokenCreate(new ItemApexProcessorTokenCreateRequest(accessToken, "[Account ID]")).execute();

  if (apexResponse.isSuccessful()) {
    String apexProcessorToken = apexResponse.body().getProcessorToken();

For a valid request, the API will return a JSON response similar to:

  "processor_token": "processor-sandbox-0asd1-a92nc",
  "request_id": "[Unique request ID]"

For possible error codes, see the full listing of Plaid error codes.

Note: The account_id parameter is required if you wish to receive an Apex processor_token. If the account_id parameter is omitted, no processor_token will be generated. Only the access_token will be returned.

Step 5: Test with sandbox credentials



Link's sandbox mode is compatible with Plaid's Sandbox API environment and Apex's "test mode" API. To test the integration in sandbox mode, simply use the Plaid sandbox credentials along with your public_key.

Please contact Apex Tech Integration (techintegration@apexclearing.com) for assistance with Sentinel testing and credentials.

Step 6: Get ready for production



Your account is immediately enabled for our Sandbox and Development environments (https://sandbox.plaid.com and https://development.plaid.com), which allows you to test with Sandbox API credentials and up to 100 live users. To move to Production, please [request access][dashboard-production-access] from the Dashboard.


Find answers to many common integration questions and concerns—such as pricing, sandbox and test mode usage, and more—at our Help Center and [docs][link-docs].