Skip to main content
Test Income & Employment (VOIE) and Employment History (VOE) flows in sandbox using the credentials below. VOIE and VOE share the same payroll credentials — only the product_type value on the bridge token or order differs (income for VOIE, employment for VOE). In Truv Bridge, search for the Truv Payroll Provider to use any of these credentials.
For additional login fields, use Phone: (111)111-1111 and Email: goodlogin@domain.com.

Quick start

Use goodlogin / goodpassword for the happy path. A successful login returns a complete VOIE report with bi-weekly paystubs, an annual income summary, W-2s, and bank account allocations.
CredentialProviderSample report
goodlogin / goodpasswordTruv Payroll ProviderBi-weekly VOIE PDF
For the underlying JSON shape, see the User Income and Employment Report object. Sample response — captured from a live sandbox order. Expand a credential to see the response it returns.
The complete report a successful payroll connection returns: employment metadata, an annual income summary, per-pay-period statements (one shown; the rest follow the same shape), W-2s, and bank account allocations. Captured from a live sandbox order. Pay-period, earnings, and deduction arrays are truncated here for length.
{
  "report_id": "c219d26c1fc7412fb1d0df36a9652600",
  "created_at": "2026-06-18T01:43:32.553366Z",
  "completed_at": "2026-06-18T01:43:32.132883Z",
  "last_task_at": "2026-06-18T01:43:21.714235Z",
  "links": [
    {
      "id": "ac978e05483e48379a5ec82b556d20a0",
      "link_id": "f5ef8b9e1eda4640b38069c9e851bc3a",
      "tracking_info": "8f50b58e35644bb5bff989341eafcdb5",
      "data_source": "payroll",
      "provider": "truv",
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "id": "e803dc34b8184c4a8ada449b42fccc65",
          "job_title": "PR associate",
          "job_type": "F",
          "start_date": "2023-01-01",
          "end_date": null,
          "external_last_updated": "2026-06-08",
          "is_active": true,
          "manager_name": "Jenny McDouglas",
          "company": {
            "name": "Acme",
            "address": {
              "zip": "98765",
              "city": "Anytown",
              "state": "CA",
              "street": "123 Main Street",
              "country": "US"
            },
            "phone": "5555551234",
            "ein": null
          },
          "profile": {
            "id": "e776ba2b32bf4e32aece51c5878d3cdd",
            "created_at": "2026-06-18T01:43:24.784615Z",
            "updated_at": "2026-06-18T01:43:24.784625Z",
            "first_name": "John",
            "last_name": "Doe",
            "full_name": "John Doe",
            "middle_initials": null,
            "email": "john.doe@gmail.com",
            "ssn": "991919991",
            "date_of_birth": "1992-03-03",
            "home_address": {
              "zip": "94062",
              "city": "Redwood City",
              "state": "CA",
              "street": "35 Dry Ridge Rd",
              "country": "US"
            }
          },
          "original_hire_date": "2012-02-01",
          "derived_fields": [],
          "missing_data_fields": [],
          "income": "56269.25",
          "income_unit": "YEARLY",
          "pay_rate": "2153.60",
          "pay_frequency": "BW",
          "statements": [
            {
              "id": "3a5d6a193fc7491689bc62317f4b046f",
              "pay_date": "2026-06-08",
              "net_pay": "1629.98",
              "net_pay_ytd": "19559.76",
              "gross_pay": "2157.89",
              "gross_pay_ytd": "25894.68",
              "bonus": null,
              "commission": null,
              "hours": "80.00",
              "basis_of_pay": "S",
              "period_start": "2026-05-26",
              "period_end": "2026-06-08",
              "regular": "1935.77",
              "regular_ytd": "23229.24",
              "bonus_ytd": null,
              "commission_ytd": null,
              "overtime": "222.12",
              "overtime_ytd": "2665.44",
              "other_pay": null,
              "other_pay_ytd": null,
              "earnings": [
                {
                  "name": "Regular",
                  "category": "regular",
                  "amount": "1935.77",
                  "rate": "26.92",
                  "units": "71.90"
                },
                {
                  "name": "Double Time",
                  "category": "overtime",
                  "amount": "161.54",
                  "rate": "53.84",
                  "units": "3.00"
                },
                "...and 1 more earnings lines (omitted for brevity)"
              ],
              "earnings_ytd": [
                {
                  "name": "Regular",
                  "category": "regular",
                  "amount": "23229.24",
                  "rate": "26.92",
                  "units": "862.80"
                },
                {
                  "name": "Double Time",
                  "category": "overtime",
                  "amount": "1938.48",
                  "rate": "53.84",
                  "units": "36.00"
                },
                "...and 1 more earnings ytd lines (omitted for brevity)"
              ],
              "deductions": [
                {
                  "name": "Federal Income Tax",
                  "amount": "153.63",
                  "category": "federal"
                },
                {
                  "name": "Social Security Tax",
                  "amount": "133.89",
                  "category": "socialsec"
                },
                "...and 4 more deductions lines (omitted for brevity)"
              ],
              "deductions_ytd": [
                {
                  "name": "Federal Income Tax",
                  "amount": "1843.56",
                  "category": "federal"
                },
                {
                  "name": "Social Security Tax",
                  "amount": "1606.68",
                  "category": "socialsec"
                },
                {
                  "name": "401K Dollars",
                  "amount": "1553.64",
                  "category": "retirement"
                },
                {
                  "name": "CA State Income Tax",
                  "amount": "631.44",
                  "category": "state"
                },
                {
                  "name": "Medicare Tax",
                  "amount": "375.72",
                  "category": "medicare"
                },
                {
                  "name": "Blue Ash Income Tax",
                  "amount": "323.88",
                  "category": "local"
                }
              ],
              "md5sum": "a9b85d17e3583203a854f85a29f78ed5",
              "file": "https://citadelid-files.s3.amazonaws.com/sandbox/statements/1194546.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZWHJR5UGKNMOUOTK%2F20260618%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260618T014334Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=6a0374095c4875ba336efeb045805aa914bd502654874de7b125cc127167f2b1",
              "derived_fields": [],
              "missing_data_fields": [],
              "check_number": null
            },
            "...and 53 more pay statements (omitted for brevity)"
          ],
          "annual_income_summary": [
            {
              "id": "3a5d6a193fc7491689bc62317f4b046f",
              "year": 2026,
              "regular": "23229.24",
              "bonus": null,
              "commission": null,
              "overtime": "2665.44",
              "other_pay": null,
              "net_pay": "19559.76",
              "gross_pay": "25894.68"
            },
            {
              "id": "1385cc45e75c474485c10124e306de8b",
              "year": 2025,
              "regular": "50330.02",
              "bonus": null,
              "commission": null,
              "overtime": "5775.12",
              "other_pay": null,
              "net_pay": "42379.48",
              "gross_pay": "56105.14"
            },
            {
              "id": "2556ebea9d454ea18ddaf85a4143a692",
              "year": 2024,
              "regular": "50330.02",
              "bonus": null,
              "commission": null,
              "overtime": "5775.12",
              "other_pay": null,
              "net_pay": "42379.48",
              "gross_pay": "56105.14"
            }
          ],
          "bank_accounts": [
            {
              "account_number": "11114623",
              "routing_number": "101014378",
              "account_name": null,
              "account_type": "C",
              "deposit_type": "A",
              "deposit_value": "1604.98",
              "bank_name": "Sandbox Bank"
            },
            {
              "account_number": "11111308",
              "routing_number": "101013399",
              "account_name": null,
              "account_type": "C",
              "deposit_type": "A",
              "deposit_value": "25.00",
              "bank_name": "Sandbox Bank"
            }
          ],
          "w2s": [
            {
              "file": "https://citadelid-files.s3.amazonaws.com/sandbox/w2s/2560.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZWHJR5UGKNMOUOTK%2F20260618%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260618T014334Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=7bcd1e3f77c7f8a105a702f5c5745ddfb0dc02bb08cac464f8cc4a341a68a63a",
              "md5sum": "385320b9c0f851260e86472707a5de18",
              "year": 2023,
              "wages": "56105.14",
              "federal_tax": "3994.38",
              "social_security_wages": "56105.14",
              "social_security_tax": "3481.14",
              "medicare_wages": "56105.14",
              "medicare_tax": "814.06",
              "gross_pay": null
            },
            "...and 2 more W-2s (omitted for brevity)"
          ],
          "gse_accepted": true,
          "last_period_end": "2026-06-08",
          "last_pay_date": "2026-06-08"
        }
      ]
    }
  ]
}

Credential scenarios

Every credential here connects through the Truv Payroll Provider and returns the same report shape as Quick start — the Sample responses panels show only the fields that differ. The VOIE-* scenario ID is a stable test-case identifier you can cite in tickets.
Every scenario below uses the password goodpassword — only the username changes. The error scenarios are the exception: there the password field carries the trigger.

Pay frequency

All four scenarios return SSN 991-91-9991; only the pay cadence differs.
ScenarioUsernamepay_frequencySample report
VOIE-PF1goodloginBW (bi-weekly)PDF
VOIE-PF2goodlogin.weeklyW (weekly)PDF
VOIE-PF3goodlogin.semimonthlySM (semi-monthly)PDF
VOIE-PF4goodlogin.monthlyM (monthly)PDF
Use these to validate your handling of pay_frequency (W, BW, SM, M) and to confirm your annualization logic across cadences.
Same report shape as the quick-start response above; pay_frequency is W and statements arrive weekly.
{
  "links": [
    {
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "company": "Acme",
          "job_title": "PR associate",
          "job_type": "F",
          "is_active": true,
          "start_date": "2023-01-01",
          "end_date": null,
          "pay_frequency": "W",
          "income": "56104.88",
          "income_unit": "YEARLY",
          "pay_rate": "1078.94",
          "statement_count": 108,
          "w2_count": 3,
          "missing_data_fields": [],
          "latest_statement": {
            "pay_date": "2026-06-15",
            "period_start": "2026-06-09",
            "period_end": "2026-06-15",
            "hours": "38.20",
            "gross_pay": "1078.94",
            "net_pay": "815.00",
            "gross_pay_ytd": "25894.56",
            "net_pay_ytd": "19560.00"
          }
        }
      ]
    }
  ]
}

Employment type

ScenarioUsernameSSNWhat it returns
VOIE-E1fulltime2211Full-time salesperson with regular salaried paystubs
VOIE-E2hourly.part-time666382548Hourly part-time worker with variable hours per stub
VOIE-E3partial.data2222Payroll connection succeeds but returns sparse employment metadata — job_title, job_type, and original_hire_date come back null. Use to validate your handling of null fields on the employment object.
VOIE-E4goodlogin.min-data991-91-9991Minimal information returned (no W-2s, sparse statements)
VOIE-E5multiple.employmentsMultiple different employers attached to one applicant
VOIE-E6multiple.employments27740Multiple same-employer positions (e.g. transferred roles)
VOIE-E7nonactive1890Employment with an end_date set and is_active: false
Salaried full-time employee with regular paystubs.
{
  "links": [
    {
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "company": "Real Estate Business",
          "job_title": "Sales Associate",
          "job_type": "F",
          "is_active": true,
          "start_date": "2023-03-12",
          "end_date": null,
          "pay_frequency": "SM",
          "income": "88663.20",
          "income_unit": "YEARLY",
          "pay_rate": "2812.50",
          "statement_count": 50,
          "w2_count": 3,
          "missing_data_fields": [],
          "latest_statement": {
            "pay_date": "2026-06-15",
            "period_start": "2026-06-01",
            "period_end": "2026-06-15",
            "hours": "86.67",
            "gross_pay": "3694.30",
            "net_pay": "3166.39",
            "gross_pay_ytd": "40637.30",
            "net_pay_ytd": "34830.29"
          }
        }
      ]
    }
  ]
}

Tenure

Use these credentials when your decisioning depends on the borrower’s tenure with their current employer — for example, PLL eligibility rules that require a minimum employment length, or income-stability decisioning that looks at months at current employer.
ScenarioUsernameReturns
VOIE-T1goodlogin.tn1Active employment with less than 12 months tenure at the current employer
VOIE-T2goodlogin.tn2Active employment with less than 12 months tenure at the current employer (alternate profile for multi-applicant test sets)
Both credentials produce the same response shape as goodlogin / goodpassword — the only difference is that start_date is set to a date inside the last 12 months. Use one or the other (or both) when your QA matrix has multiple sub-12-month scenarios that need distinct credentials.
start_date falls inside the last 12 months. Use to confirm tenure-based eligibility logic.
{
  "links": [
    {
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "company": "Acme",
          "job_title": "PR associate",
          "job_type": null,
          "is_active": true,
          "start_date": "2026-02-02",
          "end_date": null,
          "pay_frequency": "SM",
          "income": "51789.36",
          "income_unit": "YEARLY",
          "pay_rate": "2157.89",
          "statement_count": 9,
          "w2_count": 0,
          "missing_data_fields": [],
          "latest_statement": {
            "pay_date": "2026-06-15",
            "period_start": "2026-06-01",
            "period_end": "2026-06-15",
            "hours": "76.40",
            "gross_pay": "2157.89",
            "net_pay": "1629.98",
            "gross_pay_ytd": "19421.01",
            "net_pay_ytd": "14669.82"
          }
        }
      ]
    }
  ]
}

Benefits and special cases

Both scenarios return SSN 9988.
ScenarioUsernameWhat it returns
VOIE-B1militaryMilitary MyPay data via the DFAS myPay provider
VOIE-B2unemploymentWeekly unemployment benefits
Retirement, disability, and Veterans benefits: Search for the benefit type in Truv Bridge (for example, “SSA” for Social Security or “VA Benefits”), pick a login method, and use goodlogin / goodpassword. Retirement and disability return a Social Security Administration Benefits Verification Letter. Veterans Benefits return a VA Benefit Summary Letter via the Veterans Affairs provider, or a retirement paystub via the DFAS myPay provider.
Military service member pay record.
{
  "links": [
    {
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "company": "United States Air Force",
          "job_title": "AF O4",
          "job_type": "F",
          "is_active": true,
          "start_date": "2023-03-16",
          "end_date": null,
          "pay_frequency": "M",
          "income": "141015.71",
          "income_unit": "YEARLY",
          "pay_rate": "7192.20",
          "statement_count": 26,
          "w2_count": 3,
          "missing_data_fields": [],
          "latest_statement": {
            "pay_date": "2026-05-31",
            "period_start": "2026-05-01",
            "period_end": "2026-05-31",
            "hours": null,
            "gross_pay": "16332.67",
            "net_pay": "16332.67",
            "gross_pay_ytd": "81663.35",
            "net_pay_ytd": "81663.35"
          }
        }
      ]
    }
  ]
}

Gig and shift workers

ScenarioUsernameWhat it returns
VOIE-G1goodlogin.shiftGig worker with earned wage access — use for testing gig-payroll VOIE flows where hours and earnings cadence differ from W-2 payroll
Gig provider connections return different field coverage than W-2 payroll connections. DoorDash returns gross pay and hours but no net pay or deductions; Uber returns gross and net pay but no hours. Validate your decisioning logic against partial-coverage responses, not against the assumption that every field will be populated.
Gig worker with earned wage access; field coverage differs from W-2 payroll.
{
  "links": [
    {
      "provider_name": "Truv payroll provider",
      "employments": [
        {
          "company": "DoorDash",
          "job_title": "Gig Worker",
          "job_type": null,
          "is_active": true,
          "start_date": "2026-04-06",
          "end_date": null,
          "pay_frequency": "W",
          "income": null,
          "income_unit": null,
          "pay_rate": null,
          "statement_count": 8,
          "w2_count": 0,
          "missing_data_fields": [],
          "latest_statement": {
            "pay_date": "2026-05-24",
            "period_start": "2026-05-17",
            "period_end": "2026-05-23",
            "hours": "31.00",
            "gross_pay": "618.50",
            "net_pay": null,
            "gross_pay_ytd": null,
            "net_pay_ytd": null
          }
        }
      ]
    }
  ]
}

Error scenarios

VOIE shares the universal authentication-error credentials. Use these to test your error handling and retry UX.
ScenarioCredentialTask statusUse it to test
VOIE-X1goodlogin / no_datano_dataSuccessful login, provider returns zero records
VOIE-X2goodlogin / mfamfadoneMFA flow — enter code 12345
VOIE-X3goodlogin / mfa_captchamfadoneMFA captcha — enter answer 9M4BP
VOIE-X4goodlogin / mfa_selectmfadoneMFA verification-method selection
VOIE-X5goodlogin / longcheckparsedone (delayed)~30 second processing delay
VOIE-X6error.user / login_errorlogin_errorIncorrect credentials
VOIE-X7error.user / mfa_errormfa_errorMFA verification failed
VOIE-X8error.user / account_lockedaccount_lockedAccount locked by provider
VOIE-X9error.user / unavailableunavailableProvider under maintenance
VOIE-X10error.user / errorerrorGeneric login error
VOIE-X11error.user / config_errorconfig_errorOrganization ID configuration failure
See Task lifecycle for the full status reference and the meaning of each error state.

Fraud and suspicious documents

Document-uploaded VOIE uses filename-driven triggers in sandbox to simulate fraud detection. The full filename → task status + error_message map lives on the Test Documents page. For interpreting is_suspicious on the report, fraud-tier behavior, and recommended manual-review workflows, see Fraud Detection & Manual Review.

Webhook events

When testing VOIE end to end, your webhook endpoint receives one task-status-updated event per status transition plus one order-status-updated event per connection when the user finishes the order.
Per-task event (one per employer connection):
{
  "webhook_id": "609a82aab21e4d9ba2569f35e9e8f26a",
  "event_type": "task-status-updated",
  "updated_at": "2026-04-26T13:02:20.369267+00:00",
  "task_id": "67f2924530564282bbaf6d27655e94a4",
  "link_id": "64f8e374949c4b769706028022626bf1",
  "product": "income",
  "tracking_info": "your-applicant-id",
  "status": "done"
}
Order event (one per connection — fires for each unique link_id when the user closes Bridge via Finish and Share, so an order with more than one connection emits multiple order-status-updated events):
{
  "webhook_id": "698e974cb30646189862229199f7ed1a",
  "event_type": "order-status-updated",
  "event_created_at": "2026-04-26T13:02:35.172897+00:00",
  "product": "income",
  "link_id": "64f8e374949c4b769706028022626bf1",
  "order_id": "45771e47434341039c61ccb28caeb9d8",
  "order_number": "your-loan-number",
  "status": "completed"
}
For the difference between these two events and why tracking_info is the reliable mapping key, see the Orders object reference.

Mortgage VOIE (GSE testing)

For Fannie Mae Day 1 Certainty and Freddie Mac AIM testing — with borrower test accounts that map to specific GSE submission outcomes — see GSE Testing and the credential tables on the Fannie Mae D1C and Freddie Mac AIM pages.

Next steps

Bridge Widget Guide

Mint a bridge token and embed the widget

Embedded Orders

Order-driven VOIE with auto-generated reports

GSE Testing

Fannie Mae D1C and Freddie Mac AIM workflows

Report Object

JSON schema for the VOIE report