Plaid logo
Docs
ALL DOCS

Income

  • Introduction to Income
  • Bank Income
  • Document Income
  • Payroll Income
  • Add Income to your app
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 Income to your app

    Use Income to fetch income information about your users

    This guide will walk you through how to use Income to retrieve information about your users' current sources of income.

    This is a basic quickstart guide that does not cover all features of the Income product. For more complete information about Income endpoints and capabilities, see the individual product pages for Bank Income, Document Income, and Payroll Income.

    Get Plaid API keys and complete application and company profile

    If you don't already have one, 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 also need to complete your application profile and company profile in the Dashboard if you wish to retrieve real data in Production. The information in your profile will be shared with users of your application when they manage their connection on the Plaid Portal, and must be completed before connecting to certain institutions.

    Install and initialize Plaid libraries

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

    Select group for content switcher
    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, Development, 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 group for content switcher
    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 a User Token

    Unlike many other Plaid products, where you start by creating Items to represent user connections with individual banks, with Income you first start by creating a user_token that represents an individual user. As you add various sources of income, those will all be associated with this single user_token, which allows you to receive consolidated income from different sources by requesting an income report for that user_token.

    To create a user_token, make a call to the /user/create endpoint. This endpoint requires a unique client_user_id value to represent the current user. Typically, this value is the same identifier you're using in your own application to represent the currently signed-in user. This call will return a randomly-generated string for the user_token as well as a separate user ID that Plaid includes in webhooks to represent this user.

    You can only create one user_token per client_user_id. If you try to create a user_token with a client_user_id that you have previously sent to Plaid, you will receive an error.

    Depending on your application, you might wish to create this user_token as soon as your user creates an account, or right before they begin the process of confirming their income data with you.

    1const { IdentityGetRequest } = require('plaid');
    2
    3// Pull Identity data for an Item
    4const request: IdentityGetRequest = {
    5 access_token: accessToken,
    6};
    7try {
    8 const response = await plaidClient.identityGet(request);
    9 const identities = response.data.accounts.flatMap(
    10 (account) => account.owners,
    11 );
    12} catch (error) {
    13 // handle error
    14}
    15
    16// The userId here represents the user's internal user ID with your
    17// application
    18const createUserToken = async (userId) => {
    19 const response = await plaidClient.userCreate({
    20 client_user_id: userId,
    21 });
    22 const newUserToken = response.data.user_token;
    23 const userIdForWebhooks = response.data.user_id;
    24 await updateUserRecordWithIncomeInfo(userId, newUserToken, userIdForWebhooks);
    25};

    Decide what income verification method(s) you want to support

    Income supports three different ways that a user can verify their sources of income.

    • Payroll Income allows Plaid to retrieve information such as recent pay stubs and W-2 forms directly from the user's payroll provider. This tends to provide the most comprehensive data, but is dependent upon the user being able to sign in with their payroll provider.
    • Document Income allows the user to upload images of income-related documents (such as pay stubs and W-2 forms), which Plaid can scan and interpret for you.
    • Bank Income allows the user to connect with their bank to identify deposits that represent sources of income.

    Depending on which methods you want to support (and it's perfectly acceptable to support all three), you will need to implement slightly different processes. While you can collect Payroll and Document Income in the same Link flow, you cannot collect Payroll or Document Income in the same Link flow as Bank Income.

    Fetching Payroll or Document Income data

    The process for implementing Payroll and Document Income is very similar, so we'll cover these two scenarios next.

    Create a Link token for Payroll or Document Income

    Plaid Link is a drop-in module that provides a secure, elegant UI flow to guide your users through the process of connecting Plaid with their financial institutions. With Income, Link can help your user search for and connect to their payroll provider as well as assist them in uploading documents.

    Note that these instructions cover Link on the web. For instructions on using Link within mobile apps, see the appropriate section in the Link documentation.

    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, single-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, initialize Link with the link_token that you just created.

    When calling the /link/token/create endpoint, you'll include an object telling Plaid about your application as well as how to customize the Link experience. When creating a link_token for Payroll or Document Income, there are a few extra values you'll need to supply in this object:

    • You will need to pass in the user_token that you created earlier.
    • You can only list "income_verification" in the list of products
    • You will need to create an object with income_source_types set to ["payroll"] and pass that as the value for income_verification

    Note that in the code sample below, in addition to passing in a user_token, we are also passing in the signed in user's ID as the user.client_user_id value. These are fundamentally different user IDs used for different purposes. The user.client_user_id value is primarily used for logging purposes and allows you to search for activity in the Plaid Dashboard based on the user ID. While its value is most likely the same user ID that you passed in when creating the user_token above, they are otherwise unrelated.

    1// Using Express
    2
    3app.post('/api/create_link_token_for_payroll_income', async function (
    4 request,
    5 response,
    6) {
    7 // Get the client_user_id by searching for the current user.
    8 const clientUserId = await GetSignedInUserId();
    9 // Get the Plaid user token that we stored in an earlier step
    10 const userToken = await GetPlaidTokenForUser();
    11 const request = {
    12 user: {
    13 // This should correspond to a unique id for the current user.
    14 client_user_id: clientUserId,
    15 },
    16 client_name: 'Plaid Test App',
    17 products: ['income_verification'],
    18 user_token: userToken,
    19 income_verification: {
    20 income_source_types: ['payroll'],
    21 },
    22 language: 'en',
    23 webhook: 'https://webhook.example.com',
    24 country_codes: ['US'],
    25 };
    26 try {
    27 const createTokenResponse = await client.linkTokenCreate(request);
    28 response.json(createTokenResponse.data);
    29 } catch (error) {
    30 // handle error
    31 }
    32});

    By default, a link_token created this way will allow the user to collect income information using both the Payroll and Document methods. However, in some cases you might want to permit the user to only use one of these methods. To do that, you can specify the flow_types, as in the example below.

    1income_verification: {
    2 income_source_types: ["payroll"],
    3 payroll_income: { flow_types: ["payroll_digital_income"] },
    4},
    Install the Link library

    You need to install the Link JavaScript library from Plaid in order to use Link in your web application.

    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

    To run Link, you'll first need to retrieve the link_token from the server using the call to /link/token/create described above. Then, call Plaid.create(), passing along that token alongside other callbacks you might want to define. This will return a handler that has an open method. Call that method to open up the Link UI and start the connection process.

    1const linkHandler = Plaid.create({
    2 token: (await $.post('/api/create_link_token_for_payroll_income')).link_token,
    3 onSuccess: (public_token, metadata) => {
    4 // Typically, you'd exchange the public_token for an access token.
    5 // While you can still do that here, it's not strictly necessary.
    6 },
    7 onExit: (err, metadata) => {
    8 // Optionally capture when your user exited the Link flow.
    9 // Storing this information can be helpful for support.
    10 },
    11 onEvent: (eventName, metadata) => {
    12 // Optionally capture Link flow events, streamed through
    13 // this callback as your users connect an Item to Plaid.
    14 },
    15});
    16
    17linkHandler.open();

    If you've had experience with other Plaid products, you're probably used to taking the public_token received from Link and exchanging it on your server for a persistent access_token. However, because Payroll and Document Income are fetched once (and don't require persistent connections with your user's bank), and all of your reports are associated with the user's user_token, there's no need to retrieve or store an access_token in this case.

    Listen for webhooks

    After a user has finished using Link, it may take some time before Plaid has the user's income information available for you to download. In the case of Payroll Income, this typically takes a few seconds. For Document Income, this may take several minutes. Listen for the INCOME: INCOME_VERIFICATION webhook to know when this user's data is ready.

    1app.post('/server/receive_webhook', async (req, res, next) => {
    2 const product = req.body.webhook_type;
    3 const code = req.body.webhook_code;
    4 if (product === 'INCOME' && code === 'INCOME_VERIFICATION') {
    5 const plaidUserId = req.body.user_id;
    6 const verificationStatus = req.body.verification_status;
    7 if (verificationStatus === 'VERIFICATION_STATUS_PROCESSING_COMPLETE') {
    8 await retrieveIncomeDataForUser(plaidUserId);
    9 } else {
    10 // Handle other cases
    11 }
    12 }
    13 // Handle other types of webhooks
    14});

    The user_id value included in this webhook is the same user_id that was returned by Plaid when you first created a user_token for this user.

    Fetch income data

    Now that Plaid has confirmed it has finished processing this user's data, you can fetch the data by making a call to the /credit/payroll_income/get endpoint. Pass in the user_token, and Plaid will return all Payroll and Document Income sources associated with that token.

    1try {
    2 const response = await plaidClient.creditPayrollIncomeGet({
    3 user_token: userToken,
    4 });
    5 const incomeData = response.data;
    6 // Do something interesting with the income data here.
    7} catch (error) {
    8 // Handle error
    9}

    This call will typically return an array of items, each of which represents a connection with a payroll provider. These items, in turn, contain one or more payroll_income objects that contain detailed payroll information for the user. This can include individual pay stubs (with a full breakdown of gross pay, deductions, net pay, and more), as well as W-2 forms and all of their information. See the sample response object in the documentation for a full example of what this response might look like.

    You can distinguish between income that was retrieved through Payroll Income and income that was retrieved through Document Income by looking for an account_id value on the payroll_income object. If the data was retrieved through scanning user documents, this value will be null.

    Fetching Bank Income data

    As an alternative to downloading income data from the user's payroll provider or W-2 forms, Plaid can also find income data in the user's bank account. Plaid will look for deposits that might be sources of income and ask the user to identify which deposits represent income that they wish to share with your application.

    Create a Link token for Bank Income

    Creating a link_token for Bank Income is similar to the process for creating a link_token for Payroll or Document Income. The main differences are:

    • While you still must include "income_verification" as a product, you are allowed to combine this product with other products that you might want to use with this financial institution.
    • Your income_source_types must be set to ["bank"].
    • Your income_verification object must also include a bank_income object, where you have set the value of days_requested. This is the number of days back that Plaid will search for regularly occurring deposits.

    The value of days_requested should a large enough number that you find all relevant deposits, but not so large that the user gets tired waiting for Plaid to retrieve all the relevant data. We recommend 120 days as good balance between the two.

    1app.post('/api/create_link_token_for_bank_income', async function (
    2 request,
    3 response,
    4) {
    5 // Get the client_user_id by searching for the current user.
    6 const clientUserId = await GetSignedInUserId();
    7 // Get the Plaid user token that we stored in an earlier step
    8 const userToken = await GetPlaidTokenForUser();
    9 const request = {
    10 user: {
    11 // This should correspond to a unique id for the current user.
    12 client_user_id: clientUserId,
    13 },
    14 client_name: 'Plaid Test App',
    15 products: ['income_verification', 'transactions', 'assets'],
    16 user_token: userToken,
    17 income_verification: {
    18 income_source_types: ['bank'],
    19 bank_income: { days_requested: 60 },
    20 },
    21 language: 'en',
    22 webhook: 'https://webhook.example.com',
    23 country_codes: ['US'],
    24 };
    25 try {
    26 const createTokenResponse = await client.linkTokenCreate(request);
    27 response.json(createTokenResponse.data);
    28 } catch (error) {
    29 // handle error
    30 }
    31});
    Install the Link library

    As described earlier, you need to install the Link JavaScript library from Plaid to use Link in your web application.

    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

    Retrieve the link_token from the server, then call Plaid.create(), passing along the link_token alongside other callbacks you might want to define. This will return a handler that has an open method, which you can call to start the Link process. This is similar to the process described above, but with Bank Income you will probably want to keep the public_token and exchange it for an access_token, as described in the next step.

    1const linkHandler = Plaid.create({
    2 token: (await $.post('/api/create_link_token_for_bank_income')).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();
    Retrieve metadata about the Link session

    Call /credit/sessions/get in your server after receiving onSuccess, passing in the user_token that you used to create the Link token.

    1try {
    2 const response = await plaidClient.creditSessionsGet({
    3 user_token: userRecord[FIELD_USER_TOKEN],
    4 });
    5 const sessionData = response.data;
    6} catch (error) {
    7 // Handle this error
    8}

    If the user has finished the Bank Income verification flow, then the most recent session will have a bank_income_result with status APPROVED.

    If you are using other Plaid products such as Auth or Balance alongside Bank Income, make sure to capture the public_token from the item_add_result callback and exchange it for an access_token.

    Get a persistent access token (for other products)

    For the purpose of retrieving income data, you don't necessarily need an access_token. Plaid will retrieve the income data for you, and then that data will be associated with the user_token that you created when first configuring Link.

    However, if you are using any other product with this financial institution (such as Transactions, Balance, or Assets), you will need to exchange your public_token for an access_token and item_id. The access_token lets you make authenticated calls to these other products in the Plaid API.

    Exchanging a public_token for an access_token is as easy as calling the /item/public_token/exchange endpoint from the server-side handler. Store the access_token and item_id that get returned in a secure server-side location. Never store this information on the client.

    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});

    Fetch income data

    You can fetch income data by calling the /credit/bank_income/get endpoint using the Plaid client library, passing in the user_token you created earlier. Note that, similar to Document or Payroll Income, this data is static -- it is a snapshot of the user's income data that was retrieved by Plaid when the user ran Link. It does not update or change over time.

    By default, Plaid will only return the most recent report in its response. However, you might want to retrieve more than one report if your user has intentionally run Link multiple times. You can do this by passing an options object with a count value set to an integer.

    1try {
    2 const response = await plaidClient.creditBankIncomeGet({
    3 user_token: userRecord[FIELD_USER_TOKEN],
    4 options: {
    5 count: 3,
    6 },
    7 });
    8 const bankIncomeData = response.data;
    9} catch (error) {
    10 // Handle this error
    11}

    This call typically returns a bank_income array, which consists of a number of different objects that represent the report generated when the user ran Link. These individual reports contain an items array, which in turn contains one or more objects that represent the financial institutions associated with this report. These objects contain a bank_income_accounts array of objects, which gives you information about the individual accounts, as well as a bank_income_sources array of objects, which in turn contains the total amount of income reported, along with historical transactions about that income.

    Each report also contains a bank_income_summary object, that summarizes the total bank income identified across all items in this report.

    Connecting to multiple banks in the same report

    Bank Income allows you to accept data from multiple banks in the same report. To enable this feature, first include enable_multiple_items: true inside the bank_income object that you pass to /link/token/create.

    1const request = {
    2 ...
    3 income_verification: {
    4 income_source_types: ['bank'],
    5 bank_income: {
    6 days_requested: 60,
    7 enable_multiple_items: true,
    8 },
    9 },
    10};

    Then, after the user has exited Link and you receive an onSuccess or onExit callback, there will be a distinct item_add_result returned in the /credit/sessions/get response for each Item the user successfully linked. If the user has completed the Bank Income verification flow for a given Item, there will be a corresponding bank_income_result for that Item with status APPROVED.

    Ensure that you call /credit/sessions/get for both onSuccess and onExit Link callbacks, as the Link callback will only reflect the state of the last Item linked.

    When your user connects with multiple banks in a single Link process, you will receive each bank's data in the item array for that report when calling /credit/bank_income/get.

    Although retrieving multiple items in the same report makes parsing your results easier (and is a better experience for your user), you may still wish to retrieve more than one report when calling /credit/bank_income/get in case your user forgets to add all of their banks the first time and has to run Link multiple times.

    Example code

    For an example of an app that incorporates Document, Payroll and Bank Income, see the React and Node-based Income Sample app. The Income Sample app is an application that uses Income and Liability data to help determine whether the user can qualify for financing on a pre-owned hoverboard. It supports the use of all three types of income data.

    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
    Was this helpful?
    Developer community
    GitHub
    GitHub
    Stack Overflow
    Stack Overflow
    YouTube
    YouTube
    Discord
    Discord