Skip to main content
Follow these best practices to ensure a successful Embedded Orders integration, from order creation through data retrieval and ongoing maintenance.

Embedded Orders vs Bridge Token

Truv offers two integration methods. Choose based on your use case:
Embedded OrdersBridge Token
When to useYou don’t know the user’s employer upfront, or you need Truv to manage the order lifecycle (notifications, reminders, status tracking)You already know the employer and want full control over the UI and data flow
Create viaPOST /v1/orders/POST /v1/users/{user_id}/tokens/
Products parameterproducts array: ["income"], ["assets"], ["income", "assets"]product_type string: "income", "employment", "assets" + optional allowed_products array
Bridge initializationPass bridge_token from order response, set isOrder: truePass bridge_token from token response, isOrder not set
NotificationsTruv can send email/SMS to the user with a verification linkYou handle all user communication
Webhooksorder-status-updated + task-status-updatedtask-status-updated only
Data retrievalVia order ID or link IDVia link ID only
Best forHosted flows, multi-employer orders, caseworker-initiated verificationInline embedded flows where you control the full UX
Most integrations use Embedded Orders. Use Bridge Token only when you need direct control over the connection flow and already have the employer identified. See Embedded Orders overview and Bridge Widget overview for full implementation guides.

Create an order

Request the right products

Specify only the products your use case requires. When you include income in the products array, employment data is automatically included. You do not need to pass both.
// Correct — income includes employment data
{ "products": ["income"] }

// Incorrect — employment is redundant here
{ "products": ["income", "employment"] }

// Assets only
{ "products": ["assets"] }

// Income + Assets
{ "products": ["income", "assets"] }

Use external_user_id for user continuity

Pass your internal user identifier as external_user_id when creating orders. This maps to a persistent Truv user and carries forward across every order you create for that person.
curl --request POST \
     --url https://prod.truv.com/v1/orders/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
     --header 'Content-Type: application/json' \
     --data '{
  "products": ["income"],
  "first_name": "John",
  "last_name": "Doe",
  "external_user_id": "your-internal-user-id-1235"
}'
When you create a second order with the same external_user_id, the user’s previous connections are remembered. For example, if a user connected to ADP on their first order and you create a new order with the same external_user_id, the orders landing page will already show their ADP connection, reducing friction and improving completion rates.
Always pass external_user_id in production. It enables user continuity and simplifies data lookups across orders.

Optimize conversion

Skip search with deeplinking

If you already know the user’s employer or payroll provider, pass a company_mapping_id when creating the order. This skips the search screen and drops users directly into the login flow, one of the highest-impact conversion improvements you can make.
curl --request POST \
     --url https://prod.truv.com/v1/orders/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
     --header 'Content-Type: application/json' \
     --data '{
  "products": ["income"],
  "first_name": "John",
  "last_name": "Doe",
  "employers": [{
    "company_mapping_id": "abc123"
  }]
}'
Look up company_mapping_id values using the Companies API. Deeplinking guide →

Send follow-up reminders

When a user leaves without completing verification, Truv can automatically send email and SMS reminders. Suppress notifications during the in-app session, then enable them after the user exits.
# Create order with notifications suppressed during in-app flow
curl --request POST \
     --url https://prod.truv.com/v1/orders/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
     --header 'Content-Type: application/json' \
     --data '{
  "products": ["income"],
  "first_name": "John",
  "last_name": "Doe",
  "email": "john@example.com",
  "notification_settings": {
    "suppress_user_notifications": true
  }
}'
After the user closes the widget without finishing, update the order to enable reminders:
curl --request PATCH \
     --url https://prod.truv.com/v1/orders/{order_id}/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
     --header 'Content-Type: application/json' \
     --data '{
  "notification_settings": {
    "suppress_user_notifications": false
  }
}'
Truv sends up to 3 automatic reminders before the order expires. Order links are valid for 72 hours by default (configurable per client). Follow-up guide →

Refresh data without re-authentication

When you need updated income or employment data for an existing user, create a data refresh order instead of asking them to reconnect. Truv reuses existing account links. The user doesn’t need to do anything.
curl --request POST \
     --url https://prod.truv.com/v1/refresh/tasks/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET' \
     --header 'Content-Type: application/json' \
     --data '{
  "access_token": "EXISTING_ACCESS_TOKEN",
  "product_type": "income"
}'
Data refresh guide →

User experience

Wait for the right event

Use the COMPLETED event with source: "order" before advancing the user in your application. Don’t use onSuccess or onClose. The order may still have pending connections.
onEvent: function(type, payload, source) {
  if (type === 'COMPLETED' && source === 'order') {
    navigateToNextStep();
  }
}

Handle errors gracefully

Listen for ERROR events from the connection widget (source: "bridge"). The error payload uses the error object with error_code. See Bridge Events for all codes.
onEvent: function(type, payload, source) {
  if (type === 'ERROR' && source === 'bridge') {
    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. Please try again later.');
        break;
    }
  }
}

Webhooks

Process tasks as they complete

Handle task-status-updated webhooks to process data as each connection finishes. Don’t wait for the full order to complete.
# When you receive a task-status-updated webhook with status: done,
# fetch the income report for the completed link
curl --request GET \
     --url https://prod.truv.com/v1/links/{link_id}/income/report/ \
     --header 'X-Access-Client-Id: YOUR_TRUV_CLIENT_ID' \
     --header 'X-Access-Secret: YOUR_TRUV_CLIENT_SECRET'

Validate webhook signatures

Always verify the X-WEBHOOK-SIGN header to confirm requests are from Truv. Use the raw request body. Never use parsed JSON. See Webhook Security for full verification examples in multiple languages.

Security

  • Never expose API credentials in client-side code. Use bridge_token for frontend operations only.
  • Don’t log sensitive data (SSN, income figures, account numbers)
  • Encrypt verification data at rest
  • Implement data retention policies. Don’t store data longer than needed.
  • Validate webhook signatures on every request

Monitoring

Track these metrics to monitor integration health:
  • Order completion rate: percentage of orders where the user finishes at least one connection
  • Average connections per order: indicates whether users are connecting all requested accounts
  • Error rates by type: identify provider-specific or credential issues
  • Webhook delivery success: ensure you’re receiving all status updates
  • Time to completion: how long users take to finish the verification flow

Next steps

Embedded Orders Guide

Complete implementation walkthrough

Deeplinking

Skip employer search for higher conversion

Follow-up

Automatic email and SMS reminders

Data Refresh

Refresh data without re-authentication