Account Type System Guide
Understanding Types, Subtypes, and Calculations for Plaid & SnapTrade
Last Updated: 2025-10-22Related Docs:
SNAPTRADE-ACCOUNTS-TABLE.md, SNAPTRADE-TYPE-MIGRATION.md
📚 Table of Contents
- Overview
- Core Concepts
- Plaid Account Type System
- SnapTrade Account Type System
- Type Mapping & Translation
- User Overrides
- Calculations & Grouping
- The getEffectiveAccountType Function
- Data Flow Diagrams
- Common Pitfalls
Overview
Portfolio Tracker integrates with two main financial data providers:- Plaid: Bank accounts, credit cards, loans (traditional banking)
- SnapTrade: Brokerage accounts (investment platforms like Fidelity)
Core Concepts
Type vs Subtype
Type (Tier 1): Broad categoryinvestment- Accounts with stocks, bonds, mutual fundsdepository- Cash accounts (checking, savings)credit- Credit cardsloan- Loans, mortgages
401k,ira,roth- Retirement account typesbrokerage- Taxable investment accountchecking,savings- Bank account typescredit card- Credit card type
Why Two Tiers?
- Type determines where money goes in calculations
- Investment → Portfolio Value
- Depository → Cash on Hand
- Credit/Loan → Debts
- Subtype determines how it’s displayed and grouped
- 401k, IRA → Retirement group
- Brokerage → Taxable Investments group
Plaid Account Type System
How Plaid Works
Plaid connects to banks and returns accounts with pre-assigned types and subtypes:Plaid’s Type Hierarchy
Database Storage (Plaid)
Table:accounts
Why both?
source_*= What Plaid said originally (never changes)type/subtype= What user wants it to be (can be changed)
SnapTrade Account Type System
How SnapTrade Works
SnapTrade returns brokerage accounts with a single-tier type system:"401K" is specific (like a subtype), but we need a broad category (type) for calculations.
Our Solution: Map to Plaid Format
We translate SnapTrade’s single-tier system to Plaid’s two-tier system:Database Storage (SnapTrade)
Table:snaptrade_accounts
Note: SnapTrade has 6 type-related columns (vs Plaid’s 4) because we need to preserve the original SnapTrade format.
Type Mapping & Translation
SnapTrade → Plaid Conversion
When: During account creation (process-connection/route.ts)
Why This Matters
Before mapping:User Overrides
Why Allow Overrides?
Sometimes categorizations are wrong:- Plaid might mark a brokerage account as “depository”
- User might want to categorize differently for personal reasons
- Institution might not provide accurate account types
How Overrides Work
1. User Changes Type:Override Detection Example
Calculations & Grouping
How Accounts Are Categorized
Primary Rule: Use thetype field to determine category
Net Worth Calculation
Account Grouping in UI
By Type:- Retirement:
subtypeincludes retirement keywords (401k, ira, roth, etc.) - Investments:
type = 'investment'AND not retirement - Cash:
type = 'depository' - Credit Cards:
type = 'credit' - Loans:
type = 'loan'
The getEffectiveAccountType Function
Purpose
Determines the actual type to use for calculations, handling:- User overrides (always respected)
- Edge cases (depository with investments → treat as investment)
- Backward compatibility
Location
lib/account-type-utils.ts
Logic Flow
Why This Matters
WithoutgetEffectiveAccountType():
getEffectiveAccountType():
Usage Across Codebase
Daily Snapshots:Data Flow Diagrams
Plaid Account Creation
SnapTrade Account Creation
User Override Flow
Common Pitfalls
❌ Pitfall 1: Hardcoding SnapTrade Types
❌ Pitfall 2: Forgetting Fallbacks
❌ Pitfall 3: Not Using getEffectiveAccountType
❌ Pitfall 4: Comparing Type to source_account_type
❌ Pitfall 5: Ignoring Hidden Accounts
Quick Reference
Key Files
Key Database Tables
Type Values (Tier 1)
investment- Investment accountsdepository- Cash/bank accountscredit- Credit cardsloan- Loans, mortgagesother- Other account types
Common Subtypes (Tier 2)
Investments:401k,403b,457b- Employer retirement plansira,roth,sep- Individual retirement accountsbrokerage- Taxable investment account529- Education savings
checking- Checking accountsavings- Savings accountmoney market- Money market accounthsa- Health savings account
mortgage- Home mortgageauto- Car loanstudent- Student loan
Testing Your Understanding
Quiz 1: What type/subtype would these be?
- Fidelity 401(k) (SnapTrade) → ?
- Chase Checking (Plaid) → ?
- Vanguard Roth IRA (SnapTrade) → ?
- Capital One Credit Card (Plaid) → ?
type: "investment",subtype: "401k"type: "depository",subtype: "checking"type: "investment",subtype: "roth"type: "credit",subtype: "credit card"
Quiz 2: Will this account be in the retirement group?
Quiz 3: Does this account have a user override?
type !== source_type)
Migration History
Before Migration (Old System)
SnapTrade accounts:- Can’t easily group by category
- Hardcoded type checks everywhere
- No user override support
- Inconsistent with Plaid
After Migration (New System)
SnapTrade accounts:- ✅ Unified with Plaid
- ✅ Easy category grouping (
type === 'investment') - ✅ User override support
- ✅ Historical tracking (snapshots save type/subtype)
- ✅ Backward compatible (old code still works with fallbacks)
Summary
- Both Plaid and SnapTrade use a two-tier system (Type + Subtype)
- Type determines calculations, Subtype determines display
- source_* columns are immutable (what provider said)
- type/subtype columns are mutable (user can override)
- Always use
getEffectiveAccountType()for calculations - User overrides are detected by comparing
typetosource_type - SnapTrade accounts get mapped from SnapTrade format → Plaid format
- Backward compatibility via fallbacks:
account.type || account.account_type
Questions? See:
SNAPTRADE-ACCOUNTS-TABLE.md- Detailed SnapTrade column referenceCRITICAL-VERIFICATION-CHECKLIST.md- Calculation path auditlib/account-type-mappings.ts- Full mapping table