Skip to main content
Follow these best practices for Deposit Switch (DDS) and Paycheck Linked Lending (PLL) integrations using the Widget-only flow.

Wait for webhooks before proceeding

Always wait for the task-status-updated webhook with status: done before treating a connection as complete. Do not rely solely on the client-side onSuccess callback. The task may still be processing server-side.
# When you receive a task-status-updated webhook with status: done,
# retrieve the link details
curl --request GET \
     --url https://prod.truv.com/v1/links/{link_id}/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET'

Validate account details upfront

Provide complete and accurate bank account information when creating the bridge token. Missing or incorrect fields cause configuration failures. Deposit Switch: route the user’s entire paycheck or a fixed amount:
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",
  "account": {
    "account_number": "16002600",
    "routing_number": "123456789",
    "bank_name": "TD Bank",
    "account_type": "checking",
    "deposit_type": "entire"
  }
}'
Paycheck Linked Lending: deduct a fixed amount per paycheck:
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": "pll",
  "account": {
    "account_number": "16002600",
    "routing_number": "123456789",
    "bank_name": "TD Bank",
    "account_type": "checking",
    "deposit_type": "amount",
    "deposit_value": "200.00"
  }
}'

Deposit type options

deposit_typeDescription
entireRoute the entire paycheck
amountRoute a fixed dollar amount (set deposit_value)
percentRoute a percentage of the paycheck (set deposit_value)

Handle errors from webhooks

Monitor task-status-updated webhooks for error statuses. These indicate the connection or configuration failed.
Webhook statusCauseResolution
login_errorIncorrect credentialsPrompt the user to re-authenticate via Bridge Update Mode
mfa_errorMFA challenge failedPrompt the user to try again
config_errorProvider doesn’t support the requested operationFall back to manual instructions or try a different provider
account_lockedToo many failed attempts at the providerAsk the user to unlock their account with the provider
See Task lifecycle for all status transitions.

Handle client-side errors

Listen for ERROR events in the Bridge onEvent callback. The error object uses error_code, not a generic code field.
onEvent: function(type, payload) {
  if (type === 'ERROR') {
    switch (payload.error.error_code) {
      case 'LOGIN_ERROR':
        // User entered wrong credentials — Bridge handles retry UI
        break;
      case 'UNAVAILABLE':
        showMessage('This provider is temporarily unavailable. Try again later.');
        break;
      case 'LINK_EXISTS':
        showMessage('This account is already connected.');
        break;
    }
  }
}
See Bridge Events for all error codes and their meanings.

Use deeplinking when you know the employer

If you know the user’s employer or payroll provider, pass it when creating the bridge token to skip search screens and improve conversion.
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",
  "company_mapping_id": "48427a36d43c4d5aa6324bc06c692456",
  "account": {
    "account_number": "16002600",
    "routing_number": "123456789",
    "bank_name": "TD Bank",
    "account_type": "checking",
    "deposit_type": "entire"
  }
}'
See Deeplinking for the full guide.

Check DDS/PLL support before connecting

Use the company search endpoint to check if a provider supports DDS or PLL before routing the user through the flow. This avoids dead-end experiences where the user connects but the provider doesn’t support the desired product.
curl --request GET \
     --url 'https://prod.truv.com/v1/company-mappings-search/?query=Facebook' \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET'
Check the response for DDS/PLL availability before initiating the bridge token.

Leverage VOIE-PLL flow

For combined income verification and paycheck linked lending, complete the VOIE flow first, then check if the connected provider supports DDS/PLL. After VOIE completes, fetch the link details:
curl --request GET \
     --url https://prod.truv.com/v1/links/{link_id}/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET'
Check the is_dds_available flag in the response. If true, the user’s payroll provider supports DDS/PLL and you can offer it as a follow-up step without requiring the user to reconnect.

Understand the token flow

The Widget-only flow uses a three-token exchange to securely connect users to their payroll providers:
bridge_token → public_token → access_token
TokenCreated ByLifetimePurpose
bridge_tokenYour server (via API)6 hoursInitialize Truv Bridge on the client
public_tokenTruv Bridge (on success)Short-livedTemporary token for exchange
access_tokenToken exchange (via API)PersistentConfigure DDS/PLL and retrieve data

Store and protect tokens

  • access_token is persistent and grants access to the user’s data. Store it encrypted on your server.
  • bridge_token is short-lived (6 hours) and safe to pass to the client. Generate a new one if the user hasn’t started within that window.
  • public_token is single-use. Exchange it immediately for an access_token via POST /v1/link-access-tokens/ and discard it.
Never expose access_token or API credentials in client-side code.

Verify webhook signatures

Always verify the X-WEBHOOK-SIGN header on incoming webhooks to confirm they are from Truv. Use the raw request body. Never use parsed JSON. See Webhook Security for verification examples.

Next steps

Widget-only Integration

Implementation guide for Widget-only flow

Returning User

Reconnect or update an existing link

Bridge Events

Client-side event types and error codes

Task Lifecycle

Server-side connection statuses