What is income verification?
Income verification is the process of confirming a borrower’s income and employment status to assess their ability to repay a mortgage loan. Lenders must verify that borrowers have sufficient, stable income to make monthly mortgage payments. Traditionally, income verification has been a manual, time-consuming process requiring borrowers to:- Upload pay stubs
- Provide employment letters
- Log into employer HRIS systems
- Submit tax returns and W-2s
- Manually enter income information
Why D1C/AIM income verification matters
Day 1 Certainty (D1C) and Automated Income Model (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 income 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 income verification integrations
Pylon has integrations with two D1C/AIM approved income verification vendors:- Truv - Account connection-based income verification (requires borrower opt-in and your API call)
- The Work Number (TWN) - SSN-based income verification (fully automatic)
Truv
Truv is an account connection-based income verification service that allows borrowers to connect their payroll or bank accounts to automatically verify income and employment data. Pylon is a reseller of Truv and will create an account and API credentials on your behalf. Truv is driven entirely through Pylon’s GraphQL API, and Pylon supports two integration paths depending on who drives the borrower’s connection:- Embedded widget — the borrower connects their payroll account in-flow, inside your application, using the Truv Bridge widget.
- Hosted link — an LO or processor requests a link on the borrower’s behalf and sends it to them (email, text, your own portal). The borrower completes the connection later, out-of-flow, on Truv’s own hosted page. No widget embed required.
Choosing an integration path
Option 1: Embedded widget (borrower connects in-flow)
Truv flow at a glance
borrowerId you pass must belong to a loan your credentials can access.How the embedded widget works
Request a bridge token from Pylon
createInitializationToken mutation (under the verify namespace) with vendor: TRUV and the borrower’s ID. Pylon returns a bridgeToken used to initialize the Truv Bridge widget.The mutation returns a CreateInitializationTokenResponse union, so select the TruvBridgeToken member with an inline fragment:CreateInitializationTokenInput fields:vendor(VendorName!):TRUV(theVendorNameenum isTRUVorPLAID)borrowerId(ID!): the borrower being verifiedtemplateId,clientUserId(String): not used for Truv; omit
Initialize the Truv Bridge widget
bridgeToken to the Truv Bridge widget in your frontend. Truv Bridge is a pre-built UI component that handles employer/payroll lookup and the borrower’s secure login.Borrower opts in and connects accounts
Exchange the public token with Pylon
onSuccess callback hands your frontend a public token and metadata containing a Truv task_id. Pass both back to Pylon via the exchangePublicToken mutation to finalize the connection.ExchangePublicTokenInput fields:vendor(VendorName!):TRUVpublicToken(String!): the public token from the BridgeonSuccesscallbackborrowerId(ID!): the same borrower from step 1truvMetadata(TruvExchangeMetadata), required whenvendorisTRUV:taskId(String!): the Truv task ID from theonSuccessmetadataemployerName(String): optional employer name
plaidMetadata: not used for Truv; omit
ExchangePublicTokenResponse union; the TruvLinkAccess member returns linkId (the Truv task ID Pylon now tracks).Pylon retrieves and maps the data
Read the verified data
verifiedAmount field, with a voieReportId referencing the source report. Poll the GraphQL API to detect completion (see Checking income verification status). Since the data comes from Truv (a D1C and AIM approved source), no additional income documentation is typically required.End-to-end example (Node.js/TypeScript)
This example shows the two server-side calls that bookend the Truv Bridge widget: requesting the bridge token, and exchanging the public token your frontend receives from theonSuccess callback.
Embedded widget characteristics
- Client opt-in required: Borrowers must opt in and connect their accounts through Truv’s connection flow
- You must drive it: The flow runs through the
verifymutations and the Truv Bridge widget; it does not happen automatically - Asynchronous completion: Verification data is retrieved by Pylon in the background after the exchange; poll
verifiedAmountto detect when it’s ready - >95% coverage: Truv has over 95% coverage of employers and payroll providers
- Lower production costs: Cheaper production costs compared to The Work Number
- Pylon handles data mapping: Pylon automatically maps all income types (variable, commission, bonus, salary, etc.) to appropriate Pylon fields; no work required on your end
Option 2: Hosted link (LO or processor sends the borrower a link)
Instead of embedding a widget in your own frontend, you can ask Pylon to create a hosted verification link and send it to the borrower yourself—by email, text, or through your own portal. The borrower opens the link later and completes the connection on Truv’s hosted page, entirely outside your application. There is no widget to embed and noonSuccess callback to wire up.
requestOrder—the embedded widget flow is unaffected either way. Ask your account manager to turn it on.update:loan scope (the embedded widget’s verify mutations require update:borrower).
Hosted link flow at a glance
How the hosted link works
Request an order from Pylon
requestOrder mutation under the incomeVerification namespace with the borrower’s ID. Pylon creates the order with Truv and returns a shareUrl—the borrower-facing hosted link—along with the order’s status and expiresAt.RequestOrderInput fields:borrowerId(ID!): the borrower being verified
RequestOrderResponse fields:orderId(String!): Pylon’s ID for this order; pass it tocancelOrderstatus(IncomeVerificationOrderStatus!):PENDING,COMPLETED,CANCELED, orFAILED—a freshly created order is alwaysPENDINGexpiresAt(DateTime!): when the link stops being usableshareUrl(String): the hosted link to send the borrower;nullif the order has no usable linkexistingOrderReused(Boolean!):trueif the borrower already had a live, unexpired order and Pylon returned it instead of creating a duplicate
existingOrderReused: true) rather than creating a second link. You don’t need to track order state yourself to avoid duplicates.Send the link to the borrower
shareUrl to the borrower through whatever channel your application uses—email, SMS, an in-app notification, or your own borrower portal. Pylon does not deliver the link on your behalf.Borrower connects on Truv's hosted page
expiresAt, selects their employer or payroll provider, and authenticates through Truv’s own hosted flow—no widget embed, and no active session in your application required.Pylon retrieves and maps the data
Read the verified data
verifiedAmount field, with a voieReportId referencing the source report. Poll the GraphQL API to detect completion (see Checking income verification status).Checking and canceling orders
UseincomeVerification.orders to list a borrower’s recent orders—for example, to show an LO whether a link is still live before deciding to send a new one:
shareUrl is only populated while an order is PENDING and unexpired—expired, completed, canceled, or failed orders return null.
To cancel a still-pending order (for example, if it was sent to the wrong borrower or is no longer needed), call cancelOrder:
Hosted link characteristics
- No widget required: Two GraphQL calls—no Truv Bridge SDK, no
onSuccesscallback to wire up - Out-of-flow: The borrower can complete verification later, from an email or text, entirely outside your application session
- You initiate it: An LO, processor, or your API caller explicitly requests the order—it does not happen automatically for every borrower
- You own delivery: Pylon returns
shareUrl; sending it to the borrower is your responsibility - Single live link per borrower: Requesting again while a link is pending and unexpired returns the existing order instead of creating a duplicate
- Cancelable: Cancel a still-pending order, with the caveat that a borrower who finishes mid-cancellation settles as
COMPLETED - Off by default: Ask your account manager to enable this capability for your organization before using it
- Same downstream pipeline: Once the borrower connects, data retrieval, income mapping, and rep/warrant tracking work identically to the embedded widget path
The Work Number (TWN)
The Work Number (TWN) is a comprehensive employment and income verification service that maintains a database of verified employment and payroll data from thousands of employers and payroll providers across the United States.How The Work Number works
Credit pull collects SSN
Pylon automatically triggers verification
Pylon queries The Work Number
Pylon uses verified data
No additional documentation needed
The Work Number characteristics
- SSN-based: Only requires the borrower’s Social Security Number (collected during credit pull)
- Fully automatic: Pylon automatically triggers verification-no borrower opt-in, no flow to initialize, and no API calls required from you
- Higher production costs: Much higher production costs compared to Truv (in the range of 5x)
- Charged on re-pull: Costs are incurred on each verification pull, including re-pulls
Programmatic configuration and cost considerations
Reach out to your account manager to discuss programmatic configuration of The Work Number. Because The Work Number is charged on each verification pull (including re-pulls), and Pylon covers the cost of unfunded loans in the closed per loan fee, high application-to-funded loan ratios can significantly impact your per-funded-loan underwriting fee. Key considerations:- Application-to-funded ratio: If you have a high dropout rate (many applications that don’t result in funded loans), the cost of The Work Number verifications per funded loan increases substantially
- Per-funded-loan impact: Since Pylon covers unfunded loan costs in the closed per loan fee, using The Work Number when you have a low application-to-funded ratio may require adjusting your per-funded-loan underwriting fee
- Vendor waterfall strategy: Consider implementing a vendor waterfall that prioritizes lower-cost options (like Truv) before falling back to The Work Number, especially if your application-to-funded ratio is low
- Configure when The Work Number should be triggered programmatically
- Understand the cost implications based on your application-to-funded ratio
- Implement vendor waterfall strategies to optimize costs
- Adjust pricing structures if needed
Checking income verification status
After income verification is initiated (automatically for The Work Number, or after borrower opt-in for Truv), check theverifiedAmount field on the Income entity to see if verification was successful. When verifiedAmount has a value, income has been verified through Truv or The Work Number, and Pylon will use this verified data for underwriting without requiring additional documentation.
For complete details on querying income data, understanding income states (stated, qualified, verified), and all income fields, see the Incomes entity guide.
GraphQL query example
Poll Pylon’s GraphQL API to check for verified income values. TheverifiedAmount field will be populated when income has been successfully verified through Truv or The Work Number:
verifiedAmount: The verified monthly income amount.nullif not yet verified, or a number if verified through Truv or The Work NumbervoieReportId: The ID of the source verification of income and employment (VOIE) report. Populated alongsideverifiedAmountwhen income is verified through TruvstatedMonthlyAmount: The borrower’s stated monthly income amount__typename: The concrete income kind (e.g.,StandardEmploymentIncome), used to select the matching inline fragment
verifiedAmount === null: Income has not been verified yet, or verification is not availableverifiedAmount > 0: Income has been successfully verified through D1C/AIM approved sources
Node.js/TypeScript polling example
Here’s a complete example of polling for verified income values using Node.js and TypeScript:- Polling strategy: The function polls at regular intervals (default: every 2 seconds) until verified incomes are found or max attempts are reached
- Verification check: Checks if
verifiedAmountis 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 incomes
- Pagination: The example shows pagination structure, though you may need to implement cursor-based pagination for loans with many incomes
Benefits
For borrowers
- No document upload: No need to upload pay stubs, employment letters, or tax documents when verification is successful
- No HRIS login: Borrowers don’t need to log into their employer’s HRIS system or payroll portal
- Faster processing: Automated verification is faster than manual document review
For lenders
- Reduced conditions: Pylon’s underwriting system generates fewer conditions when income is 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 Truv or The Work Number is more accurate than manual entry or document review
- Cost savings: Reduced manual processing and document review costs (with Truv offering lower production costs)
Limitations and fallbacks
When automated verification doesn’t work
Income verification through Truv or The Work Number may not be available if:- Truv opt-in not completed: The borrower didn’t opt in to Truv or didn’t complete the account connection process
- Employer not covered: The borrower’s employer doesn’t participate in The Work Number
- Self-employed borrowers: Both Truv and The Work Number are primarily for W-2 employees. Self-employed borrowers require different verification methods (tax returns, profit & loss statements, etc.)
- Recent employment changes: If a borrower recently changed employers, verification services may not have the latest information yet
- Contractor or gig workers: Non-traditional employment arrangements may not be covered
Fallback to traditional methods
When automatic verification isn’t available, Pylon will request traditional income verification documentation from borrowers:- Pay stubs: Recent pay stubs (typically 2-3 months)
- Employment letters: Employment verification letters from employers
- Tax returns: For self-employed borrowers, tax returns and profit & loss statements
- W-2s and 1099s: Tax documents for income verification
- Bank statements: Bank statements to verify income deposits
Best practices
Monitoring verification status
- Poll regularly: Check income verification status as part of your loan status polling workflow
- For Truv (embedded widget): Drive the flow through the
verifyGraphQL mutations:createInitializationTokento get a bridge token, thenexchangePublicTokenafter the borrower completes Truv Bridge. Verification data is then retrieved asynchronously by Pylon - For Truv (hosted link): Call
incomeVerification.requestOrderand send the returnedshareUrlto the borrower yourself; pollincomeVerification.ordersif you need to check whether a link is still live before sending a new one - For The Work Number: No action required-verification happens automatically once SSN is available
- Handle failures gracefully: If verification fails or isn’t available, immediately switch to traditional verification methods
Using verified data
- Combine with other verifications: Use Truv or The Work Number alongside other D1C/AIM approved sources (like Plaid for assets) for maximum benefit
- Pylon updates pricing automatically: Once income is verified, Pylon automatically recalculates pricing and eligibility, as verified income may affect loan terms
Related resources
- Incomes - Complete guide to the Income entity, including all income types, states (stated, qualified, verified), and fields
- Day 1 Certainty & AIM Overview - Learn about D1C and AIM programs and their benefits
- Asset Verification - Learn about Plaid for automatic asset verification
- Credit Pulls - Understand credit pull requirements (SSN is collected here for income verification)
- Order-Outs Overview - Understand when order-outs and verifications are triggered