# How to Integrate Retool with Yodlee

- Tool: Retool
- Difficulty: Advanced
- Time required: 45 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Yodlee using a REST API Resource with Yodlee's two-tier authentication: an admin token obtained via client credentials grant for managing users, and a user-specific JWT for accessing financial account data. Build financial aggregation dashboards that display linked bank accounts, transaction histories, account balances, and investment holdings from thousands of financial institutions.

## Build a Yodlee Financial Aggregation Dashboard in Retool

Yodlee is a leading enterprise financial data aggregation platform trusted by hundreds of fintech companies and financial institutions to provide normalized access to bank accounts, investment portfolios, credit cards, loans, and transaction histories from over 17,000 financial institutions worldwide. Building a Retool integration with Yodlee enables operations teams to access aggregated financial data without developing a full front-end application.

A Yodlee-powered Retool dashboard can serve multiple use cases: a financial operations panel that shows all linked accounts for a specific user alongside their transaction history; an account health monitor that surfaces accounts with stale data (where Yodlee's connection to the institution has degraded); or a portfolio overview that aggregates investment holdings and calculates allocation percentages across account types. These dashboards are particularly valuable for fintech operations teams who need to investigate user account issues, verify data quality, or provide frontline support without requiring engineers to run database queries.

Yodlee's authentication architecture requires careful management in Retool. Unlike APIs with a single long-lived key, Yodlee requires two sequential token acquisition steps: first, an admin token obtained via OAuth client credentials (valid for 30 minutes), then a user-specific JWT generated using the admin token (also short-lived). Retool Workflows can automate token refresh to keep the dashboard operational without manual intervention. This complexity is the key differentiator between Yodlee (enterprise-grade) and simpler alternatives like Plaid, which uses a more developer-friendly credential model.

## Before you start

- A Yodlee developer account at developer.yodlee.com — Yodlee requires application registration and approval for production access; sandbox access is available for development
- Yodlee API credentials: Client ID and Client Secret (provided upon application approval from the Yodlee developer portal)
- Knowledge of which Yodlee API environment you are targeting: Sandbox (sandbox.api.yodlee.com) or Production (production.api.yodlee.com)
- At least one Yodlee sandbox user with linked test accounts for development — create test users and link Dag Site bank accounts using Yodlee's sandbox test credentials
- A Retool account with permission to create Resources, Configuration Variables, and Workflows

## Step-by-step guide

### 1. Obtain Yodlee API credentials and understand the two-tier auth model

Register at developer.yodlee.com and create an application to receive your Yodlee API credentials: a Client ID and Client Secret. For development, Yodlee provides Sandbox access immediately after registration. Production access requires a business agreement and approval process. Once you have credentials, understand Yodlee's two-tier authentication before building anything in Retool — this architecture is fundamentally different from standard single-token APIs and must be handled correctly. Tier 1: Admin Token. Obtained by POSTing to the token endpoint with your Client ID and Client Secret using the client credentials OAuth grant. The admin token is valid for 30 minutes and is used ONLY for user management operations (creating users, getting user lists). It cannot access financial data. Tier 2: User JWT. To access any financial data (accounts, transactions, holdings) for a specific user, you must generate a user-level JWT. This requires a POST to the same token endpoint but including the Yodlee username for the specific user in the request body alongside the admin client credentials. The user JWT is also short-lived (typically 30 minutes). In Retool Settings → Configuration Variables, add: YODLEE_CLIENT_ID, YODLEE_CLIENT_SECRET, and YODLEE_API_BASE_URL (set to https://sandbox.api.yodlee.com/ysl for sandbox or https://production.api.yodlee.com/ysl for production). Mark Client Secret as secret. Token management will be handled by JavaScript queries in the app rather than by the resource configuration directly.

```
// Yodlee Admin Token Request — POST body (application/x-www-form-urlencoded)
// POST to {base_url}/auth/token
clientId={{ retoolContext.configVars.YODLEE_CLIENT_ID }}
secret={{ retoolContext.configVars.YODLEE_CLIENT_SECRET }}
```

**Expected result:** You have Yodlee credentials stored in Retool Configuration Variables and understand the two-step token acquisition process required before making any financial data queries.

### 2. Create the Yodlee REST API Resource and token acquisition queries

In Retool, navigate to the Resources tab and Add Resource. Select REST API. Name it 'Yodlee API'. In the Base URL field, enter {{ retoolContext.configVars.YODLEE_API_BASE_URL }}. Because Yodlee's tokens are dynamic and short-lived (not static configuration values), use 'No Auth' as the authentication type in the resource — you will pass the token in individual query headers using dynamic references. In the Headers section, add a default header: Api-Version = 1.1 (required for all Yodlee requests). Click Save Changes. Now create token management queries in your Retool app. Open or create an app, then in the Code panel create a JavaScript query named 'getAdminToken'. This query POSTs to the Yodlee token endpoint and stores the result. Set the query type to JavaScript and write code that uses fetch() with Retool's built-in utilities to call the token endpoint. Alternatively, create a REST query named 'fetchAdminToken': select the Yodlee API resource, set Method to POST, Path to /auth/token, Body Type to x-www-form-urlencoded, and Body to clientId={{ retoolContext.configVars.YODLEE_CLIENT_ID }}&secret={{ retoolContext.configVars.YODLEE_CLIENT_SECRET }}. Create a second query named 'fetchUserToken' with the same configuration but add the loginName parameter: clientId={{ retoolContext.configVars.YODLEE_CLIENT_ID }}&secret={{ retoolContext.configVars.YODLEE_CLIENT_SECRET }}&loginName={{ userIdInput.value }}. The user token response contains an 'access_token' string — reference this token in subsequent financial data queries as a custom Authorization header: { Authorization: 'Bearer ' + fetchUserToken.data.token.accessToken }.

```
// Yodlee User Token Request — form-encoded POST
// Use loginName to get user-specific JWT
// POST {base_url}/auth/token
clientId={{ retoolContext.configVars.YODLEE_CLIENT_ID }}&secret={{ retoolContext.configVars.YODLEE_CLIENT_SECRET }}&loginName={{ userIdInput.value }}
```

**Expected result:** The fetchAdminToken and fetchUserToken queries successfully return Yodlee JWT tokens visible in the Results panel.

### 3. Build queries to retrieve accounts and balances

With token acquisition working, build the financial data queries. Create a new query named 'getAccounts', select the Yodlee API resource, set Method to GET, and Path to /accounts. In the Headers section of this specific query, add a custom header: Authorization = Bearer {{ fetchUserToken.data.token.accessToken }}. This passes the user-level JWT for the selected user — if the user token hasn't been fetched yet, set a run dependency: in the query's Advanced settings, under 'Run after query', select fetchUserToken. This ensures the user token is always fresh before the accounts query runs. Add a URL parameter: key 'container', value 'bank,creditCard,investment,insurance,loan' to retrieve all account types. The accounts response contains an 'account' array with objects including: id, accountName, accountNumber (masked), accountType, balance.amount, balance.currency, providerName, refreshInfo.lastRefreshed, and refreshInfo.statusCode. Create a transformer for the accounts query that extracts and normalizes this data, converting balance amounts to a consistent currency display format and calculating data freshness in hours. Create a second query 'getTransactions' with Method GET, Path /transactions, the same Authorization header dependency, and URL parameters: 'fromDate' = {{ dateRange.startDate }}, 'toDate' = {{ dateRange.endDate }}, 'accountId' = {{ accountsTable.selectedRow?.id || '' }}, 'top' = 100.

```
// Transformer: normalize Yodlee accounts response
const accounts = data.account || [];
return accounts.map(acct => {
  const lastRefreshed = acct.refreshInfo?.lastRefreshed
    ? new Date(acct.refreshInfo.lastRefreshed)
    : null;
  const hoursOld = lastRefreshed
    ? Math.floor((Date.now() - lastRefreshed.getTime()) / (1000 * 60 * 60))
    : null;
  const statusCode = acct.refreshInfo?.statusCode;
  const isHealthy = statusCode === 0 || statusCode === 801; // 0=ok, 801=ok_partial

  return {
    id: acct.id,
    account_name: acct.accountName,
    account_number: acct.accountNumber || 'N/A',
    account_type: acct.accountType,
    provider: acct.providerName,
    balance: acct.balance
      ? `${acct.balance.currency} ${acct.balance.amount.toFixed(2)}`
      : 'N/A',
    balance_amount: acct.balance?.amount || 0,
    last_refreshed: lastRefreshed ? lastRefreshed.toLocaleString() : 'Never',
    data_age_hours: hoursOld,
    connection_status: isHealthy ? 'Healthy' : `Error (${statusCode})`
  };
});
```

**Expected result:** The getAccounts query returns a normalized list of financial accounts with balance, provider, refresh time, and connection health status.

### 4. Build the financial dashboard UI

With queries configured, build the dashboard. Add a Text Input component named 'userIdInput' at the top with label 'Yodlee User Login Name'. Add a 'Load Data' button that triggers fetchUserToken on click (which cascades to getAccounts via the query dependency). Below the user input, add a Stats row: total account count, total net assets (sum of positive balances), total liabilities (credit card and loan balances), and accounts with connection errors (count where connection_status is not 'Healthy'). Drag a Table component, bind it to {{ getAccounts.data }}, and configure columns: provider, account_name, account_type, balance, last_refreshed, data_age_hours (with conditional formatting: red text if > 24 hours), and connection_status (green for Healthy, red for Error). When a row is selected, trigger the getTransactions query via event handler. Add a second Table component below for transactions, bound to {{ getTransactions.data }}. Create a transformer for transactions that extracts: date, merchant name (from transaction.merchant.name or transaction.description), amount (positive for credits, negative for debits), category (from transaction.highLevelCategoryId or transaction.categoryId lookup), and base type (CREDIT or DEBIT). Add a Date Range Picker that controls the transaction query parameters. For fintech applications managing large user populations across multiple Yodlee accounts, RapidDev can help architect a scalable Retool solution with token caching and multi-user management.

```
// Transformer: normalize Yodlee transactions
const transactions = data.transaction || [];
return transactions.map(t => ({
  id: t.id,
  date: t.date,
  description: t.merchant?.name || t.description || 'N/A',
  amount: t.baseType === 'DEBIT'
    ? -Math.abs(t.amount.amount)
    : Math.abs(t.amount.amount),
  currency: t.amount.currency,
  category: t.categoryType || t.highLevelCategoryId || 'Uncategorized',
  base_type: t.baseType,
  account_id: t.accountId,
  status: t.status
}));
```

**Expected result:** The financial dashboard shows account health status and balances in the accounts table, and transaction history for the selected account in the transactions table.

### 5. Implement token refresh automation with Retool Workflows

Yodlee tokens expire after 30 minutes, which means dashboards left open will eventually fail with 401 errors as tokens expire mid-session. Build an automatic refresh mechanism to keep the dashboard operational. Option 1 — In-app polling: Create a Timer component in Retool (drag from the component panel) and set it to run every 25 minutes. Connect its trigger event to run fetchUserToken (which automatically re-runs getAccounts and getTransactions via dependencies). This keeps the session active for as long as the app is open. Option 2 — Retool Workflow: For more robust token management in production, create a Retool Workflow. Set a schedule trigger at 25-minute intervals. Add a Resource Query block that POSTs to the Yodlee token endpoint using your admin credentials and stores the token in a Retool Database row keyed by user ID. In your Retool app, read the current token from Retool Database rather than calling the token endpoint directly. This decouples token management from the dashboard UI. Add error handling to both approaches: if a token fetch fails (network error or invalid credentials), display an error notification in the dashboard and disable query triggers to prevent cascading failures. Reference the access token in financial data query headers dynamically: in each query's Headers section, add Authorization = Bearer {{ fetchUserToken.data?.token?.accessToken || '' }}. The optional chaining (?.) prevents errors if the token query hasn't run yet.

```
// JavaScript: check token validity before running financial queries
const tokenData = fetchUserToken.data?.token;
if (!tokenData || !tokenData.accessToken) {
  utils.showNotification({
    title: 'Authentication Required',
    description: 'Yodlee session expired. Re-enter user ID and click Load Data.',
    type: 'warning'
  });
  return;
}
// Token valid — trigger dependent queries
await getAccounts.trigger();
await getTransactions.trigger();
```

**Expected result:** The dashboard automatically refreshes Yodlee tokens every 25 minutes and shows session status, preventing mid-session authentication failures.

## Best practices

- Store Yodlee Client ID and Client Secret in Retool Configuration Variables marked as secret — these credentials provide admin-level access to all user financial data in your Yodlee environment and must be treated with the same security as database root credentials
- Never cache Yodlee financial data for more than 30 minutes — Yodlee tokens expire at 30 minutes, so cached data beyond this window may have been fetched with an already-expired token; refresh on every session start
- Implement token expiry detection in all financial data queries: check for 401 responses and automatically trigger fetchUserToken before retrying — do not rely solely on the 30-minute refresh timer
- Use Yodlee's refresh status codes to communicate account health to end users: code 0 means data is current, codes in the 400-800 range indicate connection issues requiring user action (MFA challenge, credential re-entry)
- Always display Yodlee's 'lastRefreshed' timestamp alongside balance data — financial data ages quickly and users must understand that Retool displays the last synced balance from Yodlee, not necessarily the current account balance
- For production Retool apps accessing real user financial data, implement Retool's user-level access controls so operators only see data for users assigned to their support queues — financial data carries significant privacy obligations
- Use Retool Workflows rather than in-app JavaScript for token refresh logic in production — Workflows provide centralized token management, retry handling, and audit logging that is harder to implement reliably in app-level queries

## Use cases

### Build a user financial account health monitor

Create a Retool panel that queries all Yodlee linked accounts for a specific user and displays account status, balance freshness, and provider connection health. Highlight accounts where Yodlee's data refresh has failed or data is older than 24 hours, enabling support teams to identify and assist users with connection issues without accessing the user's actual credentials.

Prompt example:

```
Build a Retool dashboard that shows all Yodlee linked accounts for a given user ID — display account name, institution name, account type, current balance, last refresh time, and connection status. Color-code rows red if the last refresh is older than 24 hours or if the account status shows an error.
```

### Build a transaction analysis and categorization review panel

Create a Retool financial analysis panel that queries Yodlee transactions for a user across all linked accounts. Display transactions in a filterable Table with Yodlee's merchant categorization, normalized transaction amounts, and merchant names. Include a date range selector, category filter, and spending totals by category shown in a Pie Chart.

Prompt example:

```
Build a Retool panel querying Yodlee transactions for a user ID across all accounts in a date range. Show a Table with merchant name, amount, date, and Yodlee category. Include a Pie Chart of spending by category and a date range picker to filter the transaction window.
```

### Build a portfolio holdings and net worth dashboard

Create a Retool investment dashboard that queries Yodlee holdings data for investment accounts, displaying securities by type, quantity, value, and percentage of total portfolio. Show net worth across all account types (checking, savings, investment, credit) in summary cards, and chart portfolio allocation by asset class.

Prompt example:

```
Build a Retool portfolio dashboard pulling Yodlee holdings for investment accounts — show a Table of securities with symbol, quantity, current value, and allocation %. Display total net worth across all account types in Stats components at the top.
```

## Troubleshooting

### Admin token request returns 400 Bad Request or 'Invalid clientId/secret'

Cause: Yodlee's token endpoint requires credentials in application/x-www-form-urlencoded format with exact field names 'clientId' and 'secret'. Sending JSON body or using incorrect parameter names (e.g., 'client_id' instead of 'clientId') causes a 400 error. Sandbox and production credentials are separate — using sandbox credentials against the production URL also causes this error.

Solution: Set the query Body Type to x-www-form-urlencoded (not JSON) and verify the field names are exactly 'clientId' and 'secret' (camelCase). Confirm that the YODLEE_API_BASE_URL configuration variable matches your credentials environment: https://sandbox.api.yodlee.com/ysl for sandbox or https://production.api.yodlee.com/ysl for production. Test with the exact URL and body in the query Results panel before referencing in other queries.

### Financial data queries return 401 Unauthorized despite having a valid admin token

Cause: Yodlee financial data endpoints (accounts, transactions, holdings) require a USER-level JWT, not the admin token. The admin token only authorizes user management operations. Using the admin token to access financial data will always return 401.

Solution: Create a separate fetchUserToken query that includes the 'loginName' parameter of the specific user in the token request body alongside client credentials. Reference the resulting user-level access token (at data.token.accessToken) in the Authorization header of all financial data queries. Never use the admin token directly for financial data access.

```
// Correct Authorization header for financial data queries
// Use user token, NOT admin token
Authorization: Bearer {{ fetchUserToken.data.token.accessToken }}
```

### getAccounts returns empty account array for a user that has linked accounts

Cause: Yodlee's sandbox uses specific test user IDs and test institutions. If the user login name does not match an existing Yodlee user in your environment, or if the user has no linked accounts, the accounts endpoint returns an empty array. Real user accounts also return no data if they have not completed the linking process through Yodlee FastLink.

Solution: Verify the user login name in the Yodlee developer portal under your application's user list. For sandbox testing, use Yodlee's pre-created test users with pre-linked Dag Site bank accounts. Confirm that the user has actually linked accounts by checking the Yodlee developer console or calling the /providers/accounts endpoint to see linked provider accounts before querying /accounts.

### Transaction query returns data but amounts appear as positive for both debits and credits

Cause: Yodlee transaction amounts are always returned as positive numbers. The transaction direction is indicated by the 'baseType' field: 'DEBIT' for money leaving the account and 'CREDIT' for money entering. Without checking baseType, all amounts appear positive regardless of whether they are expenses or income.

Solution: Apply baseType-based sign logic in your transformer: amount = t.baseType === 'DEBIT' ? -Math.abs(t.amount.amount) : Math.abs(t.amount.amount). Display debits in red and credits in green using conditional table column formatting in Retool.

```
// Apply correct sign to Yodlee transaction amounts
const signedAmount = t.baseType === 'DEBIT'
  ? -Math.abs(t.amount.amount)
  : Math.abs(t.amount.amount);
```

## Frequently asked questions

### What is the difference between Yodlee and Plaid for a Retool integration?

Yodlee is an enterprise-grade financial aggregation platform with coverage of 17,000+ global institutions and a complex two-tier authentication model, making it suitable for larger fintech operations requiring broad international coverage. Plaid is more developer-friendly with simpler single-token authentication, better documentation, and faster onboarding — preferred for startups and US-focused financial applications. Yodlee's API requires significantly more setup in Retool but provides broader institutional coverage and enterprise-level SLAs.

### How do I access Yodlee sandbox for testing the Retool integration?

Register at developer.yodlee.com to receive sandbox API credentials. Yodlee's sandbox includes pre-built test users with linked accounts at simulated 'Dag Site' financial institutions that respond with test data. Log in to your developer portal to find test user login names and Dag Site institution credentials. Use the sandbox base URL (https://sandbox.api.yodlee.com/ysl) with your sandbox Client ID and Secret. Create additional test users via the /user/register endpoint using your admin token.

### Why does Yodlee require two separate authentication tokens?

Yodlee's two-tier model separates administrative capabilities from data access to enforce the principle of least privilege. The admin token (client credentials grant) authorizes application-level operations like creating users. The user-level JWT is scoped specifically to one user's financial data — it cannot access other users' data, even with the same credentials. This architecture means a compromised user token exposes only that user's data, not the entire platform.

### How do I handle Yodlee's MFA and re-authentication challenges in Retool?

When a linked bank account requires MFA or credential re-entry (indicated by refresh status codes in the 400-range), Yodlee expects users to go through their FastLink widget — a hosted UI for re-authentication that you cannot replicate in a Retool query. In your Retool dashboard, detect these status codes in the accounts transformer and display a message directing the user to your FastLink integration URL to re-authenticate their account. Retool is not the right interface for Yodlee's interactive re-authentication flows.

### Can I use Yodlee to display real-time account balances in Retool?

Yodlee's balance data reflects the last time Yodlee synced with the financial institution — it is not real-time. Refresh intervals depend on your Yodlee plan and the institution's API capabilities: typically every few hours for most banks. You can trigger an on-demand refresh via the /providerAccounts/{id} PUT endpoint with action=REFRESH, but Yodlee processes this asynchronously. Check the refreshInfo.lastRefreshed timestamp in the accounts response to show users when balance data was last updated, and display this prominently in your Retool dashboard.

---

Source: https://www.rapidevelopers.com/retool-integrations/yodlee
© RapidDev — https://www.rapidevelopers.com/retool-integrations/yodlee
