Skip to main content

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:
SectionDescriptionWhen to Use
Pre-Bind / UnderwritingConnecting fleets and accessing historical data for risk assessmentIf you’re evaluating telematics data before binding policies
Connection LifecycleHandling connection events, disconnections, and compliance monitoringAll implementations—critical for maintaining data access
Policy Binding TransitionSwitching from manual to automatic sync when a policy is boundIf you start with underwriting and transition to ongoing monitoring
Data IngestionS3 delivery and API options for getting data into your systemsAll implementations—choose based on volume and architecture
First Notice of Loss & ClaimsAccessing crash reports, camera footage, and safety events for claimsIf you handle claims investigation or FNOL workflows
OffboardingArchiving connections when quotes are rejected or policies cancelledAll 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. Use Terminal Link 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.
The hosted flow is a URL you can send directly to fleets via email, SMS, or any messaging channel:
https://link.withterminal.com/?syncMode=manual&backfill_days=90&tags=app-7689&key={PUBLISHABLE_KEY}
Use tags to associate connections with your internal identifiers like application numbers (app-7689) or policy numbers (policy-1234).

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
Historical data availability varies by provider. See Supported Providers for details on history available for backfill.
For details on how to access backfilled data once the connection is established, see the 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
// 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');
});

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.
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',
    });
  }
}

Key Webhook Events for Insurance

EventTriggerRecommended Action
connection.completedFleet completes telematics connectionRecord connection, notify team/fleet
connection.disconnectedConnection credentials become invalidNotify insured to reconnect for compliance
connection.reconnectedPreviously disconnected connection restoredResume monitoring, clear compliance flags
See the Webhooks Guide for setup instructions and the Webhook Events Reference 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.
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"]
  }'
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
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(),
  });
}

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). For insurance use cases, we recommend using S3 Data Delivery. 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:
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
  });
}
Configure your S3 destination with daily scheduled deliveries for post-bind monitoring. The initial backfill happens automatically when connections complete their first sync.

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 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 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. 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:
// 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),
);

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:
// 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}`);
}
Camera media availability depends on the telematics provider and device capabilities. See Camera Media for details on the data model.

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.
// 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',
    });
  }
}

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:
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"
  }'
Example: Quote Rejection Workflow
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(),
    });
  }
}
Example: Policy Cancellation Workflow
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(),
    });
  }
}
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.

Complete Webhook Reference

Here’s a summary of all webhook events relevant to insurance workflows:
EventTriggerRecommended Action
connection.completedFleet completes telematics connectionRecord connection, notify team/fleet
connection.disconnectedConnection credentials become invalidNotify insured with reconnection link
connection.reconnectedPreviously disconnected connection restoredResume data monitoring
sync.completedData sync finishes successfullyTrigger data ingestion (API approach)
sync.failedData sync encounters an errorAlert operations team
delivery.completedS3 data delivery completesTrigger ETL pipeline
delivery.failedS3 delivery failsAlert operations team
vehicle.addedNew vehicle detected in fleetUpdate or compare to policy
vehicle.removedVehicle removed from fleetUpdate or compare to policy
driver.addedNew driver detected in fleetUpdate or compare to policy
driver.removedDriver removed from fleetUpdate or compare to policy
safety_event.addedNew safety event recordedUpdate risk assessment

Full Sequence Diagram


Next Steps