Switch Kit

Switch Kit

Switch Kit

This Switch Kit Tutorial is for switching aggregators from Plaid to Envestnet | Yodlee.

Switch Kit Tutorial

This documentation provides a step-by-step guide to migrate from Plaid Link to Link Money, in order access Envestnet | Yodlee data.

There are two prerequisites to working with this guide:

These two sets of credentials are required for the Switch Kit demo to work as expected.

Clone Repository

Go to GitHub, clone, and install the Switch Kit repository. If you are not familiar with cloning repositories from GitHub, you can learn more.

Add Credentials

Once the repository is downloaded onto your machine, navigate to the folder and open it. Within, you will find a file tree. At the root of this file tree, within the repository folder, create a new file called .env and insert the following text:

PLAID_CLIENT_ID=""
PLAID_SECRET=""

LINK_MONEY_CLIENT_ID=""
LINK_MONEY_CLIENT_SECRET=""

Plug in your client IDs and client secrets for Plaid and Link Money from their respective portals. NOTE: You can use a Plaid sandbox or a Plaid development key pair.

Running the Plaid Application

If you’re interested to see how this application runs with Plaid Link, open a terminal at the repository level and run the commands listed here:

npm install --save 
npm run dev

This will run the application on http://localhost:3000. Navigate there to see how the demo application is running with your Plaid instance!

Generate an Authentication Token

Our first step to switch this demo app from Plaid to Link Money is to generate some user authentication. Unlike Plaid, Link Money does not use an SDK. However, requesting an authorization token for Link Money's Plaid-type endpoints is not very different from obtaining a Plaid token.

To authenticate with Plaid, the developer must:

  1. Initialize a new Plaid Client and pass it an object with a clientID and secret specific to the developer.
  2. Create a Link Token by calling the linkCreateToken method and passing it an object that includes further details, including an optional user property and a webhook property for receiving updates.

After making these calls, a Plaid developer receives an authentication token, which they can use to authenticate and launch Plaid Link.

Rather than going through an SDK, Link Money exposes an endpoint (POST https://dev-jhhgu9vc.auth0.com/oauth/token) that replicates Plaid token generation. All of the fields that Plaid uses for authentication should be included in the Link Money token request.

try {
    const { userId, itemId } = options;
    const data = {
      client_id: '{YOUR_CLIENT_ID}',
      client_secret: '{YOUR_CLIENT_SECRET}',
      audience: 'https://link-money-api/',
      grant_type: 'client_credentials',
      organization: '{YOUR_ORGANIZATION_ID}',
    };

		// use a userId string if you require a user token.
    if (userId) {
      data.userId = userId;
    
		// use an item_id string if you require an item token. 
    } else if (itemId) {
      data.item_id = itemId; 
    }
    
    const config = {
      method: 'post',
      url: 'https://dev-jhhgu9vc.auth0.com/oauth/token',
      headers: {
        'Content-Type': 'application/json',
      },
      data: data,
    }

    const createTokenResponse = await axios(config);
    const { data: tokenData } = createTokenResponse;
		const { access_token } = tokenData;
  } catch (error) {
    // any http errors will be surfaced here. 
  }

In the demo application, it makes the most sense to add this code to a backend route, as Link Money’s token signer does not allow calls from frontend-facing codebases. In the demo application, this code lives in /api/methods/index.js. Open that file, and add the following code:

  • Replace (const { userId, itemId } = options;)
export const getLinkMoneyToken = async (req, res, next) => {
	try {
	const { body } = req;
	    const { userId, itemId } = body;
	    const data = {
	      client_id: process.env.LINK_MONEY_CLIENT_ID,
	      client_secret: process.env.LINK_MONEY_CLIENT_SECRET,
	      audience: 'https://link-money-api/',
	      grant_type: 'client_credentials',
	      organization: 'switchkit',
	    };
	
			// use a userId string if you require a user token.
	    if (userId) {
	      data.userId = userId;
	    
			// use an item_id string if you require an item token. 
	    } else if (itemId) {
	      data.item_id = itemId; 
	    }
	    
	    const config = {
	      method: 'post',
	      url: 'https://dev-jhhgu9vc.auth0.com/oauth/token',
	      headers: {
	        'Content-Type': 'application/json',
	      },
	      data: data,
	    }
	
	    const createTokenResponse = await axios(config);
	    const { data: tokenData } = createTokenResponse;
			const { access_token } = tokenData;
			res.status(200).send({ access_token });
	  } catch (error) {
	    // any http errors will be surfaced here. 
			res.status(500).send({ message: error.message });
	  }
}

The code above adapts the original token function into an Express.js controller, which will be accessible from the front end demo application. The above code also adds the credentials from our env file, so that they can be accessed securely from the backend.

Now we only need to add a route to access this method, by altering /api/routes/index.js. Add getLinkMoneyToken to the import list from ../methods:

import {
  createLinkToken,
  getAccounts,
  exchangeForPublicToken,
  getTransactions,
	getLinkMoneyToken
} from '../methods';

And in the same file, create the route:

router.post("/link-money-token", getLinkMoneyToken);

This is all we need to do to make the Link Money authentication token available to the frontend of the demo application!

Replace the Plaid Link with the Link Money Gateway

Now we turn our attention to the frontend. Our Plaid Link code is generated by the file /pages/index.vue. Navigate there now. A large amount of the code in this file - like the createPlaidInstance method and the handler data property, will no longer be needed since we are removing the Plaid Link.

Our first step is to generate a Link Money token, using the backend code we just wrote. Fortunately, there’s a method in this file, generateToken, which is Plaid-specific. We can replace its contents and make it work with Link Money. Replace the function code for generateToken with the following code:

try {
    const request = await axios.post("/api/link-money-token", { userId: "your_user_id" });
    const { data } = request;
    const { access_token } = data;
    return access_token;
  } catch (error) {
    console.log(error);
    return null;
  }

Now let’s alter the contents of the openLink method. This method was opening the Plaid Link, but now we want it to open Link Money’s account linking application. Let’s change its contents:

async openLink() {
	const token = await this.generateToken();
	const linkMoneyGatewayUri = `https://linkmoney-gateway.fingoal.com/api/authenticate?token=${token}`;
	const redirectUri = 'http://localhost:3000/success';
	window.open(`${linkMoneyGatewayUri}&redirectUri=${redirectUri}`);
}

Make sure to mark the openLink function as async, otherwise the token will not generate in time.

We pass the token and a redirect URI for the demo application’s success page to the Link Money Gateway’s URL, and open the page. Follow the account linking process to link an account with Link Money! After you finish, you will redirect to the demo application’s success page.

For Link Money, the developer does not need to maintain the link accounts application - Link Money offers an out-of-the-box link accounts solution that requires only an access token from the call made in the previous step.

By linking users to linkmoney.fingoal.com with an access_token header, the Link Money Gateway will handle user authentication with their banking application, closing the Gateway when the user exits the process.

Access API Data

Now that we’ve linked an account, we can fetch data synchronously from Link Money in two ways:

  1. The Link Money portal inserts some account data in the callback to the demo application’s /success page.
  2. We can use API calls to get transactions and accounts.

Let’s start by looking at the account data in the callback URI. We can add methods to our success.vue file to process the return data:

async digestEvents() {
  const eventsString = this.$route.query.events;
  const events = JSON.parse(eventsString);

	if (!events || events.length === 0) {
    console.log("EVENTS_DATA_NOT_FOUND");
  }
  
  events.forEach((linkEvent) => { 
    const { user_id, item_id, institution, accounts } = linkEvent;
    this.items.push(item_id); 
    this.accounts.push(...accounts)
  });
},

Within the mounted method (which runs when the page loads), add some code to invoke the digestEvents function:

if (this.$route.query.events) {
  this.digestEvents();
}

Doing so, reload the page. If there’s events in the URI for the success page, you will see them load into the accounts table.

Now we can add further methods to fetch transactions from Link Money API. First, we need to create a new token. Notice that this token, unlike the last one, is item-specific. At this point in the flow, both Link Money’s Plaid and Plaid require that all authentication go through items, not users.

async generateToken(itemId) {
  try {
    const request = await axios.post("/api/link-money-token", { itemId: itemId });
    const { data } = request;
    const { access_token } = data;
    return access_token;
  } catch (error) {
    console.log(error);
    return null;
  }
},

With the item token ready, we can fetch transactions from Link Money API:

async getLinkMoneyTransactions(itemToken) {
	// note that you can use the same parameters here that you can for the Plaid request.
  const startDate = moment().subtract(30, 'days').format('YYYY-MM-DD');
  const endDate = moment().format('YYYY-MM-DD');

  const data = {
    start_date: startDate,
    end_date: endDate,
    options: {
      count: 250,
      offset: 0,
    },
  }

  const callConfig = { 
    method: "POST",
    url: `{YOUR_LINK_MONEY_API_URL}/v1/plaid/transactions/get`,
    headers: {
      'Content-Type': "application/json",
      Authorization: "Bearer " + itemToken
    },
    data
  }

  try {
    const transactionsResponse = await axios(callConfig);
    const { data: transactionData } = transactionsResponse;
		const { transactions } = transactionData;
		if (transactions.length === 0) {
      await this.handleError(error);
    } 
    return transactions;
  } catch(error) {
    await this.handleError(error);
  }
},

If you review the code above and compare it with the Plaid GET transactions code in /api/methods/index.js, you will see that the two code snippets are almost exactly identical. Substitute {YOUR_LINK_MONEY_API_URL} in the above snippet with the production Link Money API base URL:

https://linkmoney.fingoal.com

And then add the following iterative function to pull all the transactions for all items in the callback data into the demo application.

async getAllTransactions() {
  for (let i = 0; i < this.items.length; i++) {
    const itemId = this.items[i];
    const token = await this.generateToken(itemId);
    try {
      const transactions = await this.getLinkMoneyTransactions(token);
      this.transactions.unshift(...transactions)
    } catch (error) {
      console.log(error);
    }
  }
},

Finally, invoke the getAllTransactions method in the mounted function for the demo application,

await this.getAllTransactions()

And Link Money transactions associated with all linked accounts will appear in the website’s transactions table!

To review: While the base URL needed to be substituted, the /transactions/get endpoint remains the same, the method (POST) remains the same, the authentication scheme remains the same, and the response data scheme remains the same. The data that returns from this transactions endpoint conforms to the Plaid transaction model, so database and service changes to support Link Money data are not required. For a full roster of Plaid endpoints that Link Money offers, see Plaid Endpoints.

Process Initial Webhook

We have now completed the basics, and the Switch Kit demo application is now linking through Link Money and pulling data from both Plaid and Link Money! As a final additional caveat, though, let’s look at webhooks.

Since Link Money replicates the Plaid methodology, developers configure all webhooks by passing a callback URL of their choice as the webhook property of their call to generate an access token. Note that whatever value is passed into the webhook field on the POST token request will be interpreted as the desired callback URL and will rewrite previous values. This is in accord with Plaid's webhook methodology.

When a user links accounts for the first time, webhooks will trigger and send to all developers who are registered for webhooks on a particular user or item. The webhooks always signal that there's updated financial data available to be fetched from the APIs. These webhooks can contain any of the data updates described in Plaid Webhooks, but one of the first hooks to trigger off a new account linkage will contain this INITIAL_UPDATE webhook payload:

{
  "webhook_type": "TRANSACTIONS",
  "webhook_code": "INITIAL_UPDATE",
  "item_id": "wz666MBjYWTp2PDzzggYhM6oWWmBb",
  "error": null,
  "new_transactions": 19
}

These webhooks are exactly the same as those that Plaid sends. Both the fields and values from Plaid can be reliably expected from Link Money. In this case, the webhook notifies a developer that 19 new transactions are available for an Item of ID wz666MBjYWTp2PDzzggYhM6oWWmBb.

Plaid Schema Compatibility

Transactions

From Yodlee to Plaid

YODLEE 

{
	"date": "string",
	"sourceId": "string",
	"symbol": "string",
	"cusipNumber": "string",
	"highLevelCategoryId": 0,
	"detailCategoryId": 0,
	"description": : {
		"security": "string",
		"original": "string",
		"simple": "string",
		"consumer": "string"
		},
	"memo": "string",
	"settleDate": "string",
	"type": "string",
	"baseType": "CREDIT",
	"categorySource": "SYSTEM",
	"principal": {
		"amount": 0,
		"currency": "USD"
		},
	"lastUpdated": "string",
	"interest": {
		"amount": 0,
		"currency": "USD"
		},
	"price": {
		"amount": 0,
		"currency": "USD"
		},
	"commission": {
		"amount": 0,
		"currency": "USD"
		},
	"id": 0,
	"amount": {
		"amount": 0,
		"currency": "USD"
		},
	"checkNumber": "string",
	"quantity": 0,
	"valoren": "string",
	"isManual": true,
	"merchant": {
		"website": "string",
		"address": {
			"zip": "string",
			"country": "string",
			"address3": "string",
			"address2": "string",
			"city": "string",
			"sourceType": "string",
			"address1": "string",
			"street": "string",
			"state": "string",
			"type": "HOME"
		},
		"contact": {
			"phone": "string",
			"email": "string"
		},
		"categoryLabel": [
			"string"
		],
		"coordinates": {
			"latitude": 0,
			"longitude": 0
		},
		"name": "string",
		"id": "string",
		"source": "YODLEE"
	},
	"sedol": "string",
	"transactionDate": "string",
	"categoryType": "TRANSFER",
	"accountId": 0,
	"createdDate": "string",
	"sourceType": "AGGREGATED",
	"CONTAINER": "bank",
	"postDate": "string",
	"parentCategoryId": 0,
	"subType": "AUTH_HOLD",
	"category": "string",
	"runningBalance": {
		"amount": 0,
		"currency": "USD"
	},
	"categoryId": 0,
	"holdingDescription": "string",
	"isin": "string",
	"status": "POSTED"
}
PLAID

{
    "accounts": [{
        "account_id": "string",
        "balances": {
            "available": "number" | null,
            "current": "number" | null,
            "iso_currency_code": "string" | null,
            "limit": "number" | null,
            "unofficial_currency_code": "string" | null
        },
        "mask": "string" | null,
        "name": "string",
        "official_name": "string" | null,
        "subtype": "string" | null,
        "type": "string"
    }],
    "transactions": [{
        "account_id": "string",
        "amount": "number",
        "iso_currency_code": "string" | null,
        "unofficial_currency_code": "string" | null,
        "category": ["string"] | null,
        "category_id": "string" | null,
        "date": "string",
        "authorized_date": "string" | null,
        "location": {
            "address": "string" | null,
            "city": "string" | null,
            "region": "string" | null,
            "postal_code": "string" | null,
            "country": "string" | null,
            "lat": "number" | null,
            "lon": "number" | null,
            "store_number": "string" | null,
        },
        "name": "string",
        "merchant_name": "string" | null,
        "payment_meta": {
            "by_order_of": "string" | null,
            "payee": "string" | null,
            "payer": "string" | null,
            "payment_method": "string" | null,
            "payment_processor": "string" | null,
            "ppd_id": "string" | null,
            "reason": "string" | null,
            "reference_number": "string" | null
        },
        "payment_channel": "string",
        "pending": "boolean",
        "pending_transaction_id": "string" | null,
        "account_owner": "string" | null,
        "transaction_id": "string",
        "transaction_code": "string" | null,
        "transaction_type": "string"
    }],
    "item": {
        "available_products": ["string"],
        "billed_products": ["string"],
        "consent_expiration_time": "string" | null,
        "error": {
            "error_type": "string",
            "error_code": "string",
            "error_message": "string",
            "display_message": "string" | null,
            "request_id": "string",
            "causes": "array",
            "status": "number" | null,
            "documentation_url": "string",
            "suggested_action": "string"
        },
        "institution_id": "string" | null,
        "item_id": "string",
        "update_type": "string",
        "webhook": "string" | null
    },
    "total_transactions": "number",
    "request_id": "string"
}

Translations

Yodlee FieldPlaid FieldYodlee TypePlaid TypeCompatibleNotes

date

string
string
string

sourceId is a unique ID that the provider site has assigned to the transaction. The source ID is only available for the pre-populated accounts. Pre-populated accounts are the accounts that the FI customers shares with Yodlee, so that the user does not have to add or aggregate those accounts.

string
string

CUSIP numbers consist of nine characters (including letters and numbers) that uniquely identify a company or issuer and the type of financial instrument.

category_id

number
string

Both are aggregator specific but we will write a translation service to return the appropriate categoryId.

number
object
string

name

string
string
string
string

payment_channel

boolean
string

Indicates online or physical transaction

string
string

accounts.type

string
string

accounts.subtype

string
stringnull

baseType has two values → [ CREDIT, DEBIT ] while subtype has a host of values like 401b, thrift savings plan etc

string
object
number
string
string
object
number
string
object
number
string
object
number
string

transaction_id

number
string

The unique ID of the transaction. Like all Plaid identifiers, the transaction_id is case sensitive.

object

amount

number
number

iso_currency_code, unofficial_currency_code

string
stringnull
string
number
string
boolean
object
string

location

object
object

location.postal_code

string
stringnull

location.country

string
stringnull

location.address

string

location.address

string

location.city

string
stringnull
string

location.address

string
stringnull

Plaid only has one address field, so we should probably concat Yodlee's address1, 2, 3 and merchant.street to Plaid's loaction.address

location.address

string
stringnull

location.region

string
stringnull
string
object
string
string
array
object

location.lat

number
numbernull

location.lon

number
numbernull

merchant_name

string
stringnull
string
string
string

authorized_date

string
stringnull
string

accounts.account_id, account_id

number
string

date

string
string
string
string
string
number
string

category

string
[string]null

Remember category in Plaid is array of string. Also, we'll need a translation service here to make sure we return the expected Plaid category.

accounts.balances

object
object

accounts.balances.available

number
numbernull

accounts.balances.iso_currency_code, accounts.balances.unofficial_currency_code

string
stringnull
number
string
string

pending

string
boolean

location.store_number

stringnull

payment_meta

object

all payment_meta fields are for inter-bank transfers. we'll have to exclude these fields for now.

payment_meta.by_order_of

stringnull

payment_meta.payee

stringnull

payment_meta.payer

stringnull

payment_meta.payment_method

stringnull

payment_meta.payment_processor

stringnull

payment_meta.ppd_id

stringnull

payment_meta.reason

stringnull

payment_meta.reference_number

stringnull
string

pending_transaction_id

stringnull

account_owner

stringnull

The name of the account owner. This field is not typically populated and only relevant when dealing with sub-accounts.

accounts.balances.current

numbernull

accounts.balances.limit

numbernull

accounts.mask

stringnull

accounts.name

string

items.available_products

[string]

items.billed_products

[string]

items.consent_expiration_time

stringnull

items.error

object

items.error.error_type

string

items.error.error_code

string

items.error.error_message

string

items.error.display_message

stringnull

items.error.request_id

string

items.error.causes

array

items.error.status

numbernull

items.error.documentation_url

string

items.error.suggested_action

string

items.institution_id

stringnull

items.item_id

string

items.update_type

string

items.webhook

stringnull
string

Yodlee: This is in case of 400 Bad Request

string

Yodlee: This is in case of 400 Bad Request

string

Yodlee: This is in case of 400 Bad Request

total_transactions

number

This can be accessed when you hit the Yodlee getTransactionsCount API

request_id

string

Accounts

Schema

YODLEE

{
  "account": [
    {
      "availableCash": {
        "amount": 0,
        "currency": "AUD"
      },
      "includeInNetWorth": true,
      "moneyMarketBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "enrollmentDate": "string",
      "estimatedDate": "string",
      "memo": "string",
      "guarantor": "string",
      "interestPaidLastYear": {
        "amount": 0,
        "currency": "AUD"
      },
      "lastUpdated": "string",
      "balance": {
        "amount": 0,
        "currency": "AUD"
      },
      "homeInsuranceType": "HOME_OWNER",
      "id": 0,
      "cash": {
        "amount": 0,
        "currency": "AUD"
      },
      "totalCreditLine": {
        "amount": 0,
        "currency": "AUD"
      },
      "providerName": "string",
      "valuationType": "SYSTEM",
      "marginBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "apr": 0,
      "availableCredit": {
        "amount": 0,
        "currency": "AUD"
      },
      "currentBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "isManual": true,
      "profile": {
        "identifier": [
          {
            "type": "NIE",
            "value": "string"
          }
        ],
        "address": [
          {
            "zip": "string",
            "country": "string",
            "address3": "string",
            "address2": "string",
            "city": "string",
            "sourceType": "string",
            "address1": "string",
            "street": "string",
            "state": "string",
            "type": "HOME"
          }
        ],
        "phoneNumber": [
          {
            "type": "HOME",
            "value": "string"
          }
        ],
        "email": [
          {
            "type": "PRIMARY",
            "value": "string"
          }
        ]
      },
      "escrowBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "nextLevel": "string",
      "classification": "OTHER",
      "loanPayoffAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "interestRateType": "FIXED",
      "loanPayByDate": "string",
      "faceAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "policyFromDate": "string",
      "premiumPaymentTerm": "string",
      "policyTerm": "string",
      "repaymentPlanType": "STANDARD",
      "availableBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "accountStatus": "ACTIVE",
      "lifeInsuranceType": "OTHER",
      "fullAccountNumber": "string",
      "premium": {
        "amount": 0,
        "currency": "AUD"
      },
      "aggregationSource": "SYSTEM",
      "overDraftLimit": {
        "amount": 0,
        "currency": "AUD"
      },
      "nickname": "string",
      "term": "string",
      "interestRate": 0,
      "deathBenefit": {
        "amount": 0,
        "currency": "AUD"
      },
      "address": {
        "zip": "string",
        "country": "string",
        "address3": "string",
        "address2": "string",
        "city": "string",
        "sourceType": "string",
        "address1": "string",
        "street": "string",
        "state": "string",
        "type": "HOME"
      },
      "cashValue": {
        "amount": 0,
        "currency": "AUD"
      },
      "holder": [
        {
          "identifier": [
            {
              "type": "NIE",
              "value": "string"
            }
          ],
          "gender": "string",
          "ownership": "PRIMARY",
          "name": {
            "middle": "string",
            "last": "string",
            "fullName": "string",
            "first": "string"
          }
        }
      ],
      "401kLoan": {
        "amount": 0,
        "currency": "AUD"
      },
      "homeValue": {
        "amount": 0,
        "currency": "AUD"
      },
      "accountNumber": "string",
      "createdDate": "string",
      "interestPaidYTD": {
        "amount": 0,
        "currency": "AUD"
      },
      "providerAccountId": 0,
      "collateral": "string",
      "dataset": [
        {
          "lastUpdated": "string",
          "updateEligibility": "ALLOW_UPDATE",
          "additionalStatus": "LOGIN_IN_PROGRESS",
          "nextUpdateScheduled": "string",
          "name": "BASIC_AGG_DATA",
          "lastUpdateAttempt": "string"
        }
      ],
      "runningBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "sourceId": "string",
      "dueDate": "string",
      "frequency": "DAILY",
      "maturityAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "associatedProviderAccountId": [
        0
      ],
      "isAsset": true,
      "principalBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "totalCashLimit": {
        "amount": 0,
        "currency": "AUD"
      },
      "maturityDate": "string",
      "minimumAmountDue": {
        "amount": 0,
        "currency": "AUD"
      },
      "annualPercentageYield": 0,
      "accountType": "string",
      "originationDate": "string",
      "totalVestedBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "rewardBalance": [
        {
          "expiryDate": "string",
          "balanceToReward": "string",
          "balanceType": "EXPIRING_BALANCE",
          "balance": 0,
          "description": "string",
          "balanceToLevel": "string",
          "units": "string"
        }
      ],
      "sourceAccountStatus": "IN_REPAYMENT",
      "derivedApr": 0,
      "policyEffectiveDate": "string",
      "totalUnvestedBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "annuityBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "accountName": "string",
      "totalCreditLimit": {
        "amount": 0,
        "currency": "AUD"
      },
      "policyStatus": "ACTIVE",
      "shortBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "lender": "string",
      "lastEmployeeContributionAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "providerId": "string",
      "lastPaymentDate": "string",
      "primaryRewardUnit": "string",
      "lastPaymentAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "remainingBalance": {
        "amount": 0,
        "currency": "AUD"
      },
      "userClassification": "BUSINESS",
      "bankTransferCode": [
        {
          "id": "string",
          "type": "BSB"
        }
      ],
      "expirationDate": "string",
      "coverage": [
        {
          "amount": [
            {
              "cover": {
                "amount": 0,
                "currency": "AUD"
              },
              "unitType": "PER_FAMILY",
              "type": "DEDUCTIBLE",
              "limitType": "IN_NETWORK",
              "met": {
                "amount": 0,
                "currency": "AUD"
              }
            }
          ],
          "planType": "PPO",
          "endDate": "string",
          "type": "VISION",
          "startDate": "string"
        }
      ],
      "cashApr": 0,
      "autoRefresh": {
        "additionalStatus": "SCHEDULED",
        "asOfDate": "string",
        "status": "ENABLED"
      },
      "oauthMigrationStatus": "IN_PROGRESS",
      "displayedName": "string",
      "fullAccountNumberList": {
        "paymentAccountNumber": "string",
        "unmaskedAccountNumber": "string"
      },
      "amountDue": {
        "amount": 0,
        "currency": "AUD"
      },
      "currentLevel": "string",
      "originalLoanAmount": {
        "amount": 0,
        "currency": "AUD"
      },
      "policyToDate": "string",
      "loanPayoffDetails": {
        "payByDate": "string",
        "payoffAmount": {
          "amount": 0,
          "currency": "AUD"
        },
        "outstandingBalance": {
          "amount": 0,
          "currency": "AUD"
        }
      },
      "paymentProfile": {
        "identifier": {
          "type": "REFERENCE_NUMBER",
          "value": "string"
        },
        "address": [
          {
            "zip": "string",
            "country": "string",
            "address3": "string",
            "address2": "string",
            "city": "string",
            "sourceType": "string",
            "address1": "string",
            "street": "string",
            "state": "string",
            "type": "HOME"
          }
        ],
        "paymentBankTransferCode": {
          "id": "string",
          "type": "ROUTING_NUMBER"
        }
      },
      "CONTAINER": "bank",
      "lastEmployeeContributionDate": "string",
      "lastPayment": {
        "amount": 0,
        "currency": "AUD"
      },
      "recurringPayment": {
        "amount": 0,
        "currency": "AUD"
      }
    }
  ]
}
PLAID

{
    "accounts": [
        {
            "account_id": "string",
            "balances": {
                "available": "number" | null,
                "current": "number" | null,
                "iso_currency_code": "string" | null,
                "limit": "number" | null,
                "unofficial_currency_code": "string" | null
            },
            "mask": "string" | null,
            "name": "string",
            "official_name": "string" | null,
            "subtype": "string" | null,
            "type": "string"
        }
    ],
    "item": {
        "available_products": ["string"],
        "billed_products": ["string"],
        "consent_expiration_time": "string" | null,
        "error": {
            "error_type": "string",
            "error_code": "string",
            "error_message": "string",
            "display_message": "string" | null,
            "request_id": "string",
            "causes": "array",
            "status": "number" | null,
            "documentation_url": "string",
            "suggested_action": "string"
        } | null,
        "institution_id": "string" | null,
        "item_id": "string",
        "update_type": "string",
        "webhook": "string" | null,
    },
    "request_id": "string"
}

Accounts

Yodlee FieldPlaid FieldYodlee TypePlaid TypeCompatibleNotes
object
number
string
boolean
object
number
string
string
string
string
string
object
number
string
string

balances

object
object

balances.available

number
numbernull

balances.iso_currency_code, balances.unofficial_currency_code

string
stringnull
string

account_id

number
string
object
number
string
object
number
string
string
string
object
number
string
number
object
number
string
object
number
string
boolean
object
array
string
string
string
string
string
string
string
string
string
string
string
string
array
string
string
array
string
string
object
number
string
string
string
object
number
string
string
string
object
number
string
string
string
string
string
object
number
string
string
string
string
object
number
string
string
object
number
string
string
string
number
object
number
string
object
string
string
string
string
string
string
string
string
string
string
object
number
string
array
array
string
string
string
string
object
string
string
string
string
object
number
string
object
number
string
string

This may be similar to "mask" of Plaid's account data, if it masks the account number to 4 digits

string
object
number
string
number
string
array
string
string
string
string
string
string
object
number
string
string
string
string
object
number
string
array
boolean
object
number
string
object
number
string
string
object
number
string
number

subtype

string
stringnull
string
object
number
string
array
string
string
string
number
string
string
string
string
number
string
object
number
string
object
number
string

official_name

string
stringnull
object

account.balances.limit

number
numbernull

account.balances.iso_currency_code

string
string
object
number
string
string
object
number
string
string
string
string
object
number
string
object
number
string
string
array
string
string
string
array
array
object
number
string
string
string
string
object
number
string
string
string
string
string
number
object
string
string
string
string

name

string
string
object
string

This may be similar to "mask" of Plaid's account data, if it masks the account number to 4 digits

string
object
number
string
string
object
number
string
string
object
string
object
number
string
number
string
object
object
string
string
array
string
string
string
string
string
string
string
string
string
string
object
string
string

type

string
string
string
object
number
string
object
number
string

items.item_id

Unique Id from Plaid. We will need to generate and send along.

balances.current

numbernull

balances.limit

numbernull

mask

stringnull
stringnull

items.available_products

[string]

A list of products available for the Item that have not yet been accessed.

items.billed_products

[string]

items.consent_expiration_time

stringnull

items.error

object

items.error.error_type

string

items.error.error_code

string

items.error.error_message

string

items.error.display_message

stringnull

items.error.request_id

string

items.error.causes

array

items.error.status

numbernull

items.error.documentation_url

string

items.error.suggested_action

string

items.institution_id

stringnull

Users

{
  "user": {
    "preferences": {
      "dateFormat": "string",
      "timeZone": "string",
      "currency": "AUD",
      "locale": "en_US"
    },
    "address": {
      "zip": "string",
      "country": "string",
      "address3": "string",
      "address2": "string",
      "city": "string",
      "address1": "string",
      "state": "string"
    },
    "loginName": "string",
    "name": {
      "middle": "string",
      "last": "string",
      "fullName": "string",
      "first": "string"
    },
    "id": 0,
    "roleType": "INDIVIDUAL",
    "email": "string",
    "segmentName": "string"
  }
}
No support for Users

Plaid Endpoints

Plaid Webhooks