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

# Embedded Orders Best Practices

> Guidelines for implementing Embedded Orders

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 Orders                                                                                                                        | Bridge Token                                                                                      |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| **When to use**           | You 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 via**            | `POST /v1/orders/`                                                                                                                     | `POST /v1/users/{user_id}/tokens/`                                                                |
| **Products parameter**    | `products` array: `["income"]`, `["assets"]`, `["income", "assets"]`                                                                   | `product_type` string: `"income"`, `"employment"`, `"assets"` + optional `allowed_products` array |
| **Bridge initialization** | Pass `bridge_token` from order response, set `isOrder: true`                                                                           | Pass `bridge_token` from token response, `isOrder` not set                                        |
| **Notifications**         | Truv can send email/SMS to the user with a verification link                                                                           | You handle all user communication                                                                 |
| **Webhooks**              | `order-status-updated` + `task-status-updated`                                                                                         | `task-status-updated` only                                                                        |
| **Data retrieval**        | Via order ID or link ID                                                                                                                | Via link ID only                                                                                  |
| **Best for**              | Hosted flows, multi-employer orders, caseworker-initiated verification                                                                 | Inline embedded flows where you control the full UX                                               |

<Info>
  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](/developers/integration/embedded-orders/overview) and [Bridge Widget overview](/developers/integration/bridge-widget/overview) for full implementation guides.
</Info>

***

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

```json theme={null}
// 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.

```bash theme={null}
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.

<Tip>
  Always pass `external_user_id` in production. It enables user continuity and simplifies data lookups across orders.
</Tip>

***

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

```bash theme={null}
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](/api-reference/companies/company_mapping).

[Deeplinking guide →](/developers/integration/embedded-orders/deeplinking)

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

```bash theme={null}
# 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:

```bash theme={null}
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 →](/developers/integration/embedded-orders/follow-up)

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

```bash theme={null}
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 →](/developers/integration/embedded-orders/data-refresh)

***

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

```javascript theme={null}
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](/developers/sdks/bridge-events#errors) for all codes.

```javascript theme={null}
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.

```bash theme={null}
# 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](/api-reference/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

<CardGroup cols={2}>
  <Card title="Embedded Orders Guide" icon="rectangle-list" href="/developers/integration/embedded-orders/overview">
    Complete implementation walkthrough
  </Card>

  <Card title="Deeplinking" icon="link" href="/developers/integration/embedded-orders/deeplinking">
    Skip employer search for higher conversion
  </Card>

  <Card title="Follow-up" icon="bell" href="/developers/integration/embedded-orders/follow-up">
    Automatic email and SMS reminders
  </Card>

  <Card title="Data Refresh" icon="arrows-rotate" href="/developers/integration/embedded-orders/data-refresh">
    Refresh data without re-authentication
  </Card>
</CardGroup>
