> ## 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.

# The Sandbox Scenario object

> Author your own sandbox responses — pair a login with the data Truv should return for it.

A **sandbox scenario** is a client-authored test case: when this input arrives, behave like this and return that. Create one, sign in with its login in Truv Bridge, and the task completes with your data instead of Truv's built-in test data.

Scenarios are scoped to your account, so every teammate's sandbox key reads and writes the same set. The endpoints accept sandbox keys only — a production key gets `403 env_not_sandbox`.

For a walkthrough with worked examples of payroll scenarios, see [Custom Sandbox Data](/developers/testing/custom-sandbox-data).

***

## Attributes

### Identity and routing

| Attribute | Type | Description |
| :- | :- | :- |
| id | string | Unique identifier of the scenario |
| data\_source | string | Data source the scenario answers for. Inferred from which matching fields are set when omitted. Can't be changed after create — to use another data source, create a new scenario |
| label | string | How the scenario is recognized in a list. Unique per data source within your account |
| description | string | Free-form notes about what the case covers |
| products | array | Products the scenario applies to. Payroll scenarios use `income`, `employment`, `deposit_switch`, and `pll`. Empty matches every product |
| enabled | boolean | Whether the scenario takes part in resolution |
| created\_at | datetime | Timestamp for created scenario |
| updated\_at | datetime | Timestamp for updated scenario |

### How a scenario is selected

These matching fields decide which input the scenario answers. A field left unset narrows nothing, so it matches any value. The API refuses a scenario that sets none of them, and `is_refresh` alone doesn't count — such a scenario would answer every input of its data source. No two scenarios of the same data source can have the same matching fields; `enabled` and `products` don't make them distinct.

| Attribute | Type | Data source | Description |
| :- | :- | :- | :- |
| username | string | Payroll, financial accounts, insurance | The login the user types. Matched exactly |
| password | string | Payroll, financial accounts, insurance | The password the user types |
| provider\_id | string | Payroll, financial accounts, insurance | Narrows the match to one data provider |
| company\_domain | string | Payroll | Narrows the match to one company |
| is\_refresh | boolean | Every data source | `true` matches refreshes only, `false` initial verifications only, null both |
| filenames | array | Document upload | Uploaded filenames that select this case |
| ssn\_last4 | string | Education, credit | Last four SSN digits that select this case |
| date\_of\_birth | date | Education | Date of birth that selects this case |
| phone | string | Credit | Phone number that selects this case, stored in E.164 |

### Behavior

| Attribute | Type | Description |
| :- | :- | :- |
| behavior\_status | string | Terminal status the task settles on. Defaults to `done` |
| behavior\_error\_message | string | Error message surfaced on a failing task |
| behavior\_duration\_seconds | integer | Artificial delay before the task settles, `0`–`120` |
| behavior\_mfa | object | Multi-factor authentication (MFA) screens replayed before the data is returned |

### Content

| Attribute | Type | Description |
| :- | :- | :- |
| payload | object | The data the scenario returns. Shape depends on `data_source`. Required unless `behavior_status` is a failure status |

***

## Which scenario wins

If multiple scenarios match, Truv selects the scenario with more matching fields, excluding `is_refresh`. `is_refresh` is supported on every data source but doesn't count toward matching fields; if there is still a tie, a scenario that sets it wins over one that doesn't. After that, Truv selects the oldest scenario.

Disabled scenarios never take part, and a scenario pinned to `products` is skipped for tasks of any other product. When nothing matches, the task falls through to Truv's built-in test data. [Resolve a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_resolve) reports the winner for an input without running a verification.

***

## The Sandbox Document object

A **sandbox document** is a file in your sandbox document library. Payroll paystubs and W-2s reference one by `document_id` to serve a real PDF; every W-2 requires one.

| Attribute | Type | Description |
| :- | :- | :- |
| id | string | Unique identifier of the library entry, and the value a payload references as `document_id` |
| uploaded\_file | object | The stored file: `file_id`, `filename`, `mime_type`, `size`, `md5`, a pre-signed `file` URL, plus the declared `status`, `validations` and `last_error` |
| documents | array | Test metadata describing the documents in the file, used when a document-upload scenario serves it. You configure it; Truv doesn't extract it from the file. Defaults to one paystub for John Doe at Acme Inc. when omitted |
| created\_at | datetime | Timestamp for created entry |
| updated\_at | datetime | Timestamp for updated entry |

When a task uses a sandbox document, Truv creates a separate copy for that task. The original stays in your sandbox document library and can be reused. Remove all scenario references before deleting the library entry.

***

## Endpoints

### Scenarios

* [List sandbox scenarios](/api-reference/sandbox/v1_sandbox_scenarios_list) - GET /v1/sandbox/scenarios/
* [Create a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_create) - POST /v1/sandbox/scenarios/
* [Resolve a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_resolve) - POST /v1/sandbox/scenarios/resolve/
* [Retrieve a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_read) - GET /v1/sandbox/scenarios/\{scenario\_id}/
* [Update a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_partial_update) - PATCH /v1/sandbox/scenarios/\{scenario\_id}/
* [Delete a sandbox scenario](/api-reference/sandbox/v1_sandbox_scenarios_delete) - DELETE /v1/sandbox/scenarios/\{scenario\_id}/

### Documents

* [List sandbox documents](/api-reference/sandbox/v1_sandbox_documents_list) - GET /v1/sandbox/documents/
* [Upload a sandbox document](/api-reference/sandbox/v1_sandbox_documents_create) - POST /v1/sandbox/documents/
* [Retrieve a sandbox document](/api-reference/sandbox/v1_sandbox_documents_read) - GET /v1/sandbox/documents/\{document\_id}/
* [Update a sandbox document](/api-reference/sandbox/v1_sandbox_documents_partial_update) - PATCH /v1/sandbox/documents/\{document\_id}/
* [Delete a sandbox document](/api-reference/sandbox/v1_sandbox_documents_delete) - DELETE /v1/sandbox/documents/\{document\_id}/

***

## Errors

Sandbox configuration errors use the standard [error envelope](/api-reference/errors).

| Code | Status | Cause |
| :- | :- | :- |
| `env_not_sandbox` | 403 | The request authenticated with a production key |
| `data_source_required` | 400 | The matching fields set on the scenario fit more than one data source. Send `data_source` explicitly |
| `unsupported_data_source` | 400 | The scenario sets a matching field the data source doesn't accept |
| `reserved_credential` | 400 | The login or filename collides with one of Truv's own documented sandbox credentials |
| `sandbox_limit_exceeded` | 400 | A sandbox quota would be exceeded |
| `resource_in_use` | 409 | A document is still referenced by a scenario |
| `incorrect_parameters` | 400 | A field failed validation. `extra.invalid-params` names the field and the reason |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.