Skip to main content
Set the payroll data a sandbox verification returns. A payroll scenario pairs a login with the employments, paystubs, W-2s, bank accounts, and shifts you want back, and serves them when the user signs in with that login in Truv Bridge. It drives every payroll product: Income & Employment, Employment History, Direct Deposit Switch, and Paycheck Linked Lending. Use it when the built-in payroll credentials don’t cover the case you need: a specific pay frequency, a terminated employment, a second job, or income near your approval threshold. For the shared concepts, read Custom Sandbox Data first.

Create a scenario [Server-side]

Truv’s built-in payroll logins are reserved. Don’t use goodlogin or error.user, whatever the password: the API refuses them with reserved_credential. The reserved set grows as Truv publishes new test credentials, so use a distinctive username prefix, such as acme..
This request creates a scenario with one salaried employment and one paystub:
Send "data_source": "payroll" explicitly. username and password are supported on payroll, financial accounts, and insurance, so Truv can’t infer the data source from them and refuses the request with data_source_required. Only company_domain fits payroll alone, so a scenario that sets it can leave data_source out.

Use it in Bridge

Start a sandbox verification the way you normally do. In Truv Bridge, select Truv Payroll Provider and sign in with acme.salaried / s4ndb0x. The task completes with your data instead of Truv’s built-in test data. Read the result the same way as for any other connection: from the task webhooks and the income and employment report. The scenario above sets neither provider_id nor company_domain, so any payroll provider works in sandbox. If your scenario sets either field, use a connection that matches those values.
This request fills every section of an employment. It creates a separate scenario, acme.full, so it doesn’t collide with the one above.

The response

The response is the stored scenario, with the fields you left out filled in with their defaults. The request sent no behavior fields, so the task completes with done, with no delay and no MFA. The payload is abbreviated here; the API returns it in full.
filenames, ssn_last4, and date_of_birth are matching fields for other data sources, so they stay empty on a payroll scenario.

Matching fields

These fields decide which login the scenario answers. A field you leave out narrows nothing, so it matches any value. Set at least one of username, password, provider_id, or company_domain; is_refresh doesn’t count on its own. products restricts the scenario to a subset of income, employment, deposit_switch, and pll. Empty, the default, matches every payroll product.

Behavior

A payroll scenario supports every behavior_status and replays behavior_mfa at login. The payroll sandbox acts on every status except unable_to_reset, which it treats as a successful login. See Behavior for the fields.

Payload reference

The payload object contains an employments array and optional flags. The tables below describe the fields in each employment record. Every field is optional unless noted: send only what your test needs, and leave the rest out.
Fraud markers reported alongside the data, at the top level of the payload next to employments.
Money and quantities are decimal strings, so nothing is lost to floating point: "4615.38", not 4615.38.

Examples

Each example is a request body for POST /v1/sandbox/scenarios/ and creates a new scenario. Send it with the same curl command as the first scenario. The hourly, two-job, terminated, and failing-login bodies are complete. The rest are abbreviated to the fields the example is about, and each one says so above its code block.

Hourly employee with overtime

Express an hourly wage as income plus income_unit: "HOURLY", and put the hours on the paystub.

Two employments

Return a second job by adding another entry to employments. Up to 10 fit in one scenario.

Terminated employment

Set end_date and is_active: false. end_date can equal start_date but not precede it.

Failing login

A failure status needs no payload. Use it to exercise the error paths in your integration.

Slow task

Delay the task before it finishes, up to 120 seconds, to test loading states and webhook ordering.

MFA challenge

behavior_mfa.challenges replays one screen per entry, in order. A TEXT challenge prompts for a code; an OPTIONS challenge renders a select. A challenge with neither answer nor answers accepts anything the user types.
Use answers when more than one response is acceptable. Up to 5 challenges per scenario.

Refresh-only data

Set the data a data refresh should find by restricting a scenario to refreshes with is_refresh: true. On a refresh it wins over the general scenario for the same login, because it sets is_refresh and the other doesn’t. Create it alongside the acme.salaried scenario; don’t update that one.
The user signs in once with acme.salaried and gets the original data; the refresh of that same connection gets the raised income.

Restrict a scenario to one provider or employer

Add provider_id or company_domain to answer only connections that went through a specific provider or employer. This is how the same login returns different data depending on where the user connected. Create it alongside the acme.salaried scenario: the extra matching field makes it more specific, so it wins for ADP connections. company_domain matches the employer the user selects through company search in Truv Bridge, the domain that Search companies returns. A user who picks a provider directly, such as Truv Payroll Provider, selects no employer, so a scenario that sets company_domain doesn’t match their connection.

Attach PDFs

A paystub or W-2 can carry a real file. Upload it to your sandbox document library once, then reference it by id from as many scenarios as you like. A paystub’s file is optional; every W-2 needs one, because a W-2 with nothing behind it is dropped when the task is served.
1

Upload the paystub PDF

Send the file as multipart/form-data. filename is a separate field: it is the name the entry is addressed by, and it does not have to match the name on disk.
The response is the library entry. Keep the top-level id: that is the document_id your payload references.
documents is test metadata you configure for the file, not data extracted from it. You didn’t send it, so the entry got the default: one paystub for John Doe at Acme Inc. Only document upload scenarios read it. A payroll scenario serves the file and ignores it, so leave it out.
2

Upload the W-2 PDF

The same endpoint also takes a JSON body, with the bytes base64-encoded in content. Use whichever transport suits your client, and send exactly one of file or content, never both.
The response has the same shape as the multipart one. validations and documents are abbreviated here.
3

Reference both from a scenario

Put each id on the record it belongs to: the paystub’s file on the paystub, the W-2’s file on the W-2.
Sign in with acme.documents / s4ndb0x and the completed task carries both PDFs, downloadable through the same endpoints as any other connection: Pay Statements for the paystub and Tax Documents for the W-2.

Limits

These are the default limits for payroll payloads. The account-wide limits are listed on Custom Sandbox Data.

Next steps

Income & Employment Testing

Truv’s built-in payroll credentials and sample reports

Document upload scenarios

Serve the same employment data from uploaded documents

Data refresh

How refreshes reach your is_refresh scenarios

Sandbox API reference

Full request and response schemas for every sandbox endpoint