> ## Documentation Index
> Fetch the complete documentation index at: https://docs.truv.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Document Processing

> Extract structured income data from pay stubs, W-2s, and tax returns using the Document Processing demo

Verify borrower income and employment by uploading documents directly to Truv. Send pay stubs, W-2s, 1099s, and tax returns through the [Document Collections API](/api-reference/document-collections/collections_create). Truv validates, classifies, and extracts structured data — no Bridge widget required.

<Info>
  **Integration pattern:** [Document Processing](/developers/integration/document-processing) | **Products:** Document extraction (pay stubs, W-2s, 1099s, tax returns) | **Demo:** [Document Processing](/developers/demos/mortgage/document-processing)
</Info>

***

## Get started

<Steps>
  <Step title="Run the demo">
    Clone and run the [Document Processing demo](/developers/demos/mortgage/document-processing) to upload documents, validate them, and extract structured data locally.

    ```bash theme={null}
    git clone https://github.com/truvhq/demo-apps.git
    cd demo-apps
    npm install && npm start
    ```

    Open `http://localhost:5173`, select **Mortgage > Document Processing**, and process the pre-loaded test pay stubs. You can also upload your own PDF, JPEG, or PNG files.

    See [full setup instructions](/developers/quickstarts-overview#demo-apps) for ngrok and environment configuration.
  </Step>

  <Step title="Understand the API flow">
    The demo follows this sequence:

    1. **Create a user** — Your server calls [POST /v1/users/](/api-reference/users/users_create) to create a Truv user for the borrower.
    2. **Create a document collection** — Your server sends Base64-encoded files to [POST /v1/documents/collections/](/api-reference/document-collections/collections_create) with the `user_id`. Truv validates each file (size, type, readability, uniqueness) and classifies it by document type.
    3. **Poll for validation** — Your server polls [GET /v1/documents/collections/{id}/](/api-reference/document-collections/collections_retrieve) until all files reach `successful` status.
    4. **Finalize the collection** — Your server calls [POST /v1/documents/collections/{id}/finalize/](/api-reference/document-collections/collections_finalize_create) to trigger data extraction.
    5. **Receive webhooks** — Truv sends a `task-status-updated` [webhook](/api-reference/webhooks) with `status: done` when extraction completes. The payload includes a `link_id`.
    6. **Retrieve extracted data** — Fetch the income report using the `link_id` from the webhook via [GET /v1/links/{link_id}/income/report/](/api-reference/account-link-income-and-employment-reports/link_detail_reports_income).
  </Step>

  <Step title="Review the code">
    Each step maps to a specific file in the demo. Use these as reference when building your integration.

    | Step                 | Demo file                                                                                                              | API reference                                                                                                    |
    | -------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
    | Collection creation  | [`server/routes/upload-documents.js`](https://github.com/truvhq/demo-apps/blob/main/server/routes/upload-documents.js) | [POST /v1/documents/collections/](/api-reference/document-collections/collections_create)                        |
    | Validation polling   | [`src/demos/UploadDocuments.jsx`](https://github.com/truvhq/demo-apps/blob/main/src/demos/UploadDocuments.jsx)         | [GET /v1/documents/collections/{id}/](/api-reference/document-collections/collections_retrieve)                  |
    | Finalization         | [`server/routes/upload-documents.js`](https://github.com/truvhq/demo-apps/blob/main/server/routes/upload-documents.js) | [POST /v1/documents/collections/{id}/finalize/](/api-reference/document-collections/collections_finalize_create) |
    | Webhook verification | [`server/webhooks.js`](https://github.com/truvhq/demo-apps/blob/main/server/webhooks.js)                               | [Webhooks](/api-reference/webhooks)                                                                              |
    | Report retrieval     | [`server/routes/upload-documents.js`](https://github.com/truvhq/demo-apps/blob/main/server/routes/upload-documents.js) | [Link income report](/api-reference/account-link-income-and-employment-reports/link_detail_reports_income)       |
  </Step>
</Steps>

***

## Mortgage-specific configuration

### Supported document types

| Document                    | Use case             | Fields extracted                                |
| --------------------------- | -------------------- | ----------------------------------------------- |
| Pay stubs                   | Income verification  | Employer, gross/net pay, deductions, pay period |
| W-2 forms                   | Annual income        | Wages, federal/state taxes, employer EIN        |
| 1099 forms (NEC, MISC, DIV) | Self-employed income | Non-employee compensation, payer info           |
| Tax returns (1040)          | Filed income         | AGI, tax liability, filing status               |

### Common document combinations

**Purchase / Refinance (employed borrower):**

* 2 most recent pay stubs
* Most recent W-2
* Prior year W-2 (if available)

**Self-employed borrower:**

* 1099 forms
* 1040 tax return
* Bank statements (for asset verification)

### GSE compliance

Document-extracted data supports [Fannie Mae D1C](/mortgage/d1c-aim/fannie-mae) and [Freddie Mac AIM](/mortgage/d1c-aim/freddie-mac). Every document is checked against 50M+ verified pay stubs for fraud detection. The output report uses the same schema as direct payroll connections — no changes to your LOS integration or underwriting workflow.

### Document upload via Bridge

When document upload is enabled in the [Truv Dashboard](https://dashboard.truv.com), borrowers who can't connect their payroll provider can upload documents directly within the [Truv Bridge](/developers/sdks/overview) widget. Documents uploaded through Bridge are identified by `data_source: "docs"` in the response.

### Lenient document intake

Borrowers can upload any mix of supported files — including phone photos — and Truv classifies each one and flags unreadable scans before submission. See [intelligent intake](/developers/integration/document-processing#intelligent-intake) for how recognition and selective finalization let a borrower proceed once the required documents are present.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Implementation Guide" icon="code" href="/developers/integration/document-processing">
    Complete API walkthrough for Document Collections
  </Card>

  <Card title="Document Collections API" icon="book" href="/api-reference/document-collections/collections_create">
    Full API reference for upload, validate, finalize, and retrieve
  </Card>

  <Card title="Fraud & Manual Review" icon="shield-check" href="/developers/fraud-and-manual-review">
    Handle fraud detection and document errors
  </Card>

  <Card title="GSE Testing" icon="flask" href="/developers/testing/gse-testing">
    Test with Fannie Mae and Freddie Mac report IDs
  </Card>
</CardGroup>
