Skip to content

Data Models

Database models, table structures, and design patterns for the Integration system. This document provides a database-centric view of the Integration architecture.

The Integration system centers on two tables: integrations and integration_mappings, which connect to business entities (Household, Account, Insurance, etc.) via polymorphic relationships.

erDiagram
    advisors ||--o{ integrations : has
    integrations ||--o{ integration_mappings : contains
    integration_mappings ||--o{ integration_mappings : "parent-child"
    users ||--o{ integration_mappings : "deleted_by"

    integration_mappings }o--|| households : "mappable (polymorphic)"
    integration_mappings }o--|| accounts : "mappable (polymorphic)"
    integration_mappings }o--|| insurances : "mappable (polymorphic)"
    integration_mappings }o--|| persons : "mappable (polymorphic)"

    accounts ||--o{ positions : "contains (investment accounts only)"
    accounts ||--o| account_yodlees : "satellite (Yodlee only)"

    yodlee_providers ||--o{ yodlee_provider_accounts : has
    yodlee_provider_accounts ||--o{ account_yodlees : contains

    integrations {
        int id PK
        int advisor_id FK
        enum type "IntegrationType"
        varchar reference
        json credentials
        json settings
        datetime failed_since
        tinyint failed_biz_days
        datetime last_completed_at
        datetime created_at
        datetime updated_at
        datetime deleted_at
    }

    integration_mappings {
        int id PK
        int integration_id FK
        int parent_id FK "self-ref"
        enum mappable_type
        int mappable_id
        varchar reference
        enum sync_status
        datetime last_completed_at
        datetime refreshed_at
        int deleted_by_user_id FK
        datetime created_at
        datetime updated_at
        datetime deleted_at
    }

    households {
        int id PK
        enum source "HouseholdSource"
    }

    accounts {
        int id PK
        enum source "AccountSource"
        decimal cash_balance
        int partner_oauth_client_id
    }

    insurances {
        int id PK
        enum source "InsuranceSource"
        decimal premium
        decimal benefit
    }

    positions {
        int id PK
        int investment_account_id FK
        int security_id FK
        varchar reference
        decimal quantity
        decimal cost_basis
    }

    yodlee_providers {
        int reference PK
        varchar name
        varchar favicon
        varchar logo
    }

    yodlee_provider_accounts {
        int reference PK
        int provider_ref
        enum status
    }

    account_yodlees {
        int account_id PK
        int yodlee_account_ref
        int provider_account_ref
        int status_code
    }

Represents the connection between an Advisor and a Vendor.

ColumnTypeRequiredDescription
idintYesPrimary key
advisor_idintYesFK → advisors
typeenumYesIntegrationType (47 vendors)
referencevarchar(255)NoVendor-specific identifier (e.g., Rep Code)
credentialsjsonNoEncrypted auth credentials (OAuth tokens, API keys)
settingsjsonNoSync settings (sync_note, sync_task booleans)
failed_sincedatetimeNoWhen integration started failing
failed_biz_daystinyintNoConsecutive business days failed (0-255)
last_completed_atdatetimeNoLast successful sync timestamp
created_atdatetimeYesRecord creation time
updated_atdatetimeYesRecord update time
deleted_atdatetimeNoSoft delete timestamp
  • One integration per advisor-vendor pair: An advisor can have at most one active integration per vendor type
  • Credentials encryption: Stored as encrypted JSON, contains OAuth tokens or API keys
  • Failure tracking: failed_since + failed_biz_days enable automatic disabling after threshold
  • Soft deletes: Preserves history, allows restoration

47 supported vendors, split into two categories:

API-based (29 types):

ADDEPAR, ADVYZON, ALBRIDGE, ALLIANZ_API, ASSET_BOOK, ASSET_MARK,
BLACK_DIAMOND, BLUELEAF, BRIDGE_FT, CAPITECT, CIRCLE_BLACK, COMMONWEALTH,
DST, FIN_FOLIO, INVESTIGO, LPL, MAX_MY_INTEREST, MORNINGSTAR_ADVISOR_WORKSTATION,
MORNINGSTAR_OFFICE, NATIONWIDE, ORION, PANORAMIX, REDTAIL, RISKALYZE,
SCHWAB_API, SMART_OFFICE, TAMARAC, WEALTH_ACCESS, WEALTHBOX

File-based (19 types):

ALLIANZ, ALTRUIST, APEX, BETTERMENT, FIDELITY, FIRST_CLEARING,
FLOURISH, FOLIO_INVESTING, INTERACTIVE_BROKERS, JACKSON, LPL,
MY529, PACIFIC_LIFE, PERSHING, RAYMOND_JAMES, RBC, SCHWAB, SEI, TRUST_AMERICA

Note: LPL supports both API-based and File-based integration modes.

Links external entities (vendor accounts) to internal objects (Household, Account, etc.).

ColumnTypeRequiredDescription
idintYesPrimary key
integration_idintYesFK → integrations
parent_idintNoFK → integration_mappings (self-ref, hierarchy)
mappable_typeenumYesTarget entity type (8 types)
mappable_idintYesTarget entity ID
referencevarchar(255)YesVendor’s entity ID
sync_statusenumNopending / running / completed
last_completed_atdatetimeNoLast successful sync
refreshed_atdatetimeNoLast refresh operation
deleted_by_user_idintNoFK → users (manual deletion tracking)
created_atdatetimeYesRecord creation time
updated_atdatetimeYesRecord update time
deleted_atdatetimeNoSoft delete timestamp
  • (mappable_type, mappable_id) - Polymorphic lookup optimization
HOUSEHOLD = 'household' // Root level
PERSON = 'person' // Family members
CONTACT = 'contact' // CRM contacts
ACCOUNT = 'account' // Financial accounts (PRIMARY)
TARGET_CATEGORY_MIX = 'target_category_mix'
INSURANCE = 'insurance' // Insurance policies (PRIMARY)
NOTE = 'note' // CRM notes
TASK = 'task' // CRM tasks

Data Integration Types (sync actual financial data):

  • ACCOUNT - Bank, investment, loan accounts with positions
  • INSURANCE - Life, disability, LTC policies

Mappings form a tree via parent_id:

graph TD
    I[Integration<br/>e.g., Schwab API] --> R[IntegrationMapping<br/>household, parent_id=NULL]
    R --> A1[IntegrationMapping<br/>account]
    R --> A2[IntegrationMapping<br/>account]
    R --> INS[IntegrationMapping<br/>insurance]
    A1 --> P1[Positions synced<br/>with account]

    style R fill:#e1f5fe
    style A1 fill:#fff3e0
    style A2 fill:#fff3e0
    style INS fill:#f3e5f5

Key Rule: Only root mappings (parent_id = NULL) can be synchronized. Child mappings inherit sync status from parent.

ColumnTypeDescription
sourceAccountSource enumOrigin: YODLEE, SCHWAB, FIDELITY, TWEAK (manual), etc.
cash_balancedecimalSynced from integration
partner_oauth_client_idintOAuth connection reference

AccountSource Enum: 45 sources tracking data origin (includes TWEAK for manual entry, YODLEE for aggregation, plus 43 vendor-specific sources).

ColumnTypeDescription
sourceInsuranceSource enumOrigin (5 sources)
premiumdecimalSynced from integration
benefitdecimalCoverage amount

InsuranceSource Enum:

COMMONWEALTH, ADVYZON, JACKSON, ALLIANZ_API, INVESTIGO
ColumnTypeDescription
sourceHouseholdSource enumCRM origin (7 sources)

HouseholdSource Enum:

REDTAIL, WEALTHBOX, ADVYZON, COMMONWEALTH, SMART_OFFICE, ASSET_MARK, LPL
ColumnTypeDescription
referencevarcharIntegration provider’s position ID
investment_account_idintFK → investment_accounts
security_idintFK → securities
quantitydecimalShares/units
cost_basisdecimalOriginal purchase cost

Yodlee uses a different integration architecture from the standard Advisor-Vendor pattern. It is a data aggregation service where end-users (clients) connect their financial institutions directly via OAuth/FastLink.

AspectStandard IntegrationYodlee
InitiatorAdvisor configures connectionClient links their bank accounts
Connection LevelAdvisor ↔ VendorClient ↔ Financial Institution
Storageintegrations tableDedicated Yodlee tables
IntegrationTypeExists in enumNot in enum (separate system)
AccountSourceMatches IntegrationTypeYODLEE in AccountSource enum
erDiagram
    yodlee_providers ||--o{ yodlee_provider_accounts : has
    yodlee_provider_accounts ||--o{ account_yodlees : contains
    account_yodlees ||--|| accounts : "satellite"

    yodlee_providers {
        int reference PK
        varchar name
        varchar favicon
        varchar logo
    }

    yodlee_provider_accounts {
        int reference PK
        int provider_ref
        enum status
    }

    account_yodlees {
        int account_id PK
        int yodlee_account_ref
        int provider_account_ref
        int status_code
    }

Note: Field names in diagrams are abbreviated. See table schemas below for full column names.

Represents financial institutions (banks, brokerages) available through Yodlee.

ColumnTypeDescription
referenceintPK, Yodlee’s provider ID
namevarchar(255)Financial institution name (e.g., “Chase”, “Fidelity”)
faviconvarchar(255)Institution favicon URL
logovarchar(255)Institution logo URL
created_atdatetimeRecord creation time
updated_atdatetimeRecord update time

Represents a user’s connection to a financial institution via Yodlee.

ColumnTypeDescription
referenceintPK, Yodlee’s provider account ID
yodlee_provider_referenceintFK → yodlee_providers
statusenumConnection status (see below)
created_atdatetimeRecord creation time
updated_atdatetimeRecord update time

YodleeProviderAccountStatus Enum:

LOGIN_IN_PROGRESS, USER_INPUT_REQUIRED, IN_PROGRESS,
PARTIAL_SUCCESS, SUCCESS, FAILED

Yodlee-specific metadata for accounts (1:1 relationship with accounts):

ColumnTypeDescription
account_idintPK/FK → accounts
yodlee_account_referenceintYodlee’s account ID (nullable for manual accounts)
yodlee_provider_account_referenceintFK → yodlee_provider_accounts
additional_status_codeintYodlee status code (maps to 30+ status types)
refreshed_atdatetimeLast successful Yodlee sync
flowchart LR
    subgraph Client Actions
        FL[FastLink Widget]
        MR[Manual Refresh]
    end

    subgraph Yodlee API
        YA[Yodlee Aggregation]
    end

    subgraph RightCapital
        PA[YodleeProviderAccount]
        AY[AccountYodlee]
        ACC[Account]
        POS[Position]
    end

    FL -->|OAuth| YA
    MR -->|Refresh| YA
    YA -->|Webhook/Poll| PA
    PA -->|Status Update| AY
    AY -->|Sync Data| ACC
    ACC -->|Holdings| POS

The additional_status_code in account_yodlees maps to 30 different status types:

CodeStatusAction Required
1-3LOGIN_IN_PROGRESS, DATA_RETRIEVAL_IN_PROGRESS, ACCT_SUMMARY_RECEIVEDPoll for refresh
4-5AVAILABLE_DATA_RETRIEVED, PARTIAL_DATA_RETRIEVEDDone (success)
11-12, 26-28, 30CREDENTIALS_UPDATE_NEEDED, INCORRECT_CREDENTIALS, CONSENT_*, INCORRECT_OAUTH_TOKENFastLink Edit flow
9, 14ADDL_AUTHENTICATION_REQUIRED, INVALID_ADDL_INFO_PROVIDEDFastLink Refresh flow
OthersVarious errorsShow error, no action

Action Categories:

  • done - Data retrieved successfully
  • get_refresh - Poll Yodlee for status update
  • put - User must re-authenticate via FastLink Edit
  • manual_refresh - User must provide MFA via FastLink Refresh
  • fail - Unrecoverable error, show message to user
flowchart TD
    subgraph Trigger
        NS[Nightly Sync<br/>scheduled]
        MS[Manual Sync<br/>user action]
        WH[Webhook<br/>real-time]
    end

    subgraph Lookup
        IL[Integration.getSynchronizer]
    end

    subgraph Fetch
        API[API-based<br/>Connector.call → Vendor API]
        FILE[File-based<br/>S3 → Parser]
    end

    subgraph Transform
        VM[Vendor Models]
        IM[Internal Models<br/>Account, Position, Insurance]
    end

    subgraph Persist
        DB[(Database)]
        MAP[IntegrationMappings]
    end

    NS --> IL
    MS --> IL
    WH --> IL
    IL --> API
    IL --> FILE
    API --> VM
    FILE --> VM
    VM --> IM
    IM --> DB
    IM --> MAP
    MAP -->|sync_status=completed| DB

Single integration_mappings table handles all entity types via mappable_type + mappable_id. This enables:

  • Unified sync tracking
  • Consistent audit trail
  • Single query for all linked entities

Business entities (accounts, insurances, households) have source enum columns tracking origin:

  • Enables data quality analysis
  • Supports vendor-specific business logic
  • Audit trail for data provenance

External entity IDs stored in reference columns:

  • integration_mappings.reference - Vendor’s entity ID
  • positions.reference - Vendor’s position ID
  • Enables re-sync and deduplication

Tree structure via parent_id:

  • Root mapping represents household-level link
  • Child mappings track individual accounts/insurances
  • Sync operates at root level, cascades to children

Both core tables use soft deletes (deleted_at):

  • Preserve historical data
  • Enable restoration of accidentally unlinked accounts
  • Track who deleted (deleted_by_user_id)

Integration health monitored via:

  • failed_since - Start of failure period
  • failed_biz_days - Count of business days (max 255)
  • Auto-disable after threshold exceeded
// Integration Model (retail-api/app/Models/Integration.php)
class Integration
{
// Eloquent Relationships
public function advisor(): BelongsTo; // → Advisor
public function integrationMappings(): HasMany; // → IntegrationMapping[]
// Factory Methods (return class-string or null)
public function getIntegratorFqcn(): string|null; // Integrator class name
public function getConnectorFqcn(): string|null; // Connector class name
public function getImporterFqcn(): string|null; // Importer class name
public function getSyncFqcn(): string|null; // Sync class name
public function getConfigFqcn(): string|null; // Config class name
public function getSynchronizer(): Sync; // Instantiated Sync handler
}
// IntegrationMapping Model (retail-api/app/Models/IntegrationMapping.php)
class IntegrationMapping
{
// Eloquent Relationships
public function integration(): BelongsTo; // → Integration
public function parent(): BelongsTo; // → IntegrationMapping (self)
public function children(): HasMany; // → IntegrationMapping[] (self)
public function mappable(): MorphTo; // → Household|Account|Insurance|...
public function deletedByUser(): BelongsTo; // → User
// Business Logic
public function sync(): array; // Trigger sync (root mappings only)
public function isDataIntegrationMapping(): bool; // Check if ACCOUNT or INSURANCE type
}
ComponentPath
Integration Schemapackages/libs/core-models/src/Schemas/Integration.php
IntegrationMapping Schemapackages/libs/core-models/src/Schemas/IntegrationMapping.php
IntegrationType Enumpackages/libs/core-models/src/Enums/Integration/IntegrationType.php
MappableType Enumpackages/libs/core-models/src/Enums/IntegrationMapping/IntegrationMappingMappableType.php
SyncStatus Enumpackages/libs/core-models/src/Enums/IntegrationMapping/IntegrationMappingSyncStatus.php
AccountSource Enumpackages/libs/core-models/src/Enums/Account/AccountSource.php
Retail API Modelsretail-api/app/Models/Integration.php, IntegrationMapping.php
Admin API Modelsadmin-api/app/Models/Integration.php, IntegrationMapping.php
ComponentPath
YodleeProvider Schemapackages/libs/core-models/src/Schemas/YodleeProvider.php
YodleeProviderAccount Schemapackages/libs/core-models/src/Schemas/YodleeProviderAccount.php
AccountYodlee Schemapackages/libs/core-models/src/Schemas/AccountYodlee.php
YodleeProviderAccountStatus Enumpackages/libs/core-models/src/Enums/YodleeProviderAccount/YodleeProviderAccountStatus.php
Yodlee Integratorretail-api/app/Integrations/Yodlee/Integrator.php
Yodlee Connectorretail-api/app/Integrations/Yodlee/Connector.php
Yodlee API Clientretail-api/app/Integrations/Yodlee/Api.php