Skip to main content
Document Processing uses a collection-based workflow: you create a container, upload files, monitor validation and AI classification, finalize, then retrieve the same income/employment report you’d get from a live payroll connection.

Step 1: Identify or Create a User

Retrieve an existing user_id or create a new user.
If AIM Check will be used, ensure at least the last 4 digits of the SSN are included during user creation.
Find an existing user:
curl -X GET https://prod.truv.com/v1/users/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json"
Or create a new user:
curl -X POST https://prod.truv.com/v1/users/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "external_user_id": "your-internal-id",
    "first_name": "John",
    "last_name": "Doe",
    "ssn": "1234"
  }'
Save the returned id. You’ll need it in subsequent steps.

Step 2: Create a Document Collection

Initialize the collection and upload documents in a single call. Files must be Base64-encoded.
curl -X POST https://prod.truv.com/v1/documents/collections/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {
        "mime_type": "application/pdf",
        "filename": "most-recent-paystub.pdf",
        "content": "{{base64_encoded_file}}",
        "user_id": "{{user_id}}"
      },
      {
        "mime_type": "application/pdf",
        "filename": "prior-paystub.pdf",
        "content": "{{base64_encoded_file}}",
        "user_id": "{{user_id}}"
      }
    ]
  }'
The response includes a collection_id. Save this for all subsequent calls.

Step 3: Add Files Incrementally (Optional)

For save-and-resume workflows, add more files after the initial collection is created:
curl -X POST https://prod.truv.com/v1/documents/collections/{collection_id}/upload/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {
        "mime_type": "application/pdf",
        "filename": "w2-2023.pdf",
        "content": "{{base64_encoded_file}}",
        "user_id": "{{user_id}}"
      }
    ]
  }'

Step 4: Monitor Processing Status

Document processing is asynchronous. Poll the collection until all documents show status: successful.
curl -X GET https://prod.truv.com/v1/documents/collections/{collection_id}/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json"
The response has two sections: uploaded_files: File-level validations:
FieldDescription
is_validOverall validity
is_uniqueNot a duplicate of another file in the collection
is_readableFile can be opened and parsed
is_accessibleFile is not password-protected
is_viable_sizeFile is within size limits
is_supported_typeMIME type is supported
documents: AI-extracted document records with document_type, borrower name, and page range. Example response:
{
  "collection_id": "f1f63754e72a44b4805a4d16380cd833",
  "uploaded_files": [
    {
      "file_id": "9efadd7fb43c4598b02fe79bd7e31fd7",
      "filename": "most-recent-paystub.pdf",
      "validations": {
        "is_valid": true,
        "is_unique": true,
        "is_readable": true,
        "is_accessible": true,
        "is_viable_size": true,
        "is_supported_type": true
      },
      "status": "successful",
      "user_id": "c87e695081704310b15d59ee1640b1aa"
    }
  ],
  "documents": [
    {
      "document_id": "b1091a2ddc5d428c9c8af66dbc8b0556",
      "file_id": "9efadd7fb43c4598b02fe79bd7e31fd7",
      "document_type": "PAYSTUB",
      "status": "successful",
      "first_name": "John",
      "last_name": "Doe",
      "start_page": 1,
      "end_page": 1
    }
  ]
}

Step 5: Finalize the Collection

Once documents are validated, finalize to trigger report generation. Use all uploaded documents:
curl -X POST https://prod.truv.com/v1/documents/collections/{collection_id}/finalize/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "product_type": "income"
  }'
Or select specific documents:
curl -X POST https://prod.truv.com/v1/documents/collections/{collection_id}/finalize/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "document_ids": [
      "b1091a2ddc5d428c9c8af66dbc8b0556",
      "1cbb5f9bb6f345059af491917179c80b"
    ],
    "product_type": "income"
  }'
The response includes a link_id for each user:
{
  "users": [
    {
      "id": "21ae68826be042e5ab410e531dc40889",
      "links": [
        {
          "link_id": "1995e2fc5e374beb955ae81276294815",
          "status": "new",
          "documents": [
            { "id": "ad568bb5c117439e9c00df738052c653", "document_type": "PAYSTUB" },
            { "id": "769014511ed748d0a650a73759d06127", "document_type": "PAYSTUB" }
          ]
        }
      ]
    }
  ]
}
Save the link_id.

Step 6: Retrieve Verified Data

Truv processes the Link asynchronously. Wait for the Task to complete before fetching the report. Recommended: Listen for a webhook Wait for a task-status-updated webhook with status: done and the matching link_id, then fetch the report. Alternative: Poll finalization status
curl -X GET https://prod.truv.com/v1/documents/collections/{collection_id}/finalize/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json"
Fetch the report:
curl -X GET https://prod.truv.com/v1/links/{link_id}/income/report/ \
  -H "X-Access-Client-Id: YOUR_TRUV_CLIENT_ID" \
  -H "X-Access-Secret: YOUR_TRUV_CLIENT_SECRET" \
  -H "Content-Type: application/json"
The report schema is identical to a live payroll connection.

Supported document types

Document TypeDescription
PAYSTUBPay statements / pay stubs
W2W-2 wage and tax statements
1099-DIVDividends and distributions
1099-GGovernment payments
1099-INTInterest income
1099-MISCMiscellaneous income
1099-NECNonemployee compensation
1099-RRetirement distributions
SSA-1099Social Security benefit statement
1040Individual income tax return

Additional document types

Truv also recognizes these supplementary document types for classification:
DocumentType code
Bank statementsBANK_STATEMENT
Driver’s licensesDRIVER_LICENSE
PassportsPASSPORT
Green cardsGREEN_CARD
Utility billsUTILITY_BILL
Lease agreementsLEASE_AGREEMENT
Home insurance policiesINSURANCE_HOME_POLICY
Auto insurance policiesINSURANCE_AUTO_POLICY
Letters of verificationLETTER_OF_VERIFICATION
Volunteer lettersVOLUNTEER_LETTER
For sandbox testing, use the test documents — the sandbox uses file names to determine results rather than actual file contents.

API Reference

Create Collection

Initialize a document collection

Upload Files

Add files to an existing collection

Get Collection

Check validation and AI classification status

Finalize Collection

Trigger report generation

Next steps

Test Documents

Sample PDFs for sandbox testing

Income Data Guide

Interpret income and employment data from reports

Webhooks

Set up notifications for processing completion

Document Processing Demo

Upload pay stubs, W-2s, and tax returns. See structured data extraction in action.