Plaid logo
Docs
ALL DOCS

Balance

  • Introduction to Balance
  • Add Balance to your app
  • Migrate to Signal Rules
Plaid logo
Docs
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about the Plaid API. Try asking questions like:
    Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.
    Plaid.com
    Log in
    Get API Keys
    Open nav

    Add Balance to your app

    Use Balance to fetch real-time balance data

    In this guide, we'll start from scratch and walk through how to use Balance to retrieve real-time balance information. If you are already familiar with using Plaid and are set up to make calls to the Plaid API, make sure to note that you should not include balance in the /link/token/create products array, but you should include signal, if you are using Balance for an ACH risk assessment use case; you can then skip ahead to Fetching balance data.

    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. Your application profile and company profile must be completed before connecting to certain institutions in Production.

    Install and initialize Plaid libraries

    You can use our official server-side client libraries to connect to the Plaid API from your application:

    Select Language
    1// Install via npm
    2npm 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.

    Select Language
    1// Using Express
    2const express = require('express');
    3const app = express();
    4app.use(express.json());
    5
    6const { Configuration, PlaidApi, PlaidEnvironments } = require('plaid');
    7
    8const 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});
    17
    18const client = new PlaidApi(configuration);

    Create an Item in Link

    Plaid Link is a drop-in module that provides a secure, elegant authentication flow for each institution that Plaid supports. Link makes it secure and easy for users to connect their bank accounts to Plaid. Note that these instructions cover Link on the web. For instructions on using Link within mobile apps, see the Link documentation.

    Using Link, we will create a Plaid Item, which is a Plaid term for a login at a financial institution. An Item is not the same as a financial institution account, although every account will be associated with an Item. For example, if a user has one login at their bank that allows them to access both their checking account and their savings account, a single Item would be associated with both of those accounts. If you want to customize Link's look and feel, you can do so from the Dashboard.

    If you are using Balance for a payments use case and you do not set the Link Account Select UI to "enabled for one account", your UI flow when creating a payment must handle the scenario of an end user linking an Item with multiple accounts and allow them to specify which account to use for the payment.

    In order to launch Link in Production, you must select use cases for your Link customization. This requirement is not enforced in Sandbox.

    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.

    If using Balance for ACH return risk assessment, include signal in the products array, along with all other Plaid product(s) you will be using with Balance.

    For all other Balance use cases, omit signal, but instead include the Plaid product(s) you will be using with Balance in the products array.

    balance cannot be included in the products array when calling /link/token/create.

    Create a link_token
    Select Language
    1app.post('/api/create_link_token', async function (request, response) {
    2 // Get the client_user_id by searching for the current user
    3 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: ['signal, auth'],
    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 error
    22 }
    23});
    Install Link dependency
    Select Language
    1<head>
    2 <title>Connect a bank</title>
    3 <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
    4</head>
    Configure the client-side Link handler
    1const linkHandler = Plaid.create({
    2 token: (await $.post('/create_link_token')).link_token,
    3 onSuccess: (public_token, metadata) => {
    4 // Send the public_token to your app server.
    5 $.post('/exchange_public_token', {
    6 public_token: public_token,
    7 });
    8 },
    9 onExit: (err, metadata) => {
    10 // Optionally capture when your user exited the Link flow.
    11 // Storing this information can be helpful for support.
    12 },
    13 onEvent: (eventName, metadata) => {
    14 // Optionally capture Link flow events, streamed through
    15 // this callback as your users connect an Item to Plaid.
    16 },
    17});
    18
    19linkHandler.open();

    Get a persistent access_token

    Next, on the server side, we need to exchange our public_token for an access_token and item_id. The access_token will allow us to make authenticated calls to the Plaid API. Doing so is as easy as calling the /item/public_token/exchange endpoint from our server-side handler. We'll use the client library we configured earlier to make the API call.

    Save the access_token and item_id in a secure datastore, as they’re used to access Item data and identify webhooks, respectively. The access_token will remain valid unless you actively chose to expire it via rotation or remove the corresponding Item via /item/remove. The access_token should be stored securely, and never in client-side code. A public_token is a one-time use token with a lifetime of 30 minutes, so there is no need to store it.

    Select group for content switcher
    Select Language
    1app.post('/api/exchange_public_token', async function (
    2 request,
    3 response,
    4 next,
    5) {
    6 const publicToken = request.body.public_token;
    7 try {
    8 const response = await client.itemPublicTokenExchange({
    9 public_token: publicToken,
    10 });
    11
    12 // These values should be saved to a persistent database and
    13 // associated with the currently signed-in user
    14 const accessToken = response.data.access_token;
    15 const itemID = response.data.item_id;
    16
    17 res.json({ public_token_exchange: 'complete' });
    18 } catch (error) {
    19 // handle error
    20 }
    21});

    Fetching Balance data

    Now that the authentication step is out of the way, we can begin using authenticated endpoints from the Plaid API.

    There are two ways to use Balance: by using /signal/evaluate, or by using /accounts/balance/get.

    If you are using Balance to evaluate a proposed ACH transaction for return risk, use /signal/evaluate.

    For all other use cases, use /accounts/balance/get.

    Using /signal/evaluate
    Creating a Balance-only ruleset

    In the Dashboard, navigate to Signal->Rules to create a Balance-only ruleset. When you do, Plaid will pre-populate a suggested ruleset; you can either use it as-is or customize it.

    In Sandbox, you will be offered a choice between Balance-only and Signal Transaction Score-powered rulesets. To use Balance, select "Balance-only". In Production, Signal Transaction Score rulesets will only be provided as an option if you are Production-enabled for the Signal Transaction Scores product.

    Getting the account_id

    If you are using /signal/evaluate, you will need to know the account_id of the account that is being debited. You can get this in multiple ways, the simplest of which are: by using the onSuccess callback in Link (metadata.accounts[].id) or by calling /accounts/get.

    1{
    2 ...
    3 accounts: [
    4 {
    5 id: 'ygPnJweommTWNr9doD6ZfGR6GGVQy7fyREmWy',
    6 name: 'Plaid Checking',
    7 mask: '0000',
    8 type: 'depository',
    9 subtype: 'checking',
    10 verification_status: null
    11 },
    12 {
    13 id: '9ebEyJAl33FRrZNLBG8ECxD9xxpwWnuRNZ1V4',
    14 name: 'Plaid Saving',
    15 mask: '1111',
    16 type: 'depository',
    17 subtype: 'savings'
    18 }
    19 ],
    20 ...
    21}
    Select Language
    1const request: AccountsGetRequest = {
    2 access_token: ACCESS_TOKEN,
    3};
    4try {
    5 const response = await plaidClient.accountsGet(request);
    6 const accounts = response.data.accounts;
    7} catch (error) {
    8 // handle error
    9}

    A sample response is below (note that /accounts/get returns balance data, but it is cached and not updated in real time):

    1{
    2 "accounts": [
    3 {
    4 "account_id": "blgvvBlXw3cq5GMPwqB6s6q4dLKB9WcVqGDGo",
    5 "balances": {
    6 "available": 100,
    7 "current": 110,
    8 "iso_currency_code": "USD",
    9 "limit": null,
    10 "unofficial_currency_code": null
    11 },
    12 "holder_category": "personal",
    13 "mask": "0000",
    14 "name": "Plaid Checking",
    15 "official_name": "Plaid Gold Standard 0% Interest Checking",
    16 "subtype": "checking",
    17 "type": "depository"
    18 },
    19 {
    20 "account_id": "6PdjjRP6LmugpBy5NgQvUqpRXMWxzktg3rwrk",
    21 "balances": {
    22 "available": null,
    23 "current": 23631.9805,
    24 "iso_currency_code": "USD",
    25 "limit": null,
    26 "unofficial_currency_code": null
    27 },
    28 "mask": "6666",
    29 "name": "Plaid 401k",
    30 "official_name": null,
    31 "subtype": "401k",
    32 "type": "investment"
    33 }
    34 ]
    35 ...

    Once you have obtained both an access_token and an account_id, you can call /signal/evaluate to evaluate the proposed transaction. If you do not specify a ruleset_key, the transaction will be evaluated based on the ruleset named default.

    Select Language
    1const eval_request = {
    2 access_token: 'access-sandbox-71e02f71-0960-4a27-abd2-5631e04f2175',
    3 account_id: '3gE5gnRzNyfXpBK5wEEKcymJ5albGVUqg77gr',
    4 client_transaction_id: 'txn12345',
    5 amount: 123.45,
    6}
    7
    8try {
    9 const eval_response = await plaidClient.signalEvaluate(eval_request);
    10 const core_attributes = eval_response.data.core_attributes;
    11} catch (error) {
    12 // handle error
    13}

    To determine which action to take, use the ruleset.result value of accept, reroute, or review. To learn more about these values, see Signal rules.

    You can also view the real-time current and available balances in core_attributes.current_balance and core_attributes.available_balance.

    Reporting outcomes

    If the result was review, report your final review decision to Plaid using /signal/decision/report or by uploading a CSV. For more details, see Reporting decisions and returns.

    Select Language
    1const decision_report_request = {
    2 client_transaction_id: 'txn12345',
    3 initiated: true,
    4 days_funds_on_hold: 3,
    5};
    6
    7try {
    8 const decision_report_response = await plaidClient.signalDecisionReport(
    9 decision_report_request,
    10 );
    11 const decision_request_id = decision_report_response.data.request_id;
    12} catch (error) {
    13 // handle error
    14}

    If you allow a transfer that does end up returned, report that result back to Plaid as well. You can do this by calling /signal/return/report or by uploading a CSV. For more details, see Reporting decisions and returns.

    Select Language
    1const return_report_request = {
    2 client_transaction_id: 'txn12345',
    3 return_code: 'R01',
    4};
    5
    6try {
    7 const return_report_response = await plaidClient.signalReturnReport(
    8 return_report_request,
    9 );
    10 const request_id = return_report_response.data.request_id;
    11 console.log(request_id);
    12} catch (error) {
    13 // handle error
    14}
    Using /accounts/balance/get

    For more detailed information on the schema returned, see /accounts/balance/get.

    Select group for content switcher
    Select Language
    1const { AccountsGetRequest } = require('plaid');
    2
    3// Pull real-time balance information for each account associated
    4// with the Item
    5const request: AccountsGetRequest = {
    6 access_token: accessToken,
    7};
    8try {
    9 const response = await plaidClient.accountsBalanceGet(request);
    10 const accounts = response.data.accounts;
    11} catch (error) {
    12 // handle error
    13}

    Example response data is below.

    1{
    2 "accounts": [
    3 {
    4 "account_id": "BxBXxLj1m4HMXBm9WZZmCWVbPjX16EHwv99vp",
    5 "balances": {
    6 "available": 100,
    7 "current": 110,
    8 "iso_currency_code": "USD",
    9 "limit": null,
    10 "unofficial_currency_code": null
    11 },
    12 "mask": "0000",
    13 "name": "Plaid Checking",
    14 "official_name": "Plaid Gold Standard 0% Interest Checking",
    15 "subtype": "checking",
    16 "type": "depository"
    17 },
    18 {
    19 "account_id": "dVzbVMLjrxTnLjX4G66XUp5GLklm4oiZy88yK",
    20 "balances": {
    21 "available": null,
    22 "current": 410,
    23 "iso_currency_code": "USD",
    24 "limit": 2000,
    25 "unofficial_currency_code": null
    26 },
    27 "mask": "3333",
    28 "name": "Plaid Credit Card",
    29 "official_name": "Plaid Diamond 12.5% APR Interest Credit Card",
    30 "subtype": "credit card",
    31 "type": "credit"
    32 },
    33 {
    34 "account_id": "Pp1Vpkl9w8sajvK6oEEKtr7vZxBnGpf7LxxLE",
    35 "balances": {
    36 "available": null,
    37 "current": 65262,
    38 "iso_currency_code": "USD",
    39 "limit": null,
    40 "unofficial_currency_code": null
    41 },
    42 "mask": "7777",
    43 "name": "Plaid Student Loan",
    44 "official_name": null,
    45 "subtype": "student",
    46 "type": "loan"
    47 }
    48 ],
    49 "item": {
    50 "available_products": [
    51 "balance",
    52 "credit_details",
    53 "identity",
    54 "investments"
    55 ],
    56 "billed_products": ["assets", "auth", "liabilities", "transactions"],
    57 "consent_expiration_time": null,
    58 "error": null,
    59 "institution_id": "ins_3",
    60 "item_id": "eVBnVMp7zdTJLkRNr33Rs6zr7KNJqBFL9DrE6",
    61 "webhook": "https://www.genericwebhookurl.com/webhook"
    62 },
    63 "request_id": "qk5Bxes3gDfv4F2"
    64}

    Next steps

    If you're ready to launch to Production, see the Launch checklist.

    Launch checklist

    Recommended steps to take before launching in Production

    Launch

    Launch checklist

    Recommended steps to take before launching in Production

    Launch
    Was this helpful?
    Developer community
    GitHub
    GitHub
    Stack Overflow
    Stack Overflow
    YouTube
    YouTube
    Discord
    Discord