> ## Documentation Index
> Fetch the complete documentation index at: https://developer.uphold.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Travel Rule Widget SDK reference

> Reference for the @uphold/enterprise-travel-rule-widget-web-sdk package, with the TravelRuleWidget class, constructor options, methods, and event handlers.

Complete reference documentation for the `@uphold/enterprise-travel-rule-widget-web-sdk` package.

The main class for creating and managing Travel Rule Widget instances is `TravelRuleWidget`. It requires a `TravelRuleWidgetSession` object that must be created through the API before instantiating the Widget.

## Constructor

```typescript theme={null}
new TravelRuleWidget<T extends TravelRuleWidgetFlow = TravelRuleWidgetFlow>(
  session: TravelRuleWidgetSession,
  options?: TravelRuleWidgetOptions
)
```

**Parameters:**

| Parameter | Type                      | Required | Description                                                                                                               |
| --------- | ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `session` | `TravelRuleWidgetSession` | Yes      | Travel rule session object obtained from the [Create session](/rest-apis/widgets-api/travel-rule/create-session) endpoint |
| `options` | `TravelRuleWidgetOptions` | No       | Configuration options for the Widget                                                                                      |

**Generic type parameter:**

The constructor accepts an optional generic type parameter that specifies the flow type. When provided, it enables better type inference for event handlers, particularly for the `complete` event.

**Examples:**

```typescript theme={null}
// Generic flow type (default)
const widget = new TravelRuleWidget(session);

// Specific flow type for better type inference
const depositWidget = new TravelRuleWidget<'deposit-form'>(session);
const withdrawalWidget = new TravelRuleWidget<'withdrawal-form'>(session);
```

### Options

```typescript theme={null}
type TravelRuleWidgetOptions = {
  debug?: boolean;
  layout?: WidgetLayout;
  theme?: WidgetThemeOption;
};
```

| Property | Type                | Default           | Description                                                                                           |
| -------- | ------------------- | ----------------- | ----------------------------------------------------------------------------------------------------- |
| `debug`  | `boolean`           | `false`           | Enable debug mode for additional logging                                                              |
| `layout` | `WidgetLayout`      | `'boxed'`         | Control how the Widget is laid out on larger viewports. See [WidgetLayout](#widgetlayout) for details |
| `theme`  | `WidgetThemeOption` | System preference | Control the visual appearance of the Widget. See [WidgetThemeOption](#widgetthemeoption) for details  |

**layout option:**

The `layout` option controls how the Widget is laid out when there is enough room to frame it — on viewports that are both at least `md` wide (≥768px) and at least 600px tall, i.e. tablets and up. On smaller viewports — narrower or shorter, including phones in landscape — the Widget always fills its container regardless of this option.

* `'boxed'` (default): on viewports that are ≥768px wide and ≥600px tall, centers the Widget and frames its content as a fixed-size card; on smaller viewports it fills its container. Use this when the Widget takes up the whole page (e.g. mounted into a full-page container).
* `'fluid'`: renders the Widget so it fills its container, with no frame or centering, so your own container (e.g. a modal or a sized panel) acts as the frame.

Most integrations should rely on the default `'boxed'` and only set `layout: 'fluid'` when embedding the Widget in your own framed container.

```typescript theme={null}
const widget = new TravelRuleWidget(session, {
  layout: 'fluid'
});
```

<Note>Use `'fluid'` when you already provide a centered container or modal around the Widget, to avoid a card-within-a-card appearance on larger viewports.</Note>

**theme option:**

The `theme` option lets you control the visual appearance of the Widget. By default, the Widget automatically detects and matches the user's browser or OS appearance preference (`light` or `dark`). Use this option when you want to enforce a specific theme regardless of the user's system settings.

```typescript theme={null}
const widget = new TravelRuleWidget(session, {
  theme: {
    appearance: 'dark',
    primary: { light: '#6200EA', dark: '#BB86FC' },
    // Alternatively, a single color string applies to both appearances, e.g. primary: '#6200EA'
    // primary: '#6200EA',
    fontFamily: 'Inter, sans-serif',
    components: {
      button: { borderRadius: '8px' }
    }
  }
});
```

## Methods

### `mountIframe()`

Mounts the Travel Rule Widget iframe to the specified DOM element.

**Parameters:**

* `element`: The HTML element where the Widget should be mounted

**Example:**

```javascript theme={null}
// Ensure the container has appropriate sizing
const container = document.getElementById('tr-container');

widget.mountIframe(container);
```

<Info>The container element should have explicit dimensions set via CSS. The Widget will fill the entire container. Minimum recommended size is 400px width × 600px height for optimal user experience.</Info>

### `unmount()`

Unmounts and cleans up the Travel Rule Widget iframe.

**Example:**

```javascript theme={null}
widget.unmount();
```

<Warning>The Widget will not unmount itself when a flow is finished, either by successful completion, user cancellation, or unrecoverable error, so it must always be called manually.</Warning>

### `on()`

Registers an event listener for Widget events.

**Parameters:**

* `event`: The event name to listen for
* `callback`: Function to execute when the event is triggered

**Example:**

```javascript theme={null}
widget.on('complete', (event) => {
  console.log('Travel Rule form completed:', event.detail.value);
});
```

### `off()`

Removes an event listener for Travel Rule Widget events.

**Parameters:**

* `event`: The event name to stop listening for
* `callback`: The specific function to remove (must be the same reference as used in `on()`)

**Example:**

```javascript theme={null}
const handleComplete = (event) => {
  console.log('Travel Rule form completed:', event.detail.value);
};

// Register the listener
widget.on('complete', handleComplete);

// Remove the listener
widget.off('complete', handleComplete);
```

## Events

The Travel Rule Widget emits several events during its lifecycle that you can listen to using the `on()` method.

### `complete`

Fired when the Travel Rule form is completed successfully.

```typescript theme={null}
type TravelRuleWidgetCompleteEvent<T = TravelRuleWidgetFlow> = {
  detail: {
    value: T;
  };
};
```

The `event.detail.value` contains the Travel Rule compliance data collected from the user. This is an opaque data structure that should be passed to your backend and used when resolving RFIs or creating transactions.

**Example:**

```typescript theme={null}
widget.on('complete', (event: TravelRuleWidgetCompleteEvent) => {
  const travelRuleData = event.detail.value;

  console.log('Travel Rule form completed:', travelRuleData);

  // Send the data to your backend to resolve the RFI or create the transaction
  await submitTravelRuleData(travelRuleData);

  widget.unmount();
});
```

**Usage in different flows:**

For deposit flows:

```typescript theme={null}
const depositWidget = new TravelRuleWidget<'deposit-form'>(session);

depositWidget.on('complete', async (event) => {
  // Use the travel rule data to resolve the quote requirement
  await resolveQuoteRequirement(quoteId, event.detail.value);

  depositWidget.unmount();
});
```

For withdrawal flows:

```typescript theme={null}
const withdrawalWidget = new TravelRuleWidget<'withdrawal-form'>(session);

withdrawalWidget.on('complete', async (event) => {
  // Use the travel rule data when creating the transaction
  await createTransaction({
    ...transactionParams,
    travelRuleData: event.detail.value
  });

  withdrawalWidget.unmount();
});
```

### `cancel`

Fired when the user cancels the Travel Rule form.

```typescript theme={null}
type TravelRuleWidgetCancelEvent = {
  detail: {};
}
```

**Example:**

```javascript theme={null}
widget.on('cancel', (event: TravelRuleWidgetCancelEvent) => {
  console.log('Travel Rule form cancelled by user');

  widget.unmount();
});
```

### `error`

Fired when an unrecoverable error occurs during the Travel Rule flow.

```typescript theme={null}
type TravelRuleWidgetError = {
  name: string;
  code: string;
  message: string;
  details?: Record<string, unknown>;
  stack?: string;
  cause?: TravelRuleWidgetError;
  httpStatusCode?: number;
}

type TravelRuleWidgetErrorEvent = {
  detail: {
    error: TravelRuleWidgetError;
  };
};
```

**Example:**

```typescript theme={null}
widget.on('error', (event: TravelRuleWidgetErrorEvent) => {
  const { error } = event.detail;
  console.error('Travel Rule form error:', error);

  // Handle specific error types
  if (error.code === 'entity_not_found') {
    // Quote or transaction not found - may have expired
    handleExpiredSession();
  } else if (error.code === 'validation_failed') {
    // Form validation error (shouldn't happen in normal flow)
    console.error('Validation error:', error.details);
  } else {
    // Generic error handling
    showGenericError(error.message);
  }

  widget.unmount();
});
```

### `ready`

Fired when the Travel Rule Widget has finished loading and is ready for user interaction.

```typescript theme={null}
type TravelRuleWidgetReadyEvent = {
  detail: {};
}
```

**Example:**

```typescript theme={null}
widget.on('ready', (event: TravelRuleWidgetReadyEvent) => {
  console.log('Travel Rule form is ready');
});
```

## Types

### TravelRuleWidgetSession

The session object obtained from the [Create session](/rest-apis/widgets-api/travel-rule/create-session) endpoint.

```typescript theme={null}
type TravelRuleWidgetSession = {
  url: string;
  token: string;
  flow: TravelRuleWidgetFlow;
  data: TravelRuleWidgetData;
}
```

### TravelRuleWidgetFlow

Represents the different flows supported by the Travel Rule Widget.

```typescript theme={null}
type TravelRuleWidgetFlow = 'deposit-form' | 'withdrawal-form';
```

### TravelRuleWidgetData

The data object included in the session, containing context for the flow.

```typescript theme={null}
type TravelRuleWidgetData = {
  provider: 'notabene';
  parameters: object;
};
```

### TravelRuleResult

The result object returned upon successful completion of the Travel Rule form.

```typescript theme={null}
type TravelRuleResult = Record<string, unknown>;
```

<Note>
  The `event.detail.value` object is an opaque data structure that should be used as-is when resolving RFIs or creating transactions.
</Note>

### WidgetLayout

Controls how the Widget is laid out on larger viewports.

```typescript theme={null}
type WidgetLayout = 'boxed' | 'fluid';
```

| Value     | Description                                                                                                                                                                              |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'boxed'` | Default. On viewports that are ≥768px wide and ≥600px tall (tablets and up), centers the Widget and frames its content as a fixed-size card; on smaller viewports it fills its container |
| `'fluid'` | Renders the Widget so it fills its container, with no frame or centering, so your own container acts as the frame                                                                        |

### WidgetThemeOption

Controls the visual appearance of the Widget.

```typescript theme={null}
type WidgetThemeOption = {
  appearance?: 'light' | 'dark';
  primary?: ColorTokenValue;
  primaryForeground?: ColorTokenValue;
  foreground?: ColorTokenValue;
  emphasisForeground?: ColorTokenValue;
  background?: ColorTokenValue;
  fontFamily?: FontFamily;
  components?: {
    button?: { borderRadius?: string };
    input?: { borderRadius?: string };
    card?: { borderRadius?: string };
  };
};
```

| Property             | Type                | Description                                                                                            |
| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ |
| `appearance`         | `'light' \| 'dark'` | Forces the Widget to render in light or dark mode, overriding the user's system preference             |
| `primary`            | `ColorTokenValue`   | Primary brand color, used for buttons and key interactive elements                                     |
| `primaryForeground`  | `ColorTokenValue`   | Text color rendered on top of the primary color                                                        |
| `foreground`         | `ColorTokenValue`   | Main text color                                                                                        |
| `emphasisForeground` | `ColorTokenValue`   | Emphasized text color                                                                                  |
| `background`         | `ColorTokenValue`   | Widget background color                                                                                |
| `fontFamily`         | `FontFamily`        | Font family applied across the Widget. See [FontFamily](#fontfamily) for details                       |
| `components`         | `object`            | Per-component style overrides for `button`, `input`, and `card` (each accepts `borderRadius?: string`) |

### ColorTokenValue

A color value that can be a single string applied to both light and dark modes, or separate values per mode.

```typescript theme={null}
type ColorTokenValue = string | { light: string; dark: string };
```

### FontFamily

A font family that can be a single string applied to all slots, or separate values per slot (`mono`, `sans`, `serif`).

```typescript theme={null}
type FontFamily = string | Partial<Record<'mono' | 'sans' | 'serif', string>>;
```

## Complete usage example

Here's an end-to-end example showing how to use the Travel Rule Widget with all events and type safety:

```typescript theme={null}
import { TravelRuleWidget } from '@uphold/enterprise-travel-rule-widget-web-sdk';

// Create a Travel Rule Widget session from your backend
const session = await createTravelRuleWidgetSession(quoteId);

// Initialize the Widget with type inference
const widget = new TravelRuleWidget<'deposit-form'>(session, { debug: true });

// Handle ready event
widget.on('ready', () => {
  console.log('Travel Rule form is ready');
});

// Handle completion with the Travel Rule data
widget.on('complete', async (event) => {
  const travelRuleData = event.detail.value;
  console.log('Travel Rule form completed:', travelRuleData);

  try {
    // Send the data to your backend to resolve the quote requirement
    await resolveQuoteRequirement(quoteId, travelRuleData);

    // Proceed with the transaction flow
    showSuccessMessage('Travel Rule compliance completed');
  } catch (error) {
    console.error('Failed to submit Travel Rule data:', error);
    showErrorMessage('Failed to submit compliance information');
  }

  widget.unmount();
});

// Handle cancellation
widget.on('cancel', () => {
  console.log('Travel Rule form cancelled by user');
  showCancellationMessage();
  widget.unmount();
});

// Handle errors with specific error handling
widget.on('error', (event) => {
  const { error } = event.detail;
  console.error('Travel Rule form error:', error);

  if (error.code === 'entity_not_found') {
    showErrorMessage('Session expired. Please start over.');
  } else {
    showErrorMessage(error.message);
  }

  widget.unmount();
});

// Mount the Widget to a DOM element
widget.mountIframe(document.getElementById('tr-container'));
```
