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

# Direct Deposit Switch Testing

> Sandbox credentials, allocation scenarios, and webhook flow for DDS integrations

Test Direct Deposit Switch (DDS) flows in sandbox using the credentials below. Pass `product_type: deposit_switch` on the bridge token along with the `account` block, and search for **Truv Payroll Provider** in Truv Bridge.

<Tip>
  For additional login fields, use **Phone:** `(111)111-1111` and **Email:** `goodlogin@domain.com`.
</Tip>

<Warning>
  The `account` block is functionally required at bridge-token creation for `deposit_switch`. The widget writes the new allotment into the payroll provider during the customer's authenticated session, so the destination must be in hand before Bridge launches. See [DDS implementation](/banking/integration/dds#configure-account-details) for the full constraint set.
</Warning>

***

## Quick start

Use `goodlogin` / `goodpassword` against Truv Payroll Provider with this bridge token payload:

```bash theme={null}
curl --request POST \
  --url https://prod.truv.com/v1/users/{user_id}/tokens/ \
  --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
  --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
  --header 'content-type: application/json' \
  --data '{
    "product_type": "deposit_switch",
    "tracking_info": "your-applicant-id",
    "account": {
      "account_number": "16002600",
      "routing_number": "123456789",
      "bank_name": "Your Bank",
      "account_type": "checking",
      "deposit_type": "entire"
    }
  }'
```

A successful switch transitions the task through `parse` → `full_parse` → `switch_deposit` → `done`. Retrieve the confirmation with [GET /v1/users/\{user\_id}/deposit\_switch/report/](/api-reference/dds-reports/dds-report-retrieve).

***

## Allocation type scenarios

DDS supports three allocation types. Each behaves differently on the payroll-provider side, so test all three.

| Scenario | `deposit_type` | `deposit_value`                 | Behavior                                              |
| -------- | -------------- | ------------------------------- | ----------------------------------------------------- |
| `DDS-A1` | `entire`       | Not required                    | Routes the entire paycheck to the destination account |
| `DDS-A2` | `amount`       | Dollar amount (e.g. `"500.00"`) | Routes a fixed dollar amount per pay cycle            |
| `DDS-A3` | `percent`      | Percentage (e.g. `"50"`)        | Routes a percentage of the paycheck                   |

Sample DDS report response after a successful switch:

```json theme={null}
{
  "id": "24d7e80942ce4ad58a93f70ce4115f5c",
  "status": "done",
  "finished_at": "2026-05-15T11:30:00Z",
  "completed_at": "2026-05-15T11:30:00Z",
  "access_token": "48427a36d43c4d5aa6324bc06c692456",
  "tracking_info": "your-applicant-id",
  "deposit_details": {
    "account_number": "16002600",
    "account_type": "checking",
    "routing_number": "123456789",
    "bank_name": "Your Bank",
    "deposit_type": "percent",
    "deposit_value": "50.00"
  },
  "initial_accounts": [
    {
      "account_number": "16001234",
      "routing_number": "55999876"
    }
  ]
}
```

***

## Error scenarios

DDS surfaces a number of payroll-provider-side validation failures as `config_error`. The most common ones to test:

| Scenario | Credential / setup                                                | Task status      | What it simulates                                                                                                                                                 |
| -------- | ----------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DDS-X1` | `goodlogin` / `goodpassword`, customer already at 100% allocation | `config_error`   | Payroll provider rejects the new allotment because total distribution already equals 100%. The customer must reduce or remove an existing allotment before retry. |
| `DDS-X2` | `error.user` / `config_error`                                     | `config_error`   | Organization ID configuration failure                                                                                                                             |
| `DDS-X3` | `error.user` / `login_error`                                      | `login_error`    | Incorrect credentials                                                                                                                                             |
| `DDS-X4` | `error.user` / `mfa_error`                                        | `mfa_error`      | MFA verification failed                                                                                                                                           |
| `DDS-X5` | `error.user` / `account_locked`                                   | `account_locked` | Account locked by provider                                                                                                                                        |

<Note>
  For the "already at 100%" scenario, Truv surfaces the payroll provider's exact rejection message in the task `error_message` field. Render that message back to the customer rather than a generic error — it tells them exactly which existing allotment to adjust.
</Note>

See [Task lifecycle](/api-reference/tasks/lifecycle) for the full status reference.

***

## Already-connected employers

When the same applicant (same `external_user_id`) attempts a second connection to the same employer they've already verified at, Truv blocks the duplicate by default — controlled by the `is_same_account_connection_restricted` UWS flag, which is **on** for most accounts.

In Bridge, the applicant sees an **"Already connected"** screen with an option to update the existing connection rather than creating a new one. From the API side, this means:

* Creating a new order with the same `external_user_id` and routing the applicant back through Bridge for the same employer does **not** produce a second link or a second `switch_deposit` task.
* To programmatically refresh a DDS connection's data (without the applicant re-authenticating), use the [refresh order endpoint](/api-reference/orders/orders_create_refresh_order) on the original order.
* To re-allocate to a **different** destination account for the same applicant + same employer, you'll need to either disable the restriction on your account (contact [support@truv.com](mailto:support@truv.com)) or update the existing allotment via the same provider session.

For QA test plans that exercise "applicant reconnects after disconnecting": use a fresh `external_user_id` per test run, since the same `external_user_id` will be treated as a returning user.

***

## Webhook events

DDS includes one status that other products don't: `switch_deposit`. This indicates Truv is actively writing the new allotment into the payroll provider after parsing completed.

<Accordion title="Sample webhook payload">
  ```json theme={null}
  {
    "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": "deposit_switch",
    "tracking_info": "your-applicant-id",
    "status": "switch_deposit"
  }
  ```
</Accordion>

The terminal event arrives with `status: done` (or `status: config_error` if the switch failed at the payroll-provider validation step).

***

## Behavior and limitations

### No PDF report

Unlike VOIE and VOA, DDS does not generate a downloadable PDF report. The deliverable is the JSON response from the [DDS Report endpoint](/api-reference/dds-reports/dds-report-retrieve), which confirms the destination Truv wrote and the customer's pre-existing accounts.

If you persist switch evidence for audit, store the JSON response alongside your application record at the time `task-status-updated` fires with `status: done`.

### Destination matching

When Truv writes the allotment, the match key against existing direct deposit rows is `account_number + routing_number` (with a last-4 fallback when the payroll provider masks the account number). Same destination is a no-op or in-place update; different destination is an insert. There is no source-of-origin marker — Truv cannot distinguish a row it wrote previously from one the customer created manually.

See [DDS destination matching](/banking/integration/dds#configure-account-details) for the full match rules.

***

## Next steps

<CardGroup cols={2}>
  <Card title="DDS Implementation Guide" icon="book-open" href="/banking/integration/dds">
    Full implementation guide with allocation patterns and constraints
  </Card>

  <Card title="Bridge Token API" icon="key" href="/api-reference/bridge-token/users_tokens">
    Mint a deposit\_switch bridge token
  </Card>

  <Card title="DDS Report API" icon="file-lines" href="/api-reference/dds-reports/dds-report-retrieve">
    Retrieve the switch confirmation
  </Card>

  <Card title="Webhook Events" icon="bell" href="/api-reference/webhook-events">
    Handle task-status-updated through switch\_deposit
  </Card>
</CardGroup>
