plaid-integration
Integrate Plaid API for bank account connections and transaction syncing. Use when implementing financial data access, bank linking, or transaction imports in TypeScript/Bun applications.
When & Why to Use This Skill
This Claude skill streamlines the integration of the Plaid API into TypeScript and Bun applications, enabling secure bank account connections and automated transaction syncing. It provides a comprehensive framework for handling the Plaid Link flow, managing access tokens, designing robust database schemas for financial data, and implementing efficient transaction pagination for high-volume data retrieval.
Use Cases
- Personal Finance Management: Building dashboards that aggregate and categorize transactions from multiple bank accounts to provide users with spending insights.
- Automated Accounting & Reconciliation: Syncing real-time bank data with business accounting software to automate expense tracking and financial reporting.
- Lending and Credit Verification: Accessing verified income and transaction history to streamline loan applications and credit risk assessments.
- Wealth Management Tools: Consolidating investment and liability data to provide a holistic view of a user's net worth and portfolio performance.
| name | plaid-integration |
|---|---|
| description | Integrate Plaid API for bank account connections and transaction syncing. Use when implementing financial data access, bank linking, or transaction imports in TypeScript/Bun applications. |
Plaid API Integration
Integrate Plaid for connecting bank accounts and syncing transactions in TypeScript applications using Bun.
Quick Start
bun add plaid
import { Configuration, PlaidApi, PlaidEnvironments } from 'plaid';
const plaidClient = new PlaidApi(new Configuration({
basePath: PlaidEnvironments[process.env.PLAID_ENV || 'sandbox'],
baseOptions: {
headers: {
'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,
'PLAID-SECRET': process.env.PLAID_SECRET,
}
}
}));
Environment Setup
| Environment | Use Case | HTTPS Required | Real Data |
|---|---|---|---|
sandbox |
Development/testing | No | No (test accounts) |
development |
Limited Production | Yes for redirect, No for popup | Yes (with limits) |
production |
Full production | Yes | Yes |
Critical: Use popup mode (no redirect_uri) for local development to avoid HTTPS requirements:
// Popup mode - works with HTTP localhost
const linkConfig = {
user: { client_user_id: `user-${Date.now()}` },
client_name: 'My App',
products: ['transactions'],
country_codes: ['US'],
language: 'en',
// NO redirect_uri = popup mode
};
Authentication Flow
The Plaid Link flow has 3 steps:
- Create Link Token (backend) → Returns temporary token for Link UI
- User Authenticates (frontend) → Opens Plaid Link, user logs into bank
- Exchange Tokens (backend) → Trade public_token for permanent access_token
See references/code-examples.md for complete implementation.
Key Concepts
- Item: A bank connection (one per institution per user)
- Access Token: Permanent credential for API calls (store securely)
- Public Token: Temporary token from Link (exchange immediately)
- Link Token: Short-lived token to initialize Link UI
Products
Common products to request:
| Product | Description |
|---|---|
transactions |
Transaction history and real-time updates |
auth |
Account and routing numbers |
identity |
Account holder information |
investments |
Investment account data |
liabilities |
Loan and credit card data |
Database Schema
For multi-account support, use SQLite with Bun's built-in driver:
import { Database } from "bun:sqlite";
db.run(`
CREATE TABLE IF NOT EXISTS items (
id TEXT PRIMARY KEY,
access_token TEXT NOT NULL,
institution_id TEXT,
institution_name TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS accounts (
id TEXT PRIMARY KEY,
item_id TEXT NOT NULL,
name TEXT NOT NULL,
type TEXT NOT NULL,
subtype TEXT,
current_balance REAL,
FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS transactions (
id TEXT PRIMARY KEY,
account_id TEXT NOT NULL,
amount REAL NOT NULL,
date TEXT NOT NULL,
name TEXT NOT NULL,
merchant_name TEXT,
category TEXT,
FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE
)
`);
Transaction Pagination
Plaid returns max 500 transactions per request. Always paginate:
let offset = 0;
const count = 500;
let hasMore = true;
while (hasMore) {
const response = await plaidClient.transactionsGet({
access_token,
start_date: '2023-01-01',
end_date: '2024-12-31',
options: { count, offset },
});
// Process response.data.transactions
offset += response.data.transactions.length;
hasMore = offset < response.data.total_transactions;
}
Common Errors
| Error Code | Cause | Solution |
|---|---|---|
INVALID_ACCESS_TOKEN |
Token expired or invalid | Re-link the account |
ITEM_LOGIN_REQUIRED |
Bank requires re-authentication | Use update mode Link |
INVALID_FIELD + "redirect_uri must use HTTPS" |
Using redirect in dev/prod | Use popup mode or HTTPS |
PRODUCTS_NOT_SUPPORTED |
Institution doesn't support product | Check institution capabilities |
Documentation Links
Reference Files
references/code-examples.md- Complete implementation patternsreferences/api-reference.md- API endpoints and responses