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

# Insurance

> Best practices for implementing Terminal in auto insurance workflows, from quoting through policy binding.

## Overview

This guide covers best practices for integrating Terminal into commercial auto insurance workflows. It's organized into key implementation areas that map to the insurance policy lifecycle:

### What This Guide Covers

This guide walks through the complete insurance workflow with Terminal. Depending on your use case, some sections may be optional:

| Section                                                                          | Description                                                           | When to Use                                                         |
| -------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------- |
| **[Pre-Bind / Underwriting](#pre-bind--underwriting)**                           | Connecting fleets and accessing historical data for risk assessment   | If you're evaluating telematics data before binding policies        |
| **[Connection Lifecycle](#connection-lifecycle)**                                | Handling connection events, disconnections, and compliance monitoring | All implementations—critical for maintaining data access            |
| **[Policy Binding Transition](#policy-binding-transition)**                      | Switching from manual to automatic sync when a policy is bound        | If you start with underwriting and transition to ongoing monitoring |
| **[Data Ingestion](#data-ingestion)**                                            | S3 delivery and API options for getting data into your systems        | All implementations—choose based on volume and architecture         |
| **[First Notice of Loss & Claims](#first-notice-of-loss--claims-investigation)** | Accessing crash reports, camera footage, and safety events for claims | If you handle claims investigation or FNOL workflows                |
| **[Offboarding](#offboarding)**                                                  | Archiving connections when quotes are rejected or policies cancelled  | All implementations—for clean lifecycle management                  |

## Pre-Bind / Underwriting

The first step in processing telematics data for underwriting is obtaining **consent** from the fleet. Terminal's Link component handles the consent flow and authorization with the telematics provider.

### Connecting Fleets with Terminal Link

Use [Terminal Link](/link-component) to guide fleets through connecting their telematics provider. During underwriting, use **Manual sync mode** to control costs—you only sync data when needed for risk assessment.

<Accordion title="View implementation options">
  <Tabs>
    <Tab title="Hosted Flow">
      The hosted flow is a URL you can send directly to fleets via email, SMS, or any messaging channel:

      ```
      https://link.withterminal.com/?sync_mode=manual&backfill_days=90&tags=app-7689&key={PUBLISHABLE_KEY}
      ```
    </Tab>

    <Tab title="React SDK">
      The React SDK can be embedded in your digital onboarding flow if you have one and use React.

      ```tsx theme={null}
      const terminal = useTerminalLink({
        publishableKey: process.env.REACT_APP_TERMINAL_PUBLISHABLE_KEY,
        onSuccess: exchangeToken,
        params: {
          syncMode: 'manual',
          backfill: { days: 90 }, // Your backfill period
          tags: ['app-7689'], // Your application/submission number
        },
      });
      ```
    </Tab>

    <Tab title="JavaScript SDK">
      The JavaScript SDK can be embedded in your digital onboarding flow if you have one.

      ```ts theme={null}
      TerminalLink.initialize({
        publishableKey: process.env.TERMINAL_PUBLISHABLE_KEY,
        onSuccess: (result) => exchangePublicToken(result.publicToken),
        params: {
          syncMode: 'manual',
          backfill: { days: 90 }, // Your backfill period
          tags: ['app-7689'], // Your application/submission number
        },
      }).open();
      ```
    </Tab>
  </Tabs>
</Accordion>

<Tip>
  Use `tags` to associate connections with your internal identifiers like
  application numbers (`app-7689`) or policy numbers (`policy-1234`).
</Tip>

### Configuring historical data for Underwriting

To assess risk, you'll typically need historical telematics data. The **backfill period** determines how much historical data Terminal retrieves from the provider.

You can configure backfill in two ways:

1. **Per-link**: Set `backfill_days` or `backfill.days` when creating the connection (shown above)
2. **Application-level default**: Configure a default backfill period in your Terminal dashboard settings

<Note>
  Historical data availability varies by provider. See the [Provider
  Explorer](/providers/explorer) for details on history available for backfill.
</Note>

For details on how to access backfilled data once the connection is established, see the [Data Ingestion](#data-ingestion) section below.

## Connection Lifecycle

Managing connection events is critical for insurance workflows. Use webhooks to automate responses to connection state changes.

### Handling Connection Completion

When a fleet successfully connects their telematics provider, Terminal sends a `connection.completed` webhook. Use this to:

* Record that the fleet has connected telematics for the quote
* Update your internal systems with the connection details
* Send a confirmation to the fleet

<Accordion title="View code">
  ```ts theme={null}
  // Webhook handler for connection.completed
  app.post('/webhooks/terminal', async (req, res) => {
    const event = req.body;

    if (event.type === 'connection.completed') {
      const { connection } = event.detail;

      // Find application number from tags (e.g., 'app-7689')
      const appTag = connection.tags?.find((t) => t.startsWith('app-'));
      const applicationNumber = appTag?.replace('app-', '');

      // Record that fleet has connected telematics
      await recordTelematicsConnected({
        applicationNumber,
        connectionId: connection.id,
        provider: connection.provider.name,
        connectedAt: event.timestamp,
      });

      // Notify your team or the fleet
      await notifyQuoteTeam({
        applicationNumber,
        message: 'Fleet has connected telematics - ready for underwriting',
      });

      // Optionally send confirmation to the fleet
      await sendFleetConfirmation({
        email: getFleetEmail(applicationNumber),
        subject: 'Telematics Connected Successfully',
        message:
          'Your telematics data is now connected for your insurance quote.',
      });
    }

    res.status(200).send('OK');
  });
  ```
</Accordion>

### Handling Disconnections

When a connection becomes disconnected (credentials expire, provider access revoked, etc.), Terminal sends a `connection.disconnected` webhook. For active policies, this creates a compliance gap—notify the fleet promptly to reconnect.

<Accordion title="View code">
  ```ts theme={null}
  if (event.type === 'connection.disconnected') {
    const { connection } = event.detail;

    // Check if this is an active policy (automatic sync = post-bind)
    if (connection.syncMode === 'automatic') {
      // Find policy number from tags (e.g., 'policy-1234')
      const policyTag = connection.tags?.find((t) => t.startsWith('policy-'));
      const policyNumber = policyTag?.replace('policy-', '');

      // Send urgent notification to insured with reconnection link
      await notifyInsured({
        email: getInsuredEmail(policyNumber),
        subject: 'Action Required: Reconnect Your Telematics',
        body: 'Your telematics connection has been disconnected. Please reconnect to stay compliant with your policy.',
        reconnectUrl: connection.linkUrl,
        priority: 'high',
      });

      // Flag the policy for compliance review
      await flagPolicyForReview({
        policyNumber,
        reason: 'telematics_disconnected',
      });
    }
  }
  ```
</Accordion>

### Key Webhook Events for Insurance

| Event                     | Trigger                                     | Recommended Action                         |
| ------------------------- | ------------------------------------------- | ------------------------------------------ |
| `connection.completed`    | Fleet completes telematics connection       | Record connection, notify team/fleet       |
| `connection.disconnected` | Connection credentials become invalid       | Notify insured to reconnect for compliance |
| `connection.reconnected`  | Previously disconnected connection restored | Resume monitoring, clear compliance flags  |

See the [Webhooks Guide](/terminal-platform/webhooks) for setup instructions and the [Webhook Events Reference](/api-reference/webhook-events/overview) for detailed payload schemas.

***

## Policy Binding Transition

When a quote is accepted and the policy is bound, transition the connection from **Manual** to **Automatic** sync mode. This enables continuous data synchronization for ongoing risk monitoring and claims support.

<Accordion title="View code">
  ```bash theme={null}
  curl --request PATCH \
    --url https://api.withterminal.com/tsp/v1/connections/current \
    --header 'Authorization: Bearer {SECRET_KEY}' \
    --header 'Connection-Token: {CONNECTION_TOKEN}' \
    --header 'Content-Type: application/json' \
    --data '{
      "syncMode": "automatic",
      "tags": ["policy-1234"]
    }'
  ```
</Accordion>

This API call:

1. Switches sync mode from manual to automatic for continuous data updates
2. Adds a policy tag to the connection for future reference (the application tag remains)

**Example: Policy Binding Workflow**

<Accordion title="View code">
  ```ts theme={null}
  async function bindPolicy(applicationNumber: string, policyNumber: string) {
    // Find the connection by application tag
    const connections = await fetch(
      `https://api.withterminal.com/tsp/v1/connections?tag=app-${applicationNumber}`,
      { headers: { Authorization: `Bearer ${SECRET_KEY}` } },
    );

    const connection = connections.data[0];

    // Transition connection for post-bind monitoring
    await fetch('https://api.withterminal.com/tsp/v1/connections/current', {
      method: 'PATCH',
      headers: {
        Authorization: `Bearer ${SECRET_KEY}`,
        'Connection-Token': connection.token,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        syncMode: 'automatic',
        tags: [...connection.tags, `policy-${policyNumber}`], // Add policy tag
      }),
    });

    // Record the transition in your system
    await recordPolicyBound({
      applicationNumber,
      policyNumber,
      connectionId: connection.id,
      boundAt: new Date().toISOString(),
    });
  }
  ```
</Accordion>

### Post-Bind Monitoring

With automatic sync enabled, Terminal continuously updates connection data. Use this for:

**Ongoing Risk Monitoring**

* Monitor safety events for policy risk assessment
* Track driver behavior trends over the policy period
* Identify high-risk vehicles or drivers

**Claims Support**

* Access historical vehicle locations for incident verification
* Review driver HOS logs around claim dates
* Retrieve safety event footage via camera media endpoints

***

## Data Ingestion

Terminal provides two methods for ingesting telematics data into your systems. Both support initial backfills (historical data after connection) and incremental updates (ongoing data).

### Option 1: Data Delivery (Recommended for Insurance)

For insurance use cases, we recommend using [S3 Data Delivery](/destinations/s3). This approach:

* **Simplifies pipeline architecture**: Data arrives in your S3 bucket automatically
* **Handles scale efficiently**: Batch deliveries are more efficient than individual API calls
* **Provides complete data ownership**: All data is stored in your AWS account
* **Supports both backfills and incremental updates**: Automatic triggers for both scenarios

#### How Data Delivery Works

**Initial Backfill**: When a connection completes its first sync, Terminal automatically triggers a delivery of all historical data (based on your configured backfill period) to your S3 bucket.

**Incremental Updates**: On your configured schedule (hourly, daily, etc.), Terminal delivers all new and updated data across your connections.

#### Handling Delivery Events

Listen for delivery webhooks to trigger your data processing pipeline:

<Accordion title="View code">
  ```ts theme={null}
  if (event.type === 'delivery.completed') {
    const { delivery, destination } = event.detail;

    // Trigger ETL pipeline to process new S3 objects
    await triggerETLPipeline({
      deliveryId: delivery.id,
      connectionIds: delivery.connectionIds,
      destinationId: destination.id,
      // Data is already in your S3 bucket
    });
  }
  ```
</Accordion>

<Tip>
  Configure your S3 destination with daily scheduled deliveries for post-bind
  monitoring. The initial backfill happens automatically when connections
  complete their first sync.
</Tip>

### Option 2: API

For more control over data access or lower-volume use cases, query the API directly. The API approach gives you flexibility to fetch exactly the data you need, when you need it.

**Backfill Data**: After a connection completes its first sync, query endpoints like `/vehicles`, `/safety/events`, and `/trips` with date filters to retrieve historical data for underwriting risk assessment.

**Incremental Updates**: For ongoing monitoring, use the `modifiedAfter` query parameter to fetch only new or updated records since your last sync. This is efficient for keeping your systems in sync without re-fetching all data.

For complete implementation details, code examples, and best practices for API-based data syncing, see the [How to Sync Data](/guides/syncing-data) guide.

## First Notice of Loss & Claims Investigation

When a claim is filed, Terminal provides access to critical data for First Notice of Loss (FNOL) and claims investigation workflows. This includes crash detection, camera footage, and detailed safety event data.

### Safety Events & Crash Reports

Terminal's [Safety Events](/models/safety-event) capture incidents detected by telematics devices, including harsh braking, collisions, speeding, and other driver behavior events. These events are invaluable for claims investigation. For a deeper dive on crash detection capabilities and provider support, see [Crash Reports](/terminal-platform/crash-reports).

**Key capabilities:**

* **Crash detection**: Many telematics providers detect collisions and report them as safety events with severity indicators
* **Event details**: Access timestamp, location, speed, and g-force data for each event
* **Driver context**: Link events to specific drivers and vehicles

**Accessing safety events via API:**

<Accordion title="View code">
  ```ts theme={null}
  // Get safety events for a specific vehicle around a claim date
  const claimDate = '2024-03-15';
  const startDate = new Date(claimDate);
  startDate.setDate(startDate.getDate() - 1); // Day before
  const endDate = new Date(claimDate);
  endDate.setDate(endDate.getDate() + 1); // Day after

  const safetyEvents = await fetch(
    `https://api.withterminal.com/tsp/v1/safety/events?vehicleIds=${vehicleId}&startedAfter=${startDate.toISOString()}&startedBefore=${endDate.toISOString()}`,
    {
      headers: {
        Authorization: `Bearer ${SECRET_KEY}`,
        'Connection-Token': connectionToken,
      },
    },
  );

  // Filter for crash events
  const crashEvents = safetyEvents.data.filter((event) =>
    ['crash', 'near_crash'].includes(event.type),
  );
  ```
</Accordion>

### Camera Media

For connections with camera-equipped telematics devices, Terminal provides access to video footage and images captured during safety events. This is critical for accident reconstruction and liability determination.

**Key capabilities:**

* **Event footage**: Video clips captured before, during, and after safety events
* **Multiple camera views**: Access road-facing, driver-facing, and cabin camera footage when available
* **Timestamp correlation**: Camera media is linked to specific safety events for easy retrieval

**Accessing camera media via API:**

<Accordion title="View code">
  ```ts theme={null}
  // Get camera media for a specific safety event
  const cameraMedia = await fetch(
    `https://api.withterminal.com/tsp/v1/safety/events/${safetyEventId}/camera-media`,
    {
      headers: {
        Authorization: `Bearer ${SECRET_KEY}`,
        'Connection-Token': connectionToken,
      },
    },
  );

  // Access media URLs for review
  const media = await cameraMedia.json();

  if (media.frontFacing?.videoUrl) {
    console.log(`Front-facing camera: ${media.frontFacing.videoUrl}`);
  }

  if (media.rearFacing?.videoUrl) {
    console.log(`Rear-facing camera: ${media.rearFacing.videoUrl}`);
  }
  ```
</Accordion>

<Note>
  Camera media availability depends on the telematics provider and device
  capabilities. See [Camera Media](/models/camera-media) for details on the data
  model.
</Note>

### Safety Event Webhooks

Subscribe to `safety_event.added` webhooks to receive real-time notifications when new safety events are recorded. This enables proactive claims handling—you can be notified of potential incidents before a claim is even filed.

<Accordion title="View code">
  ```ts theme={null}
  // Webhook handler for safety_event.added
  if (event.type === 'safety_event.added') {
    const { safetyEvent, connection } = event.detail;

    // Check if this is a severe event that may indicate a claim
    const severeTypes = ['crash', 'near_crash'];
    const isSevere = severeTypes.includes(safetyEvent.type);

    if (isSevere) {
      // Find policy number from tags
      const policyTag = connection.tags?.find((t) => t.startsWith('policy-'));
      const policyNumber = policyTag?.replace('policy-', '');

      // Alert claims team of potential incident
      await alertClaimsTeam({
        policyNumber,
        eventType: safetyEvent.type,
        timestamp: safetyEvent.startedAt,
        vehicle: safetyEvent.vehicle,
        location: safetyEvent.startLocation,
        severity: 'high',
      });
    }
  }
  ```
</Accordion>

### Dashboard Access

The Terminal dashboard provides a visual interface for reviewing safety events and camera media without writing code. Claims adjusters can:

* **Browse safety events**: Filter by date, vehicle, driver, or event type
* **Watch camera footage**: Play back video clips directly in the browser
* **Export data**: Download event details and media for claims files
* **View event locations**: See where incidents occurred on a map

This is particularly useful for claims teams who need quick access to telematics data without API integration.

***

## Offboarding

When a quote is rejected or an account is cancelled, archive the connection to stop data syncing and clean up resources.

### Archiving Connections

Mark a connection as archived when it's no longer needed:

<Accordion title="View code">
  ```bash theme={null}
  curl --request PATCH \
    --url https://api.withterminal.com/tsp/v1/connections/current \
    --header 'Authorization: Bearer {SECRET_KEY}' \
    --header 'Connection-Token: {CONNECTION_TOKEN}' \
    --header 'Content-Type: application/json' \
    --data '{
      "status": "archived"
    }'
  ```
</Accordion>

**Example: Quote Rejection Workflow**

<Accordion title="View code">
  ```ts theme={null}
  async function handleQuoteRejected(applicationNumber: string) {
    // Find the connection by application tag
    const connections = await fetch(
      `https://api.withterminal.com/tsp/v1/connections?tag=app-${applicationNumber}`,
      { headers: { Authorization: `Bearer ${SECRET_KEY}` } },
    );

    const connection = connections.data[0];

    if (connection) {
      // Archive the connection
      await fetch('https://api.withterminal.com/tsp/v1/connections/current', {
        method: 'PATCH',
        headers: {
          Authorization: `Bearer ${SECRET_KEY}`,
          'Connection-Token': connection.token,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          status: 'archived',
        }),
      });

      // Record the archival in your system
      await recordConnectionArchived({
        applicationNumber,
        connectionId: connection.id,
        reason: 'quote_rejected',
        archivedAt: new Date().toISOString(),
      });
    }
  }
  ```
</Accordion>

**Example: Policy Cancellation Workflow**

<Accordion title="View code">
  ```ts theme={null}
  async function handlePolicyCancelled(policyNumber: string) {
    // Find the connection by policy tag
    const connections = await fetch(
      `https://api.withterminal.com/tsp/v1/connections?tag=policy-${policyNumber}`,
      { headers: { Authorization: `Bearer ${SECRET_KEY}` } },
    );

    const connection = connections.data[0];

    if (connection) {
      // Archive the connection
      await fetch('https://api.withterminal.com/tsp/v1/connections/current', {
        method: 'PATCH',
        headers: {
          Authorization: `Bearer ${SECRET_KEY}`,
          'Connection-Token': connection.token,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          status: 'archived',
        }),
      });

      // Record the archival in your system
      await recordConnectionArchived({
        policyNumber,
        connectionId: connection.id,
        reason: 'policy_cancelled',
        archivedAt: new Date().toISOString(),
      });
    }
  }
  ```
</Accordion>

<Tip>
  Archiving a connection stops all data syncing and deliveries. The historical
  data remains available in your systems for reference but no new data will be
  collected.
</Tip>

***

## Complete Webhook Reference

Here's a summary of all webhook events relevant to insurance workflows:

| Event                     | Trigger                                     | Recommended Action                    |
| ------------------------- | ------------------------------------------- | ------------------------------------- |
| `connection.completed`    | Fleet completes telematics connection       | Record connection, notify team/fleet  |
| `connection.disconnected` | Connection credentials become invalid       | Notify insured with reconnection link |
| `connection.reconnected`  | Previously disconnected connection restored | Resume data monitoring                |
| `sync.completed`          | Data sync finishes successfully             | Trigger data ingestion (API approach) |
| `sync.failed`             | Data sync encounters an error               | Alert operations team                 |
| `delivery.completed`      | S3 data delivery completes                  | Trigger ETL pipeline                  |
| `delivery.failed`         | S3 delivery fails                           | Alert operations team                 |
| `vehicle.added`           | New vehicle detected in fleet               | Update or compare to policy           |
| `vehicle.removed`         | Vehicle removed from fleet                  | Update or compare to policy           |
| `driver.added`            | New driver detected in fleet                | Update or compare to policy           |
| `driver.removed`          | Driver removed from fleet                   | Update or compare to policy           |
| `safety_event.added`      | New safety event recorded                   | Update risk assessment                |

***

## Full Sequence Diagram

```mermaid theme={null}
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#e5e7eb', 'primaryTextColor':'#111827', 'primaryBorderColor':'#9ca3af', 'lineColor':'#6b7280', 'secondaryColor':'#f3f4f6', 'tertiaryColor':'#f9fafb'}}}%%
sequenceDiagram
    participant Fleet
    participant Insurer
    participant Terminal

    Note over Fleet,Terminal: Pre-Bind / Underwriting
    Insurer->>Fleet: Send Consent Flow link
    Fleet->>Terminal: Connect telematics account via Consent Flow
    Terminal->>Insurer: Webhook: connection.completed
    Insurer->>Fleet: Notify fleet of successful connection
    Terminal->>Terminal: Sync historical data for backfill period
    Terminal->>Insurer: Deliver historical data
    Terminal->>Insurer: Webhook: delivery.completed
    Insurer->>Insurer: Ingest and process data for underwriting
    Insurer->>Fleet: Provide quote

    Note over Fleet,Terminal: Policy Binding
    Fleet->>Insurer: Accept quote
    Insurer->>Terminal: Update syncMode to automatic, add policy tag

    Note over Fleet,Terminal: Post-Bind Monitoring
    loop Continuous Monitoring
        Terminal->>Terminal: Incrementally ingest telematics data
        Terminal->>Insurer: Deliver incremental data
        Terminal->>Insurer: Webhook: delivery.completed
        Insurer->>Insurer: Ingest data for risk monitoring
    end

    Note over Fleet,Terminal: Claims / FNOL
    Terminal->>Insurer: Webhook: safety_event.added (collision detected)
    Insurer->>Insurer: Alert claims team, access camera media
    Insurer->>Terminal: Query safety events and media for investigation

    Note over Fleet,Terminal: Disconnection Handling
    Terminal->>Insurer: Webhook: connection.disconnected
    Insurer->>Fleet: Send reconnection notification (compliance)
    Fleet->>Terminal: Reconnect via Consent Flow
    Terminal->>Insurer: Webhook: connection.reconnected
    Terminal->>Terminal: Incrementally ingest telematics data

    Note over Fleet,Terminal: Offboarding
    alt Quote Rejected
        Insurer->>Terminal: Archive connection (status: archived)
    else Policy Cancelled
        Insurer->>Terminal: Archive connection (status: archived)
    end

```

***

## Next Steps

* [Set up webhooks](/terminal-platform/webhooks) for event-driven automation
* [Configure S3 delivery](/destinations/s3) for automated data replication
* [Learn how to sync data](/guides/syncing-data) for API-based ingestion patterns
* [Explore the API reference](/api-reference/authentication) to query telematics data
* [Review custom identifiers](/terminal-platform/custom-identifiers) for connection organization
