Skip to main content

What is asset verification?

Asset verification is the process of confirming a borrower’s asset balances and account information to assess their ability to cover down payment, closing costs, and required reserves. Lenders must verify that borrowers have sufficient funds in their accounts to complete the mortgage transaction. Traditionally, asset verification has been a manual, time-consuming process requiring borrowers to:
  • Upload bank statements (typically 2-3 months)
  • Provide account verification letters (VOA/VOD)
  • Manually enter account balances and transaction history
  • Wait for manual document review and verification
Pylon automates this entire process using Day 1 Certainty (D1C) and Asset and Income Modeler (AIM) approved services that verify asset data automatically, reducing manual documentation and speeding up loan processing.

Why D1C/AIM asset verification matters

Day 1 Certainty (D1C) and Asset and Income Modeler (AIM) are programs from Fannie Mae and Freddie Mac that allow lenders to use automated verification sources to reduce conditions and speed up loan processing. When asset data comes from D1C/AIM approved sources, it’s considered a “verified” source, meaning no additional documentation is typically required, underwriting conditions are reduced, and loan processing is faster.

Pylon’s asset verification integrations

Pylon currently uses Plaid for D1C/AIM approved asset verification. Pylon will expand to support Truv for asset verification in the future.
  • Plaid - Account connection-based asset verification (requires borrower opt-in and your API call)
Assets only: Plaid is approved for D1C and AIM for assets only. While Plaid offers income verification products, those are not yet approved for D1C/AIM, so income items still require traditional documentation. See Income Verification for income verification options.

Plaid

Plaid is an account connection-based asset verification service that allows borrowers to connect their bank accounts to automatically verify asset balances and account information. Pylon is a reseller of Plaid and will create an account and API credentials on your behalf.

How Plaid works

1

Request initialization token from Pylon

You request an initialization token from Pylon for the borrower. Pylon provides you with a linkToken to initialize the Plaid Link component.
2

Initialize Plaid Link component

Use the linkToken provided by Pylon to initialize the Plaid Link component for that borrower in your application.
3

Borrower opts in and connects accounts

The borrower opts in and connects their bank accounts through Plaid’s secure connection flow. This allows Plaid to access account balance and transaction information.
4

Widget exchanges public token

After the borrower completes authentication, the Plaid Link widget automatically exchanges the publicToken with Pylon via the onSuccess callback (passed as a parameter to the widget). This establishes permanent access to those accounts—you don’t need to explicitly exchange the token.
5

Pylon handles data retrieval

Pylon automatically retrieves verified asset data from Plaid asynchronously. This includes account balances, account types, and institution information.
6

Pylon uses verified data

Verified asset data is automatically stored in the loan file. Pylon uses this verified data for underwriting and qualification calculations.
7

No additional documentation needed

Since the data comes from Plaid (a D1C and AIM approved source), no additional asset documentation is typically required. Pylon’s underwriting system accepts the verified data without additional documentation.

Plaid characteristics

  • Client opt-in required: Borrowers must opt in and connect their accounts through Plaid’s connection flow
  • You must call it: Request an initialization token from Pylon and initialize the Plaid Link component—it does not happen automatically
  • >95% coverage: Plaid has over 95% coverage of banks and financial institutions
  • Assets only: Plaid is approved for D1C/AIM for assets only, not income verification
  • Pylon handles data mapping: Pylon automatically maps all account types (checking, savings, etc.) to appropriate Pylon asset fields—no work required on your end

Plaid reseller program

Pylon is a reseller of Plaid, which means:
  • Credentials managed by Pylon: Pylon can obtain Plaid credentials on behalf of clients
  • Billing through Pylon: Plaid usage is billed through Pylon’s main account
  • Simplified setup: Clients don’t need to manage their own Plaid account or credentials
Simplified integration: As a Plaid reseller, Pylon handles credential management and billing, making it easier for clients to integrate Plaid without managing separate accounts.

Integration options

Pylon clients integrate Plaid using Plaid Link, Plaid’s standard web-based authentication component. Plaid Link is a pre-built UI component that handles the entire bank connection flow, allowing borrowers to securely connect their bank accounts through a modal interface. How Plaid Link works:
  • Borrower clicks a button in your application
  • Plaid Link modal opens
  • Borrower selects their bank and authenticates
  • Asset report is generated and sent to Pylon
Seamless experience: Plaid Link provides a seamless borrower experience and is the standard integration method for Plaid asset verification. For complete implementation details, see the Plaid Link documentation.

Checking asset verification status

After asset verification is initiated (after borrower opt-in for Plaid), check the amount field on Asset entities to see if verification was successful. When assets are verified through Plaid, the amount field will be populated with verified account balances, and Pylon will use this verified data for underwriting without requiring additional documentation. For complete details on querying asset data, understanding asset types, and all asset fields, see the Assets entity guide.

GraphQL query example

Poll Pylon’s GraphQL API to check for verified asset values. The amount field will be populated when assets have been successfully verified through Plaid:
query GetVerifiedAssets($loanId: ID!) {
  loan(id: $loanId) {
    borrowers(first: 10) {
      edges {
        node {
          id
          firstName
          lastName
          assets {
            id
            amount
            assetType
            ... on FinancialAccountAsset {
              institutionName
              accountIdentifier
              accountType
            }
            ... on CheckingAccountAsset {
              accountIdentifier
              institutionName
            }
            ... on SavingsAccountAsset {
              accountIdentifier
              institutionName
            }
          }
        }
      }
    }
  }
}
Key fields:
  • amount: The verified account balance. null if not yet verified, or a number if verified through Plaid
  • assetType: The type of asset (e.g., CHECKING_ACCOUNT, SAVINGS_ACCOUNT, RETIREMENT_ACCOUNT)
  • institutionName: The name of the financial institution (for financial account assets)
  • accountIdentifier: The account identifier or account number (for financial account assets)
Verification status:
  • amount === null: Asset has not been verified yet, or verification is not available
  • amount > 0: Asset has been successfully verified through D1C/AIM approved sources

Node.js/TypeScript polling example

Here’s a complete example of polling for verified asset values using Node.js and TypeScript:
import { GraphQLClient } from 'graphql-request';

const GET_VERIFIED_ASSETS = `
  query GetVerifiedAssets($loanId: ID!) {
    loan(id: $loanId) {
      borrowers(first: 10) {
        edges {
          node {
            id
            firstName
            lastName
            assets {
              id
              amount
              assetType
              ... on FinancialAccountAsset {
                institutionName
                accountIdentifier
                accountType
              }
              ... on CheckingAccountAsset {
                accountIdentifier
                institutionName
              }
              ... on SavingsAccountAsset {
                accountIdentifier
                institutionName
              }
            }
          }
        }
      }
    }
  }
`;

interface FinancialAccountAsset {
  id: string;
  amount: number | null;
  assetType: string;
  institutionName?: string;
  accountIdentifier?: string;
  accountType?: string;
}

interface BorrowerNode {
  id: string;
  firstName: string;
  lastName: string;
  assets: FinancialAccountAsset[];
}

interface LoanData {
  loan: {
    borrowers: {
      edges: Array<{
        node: BorrowerNode;
      }>;
    };
  };
}

/**
 * Polls for verified asset values for a given loan
 * @param client - GraphQL client configured with your Pylon API endpoint and auth
 * @param loanId - The ID of the loan to check
 * @param maxAttempts - Maximum number of polling attempts (default: 30)
 * @param intervalMs - Polling interval in milliseconds (default: 2000)
 * @returns Promise resolving to verified assets or null if verification not available
 */
async function pollForVerifiedAssets(
  client: GraphQLClient,
  loanId: string,
  maxAttempts: number = 30,
  intervalMs: number = 2000
): Promise<FinancialAccountAsset[] | null> {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const data = await client.request<LoanData>(GET_VERIFIED_ASSETS, {
      loanId,
    });

    const allAssets: FinancialAccountAsset[] = [];
    
    // Collect all assets from all borrowers
    for (const borrowerEdge of data.loan.borrowers.edges) {
      const borrower = borrowerEdge.node;
      
      for (const asset of borrower.assets) {
        allAssets.push(asset);
        
        // Check if this asset has been verified
        if (asset.amount !== null && asset.amount > 0) {
          console.log(
            `✓ Asset verified for ${borrower.firstName} ${borrower.lastName}: ` +
            `$${asset.amount} (${asset.assetType}) at ${asset.institutionName || 'Unknown Institution'}`
          );
        }
      }
    }

    // Check if any assets have been verified
    const verifiedAssets = allAssets.filter(
      (asset) => asset.amount !== null && asset.amount > 0
    );

    if (verifiedAssets.length > 0) {
      return verifiedAssets;
    }

    // If no verified assets yet, wait before next attempt
    if (attempt < maxAttempts - 1) {
      console.log(
        `No verified assets yet (attempt ${attempt + 1}/${maxAttempts}). ` +
        `Polling again in ${intervalMs}ms...`
      );
      await new Promise((resolve) => setTimeout(resolve, intervalMs));
    }
  }

  console.log('Asset verification not available after maximum attempts');
  return null;
}

// Example usage
const client = new GraphQLClient('https://api.pylon.mortgage/graphql', {
  headers: {
    Authorization: `Bearer ${process.env.PYLON_API_KEY}`,
  },
});

// Poll for verified assets
pollForVerifiedAssets(client, 'loan-123')
  .then((verifiedAssets) => {
    if (verifiedAssets) {
      console.log(`Found ${verifiedAssets.length} verified asset(s)`);
      // Use verified asset data for your application logic
    } else {
      console.log('Asset verification not available - fallback to traditional methods');
      // Fallback to requesting bank statements, VOA/VOD, etc.
    }
  })
  .catch((error) => {
    console.error('Error polling for verified assets:', error);
  });
Key implementation details:
  • Polling strategy: The function polls at regular intervals (default: every 2 seconds) until verified assets are found or max attempts are reached
  • Verification check: Checks if amount is not null and greater than 0
  • Error handling: Includes error handling and fallback logic for when verification isn’t available
  • Multiple borrowers: Handles loans with multiple borrowers and collects all assets
  • Asset types: Handles different asset types (checking, savings, retirement accounts, etc.)

Benefits

For borrowers

  • No document upload: No need to upload bank statements when verification is successful
  • Real-time data: Asset data is current and accurate
  • Faster processing: Automated verification is faster than manual document review
  • Better experience: Seamless connection process vs. manual document collection

For lenders

  • Reduced conditions: Pylon’s underwriting system generates fewer conditions when assets are verified through D1C/AIM sources
  • Fewer borrower tasks: Pylon creates fewer tasks for borrowers when verification is successful
  • Faster closes: Pylon’s automated processing accelerates loan processing and reduces time to close
  • Better accuracy: Verified data from Plaid is more accurate than manual entry or document review
  • Cost savings: Reduced manual processing and document review costs

Limitations and fallbacks

When automated verification doesn’t work

Asset verification through Plaid may not be available if:
  • Plaid opt-in not completed: The borrower didn’t opt in to Plaid or didn’t complete the account connection process
  • Bank not covered: The borrower’s bank doesn’t participate in Plaid
  • Account type not supported: Some account types may not be supported by Plaid
  • Connection issues: Technical issues preventing successful account connection

Fallback to traditional methods

When automatic verification isn’t available, Pylon will request traditional asset verification documentation from borrowers:
  • Bank statements: Recent bank statements (typically 2-3 months)
  • Account verification letters: VOA (Verification of Assets) or VOD (Verification of Deposit) letters from banks
  • Account statements: Investment account statements, retirement account statements, etc.
  • Gift letters: For gift funds, gift letters and transfer documentation
Always have a fallback: Don’t assume all borrowers will have assets verified through Plaid. Plaid requires borrower opt-in, and some banks may not be covered. Always be prepared to use traditional verification methods when automated verification isn’t available.

Best practices

Monitoring verification status

  • Poll regularly: Check asset verification status as part of your loan status polling workflow
  • For Plaid: Request initialization tokens from Pylon and initialize the Plaid Link component for borrowers who opt in
  • Handle failures gracefully: If verification fails or isn’t available, immediately switch to traditional verification methods

Using verified data

  • Combine with other verifications: Use Plaid alongside other D1C/AIM approved sources (like Truv or The Work Number for income verification) for maximum benefit
  • Pylon updates qualification automatically: Once assets are verified, Pylon automatically recalculates qualification and eligibility, as verified assets may affect loan terms and reserve requirements