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