Skip to main content

Overview

The Drivers API provides endpoints to query and manage driver data, including real-time location, Hours of Service (HOS), and editable profile information. Database Tables:
  • drivers - Real-time driver data from Terminal API (polled every 60s)
  • driver_profiles - Editable profile data (user-managed)
Data Sources:
  • Terminal API (/tsp/v1/drivers) - Provides driver identity, contact info, status
  • Terminal API (/tsp/v1/hos/available-time) - Provides HOS data (synced every 5 minutes)
  • Frontend - User edits to profiles

Get Current Drivers

GET /api/drivers/current

Get all drivers from the database with staleness metadata. This is a DB-first read endpoint.
limit
integer
default:"None"
Maximum number of drivers to return (1-1000)
since
string
default:"None"
ISO 8601 timestamp - only return drivers updated after this time
Response (200 OK):
{
  "dataSource": "db",
  "refreshInProgress": false,
  "staleMs": 15000,
  "maxLastUpdatedAt": "2025-11-17T19:30:00.000Z",
  "items": [
    {
      "terminal_driver_id": "drv_01D8ZQFGHVJ858NBF2Q7DV9MNC",
      "source_id": "M72323",
      "provider": "geotab",
      "status": "active",
      "first_name": "John",
      "middle_name": null,
      "last_name": "Smith",
      "driver_name": "John Smith",
      "email": "[email protected]",
      "phone": "+1234567890",
      "username": "jsmith",
      "license_state": "TX",
      "license_number": "DL123456",
      "groups": ["grp_west", "grp_hazmat"],
      "lane_preference": ["Chicago-LA", "NYC-Miami"],
      "dispatcher": "Jane Doe",
      "updated_at": "2025-11-17T19:30:00.000Z"
    }
  ],
  "itemsCount": 1
}
How it works:
  1. Query Database: Uses get_drivers_snapshot() which queries the drivers table
  2. Window Function: Uses PostgreSQL ROW_NUMBER() to get latest row per terminal_driver_id
  3. Name Construction: Combines first_name, middle_name, last_name into driver_name
  4. Staleness Check: Compares current time to max(updated_at) across all drivers
  5. Stale Threshold: Data is considered stale if staleMs > DRIVER_MAX_STALE_SECONDS * 1000 (default: 300 seconds)
Response Headers:
HeaderDescription
X-Data-SourceAlways db
X-Stale-MsMilliseconds since most recent update
ETagMD5 hash of payload
Last-ModifiedHTTP date of most recent update
Retry-AfterSeconds to wait (only on 202)

Real-Time Driver Stream

GET /api/drivers/stream

Server-Sent Events (SSE) endpoint for real-time driver updates. Event Types:
Sent immediately when client connects.
event: connected
data: {"client_id": "uuid-string"}
retry: 5000
Sent when new driver data is available.
event: driver_update
data: {
  "drivers": [...],
  "drivers_count": 25,
  "polled_at": "2025-11-17T19:30:00.000Z"
}
How it works:
  1. Connection: Client connects, receives unique client_id
  2. Initial Data: Immediately reads from drivers table via get_drivers_snapshot() and sends first driver_update
  3. Polling Wake-up: Notifies DriverPollingService to switch to fast polling
  4. Live Updates: Receives broadcasts from DriverPollingService after each poll
  5. Heartbeat: Sends :heartbeat every 30 seconds
Data Source:
  • DriverPollingService polls Terminal API /tsp/v1/drivers every 60 seconds
  • Upserts results to drivers table via upsert_drivers_batch()
  • Broadcasts to SSE clients

Hours of Service (HOS)

GET /api/drivers/hos/available-time

Get HOS available time for a driver. Reads from the drivers table (HOS columns synced every 5 minutes).
terminal_driver_id
string
required
Terminal driver ID (e.g., drv_01D8ZQFGHVJ858NBF2Q7DV9MNC)
Response:
{
  "results": [
    {
      "provider": "geotab",
      "driver": "drv_01D8ZQFGHVJ858NBF2Q7DV9MNC",
      "currentStatus": "driving",
      "availableTime": {
        "cycle": 252000000,
        "shift": 50400000,
        "drive": 39600000,
        "break": 28800000
      }
    }
  ],
  "next": null
}
Field Descriptions:
FieldDescription
cycleTotal remaining time for current cycle (e.g., 70 hours) in milliseconds
shiftTotal remaining time for current shift (e.g., 14 hours) in milliseconds
driveTotal remaining drive time for shift (e.g., 11 hours) in milliseconds
breakTime before next break required (e.g., 8 hours) in milliseconds
How it works:
  1. Queries drivers table by terminal_driver_id
  2. Reads HOS columns: hos_current_status, hos_cycle_available_ms, hos_shift_available_ms, hos_drive_available_ms, hos_break_available_ms
  3. Returns 404 if driver not found or HOS data incomplete
Data Source:
  • HOS data is synced from Terminal API /tsp/v1/hos/available-time by DriverHOSSyncService
  • Runs every 5 minutes automatically
  • Updates drivers table HOS columns via update_drivers_hos_batch()

POST /api/drivers/hos/sync

Manually trigger HOS data sync from Terminal API. Response:
{
  "fetched": 45,
  "updated": 45,
  "errors": 0
}
How it works:
  1. Calls DriverHOSSyncService.sync_hos_available_time()
  2. Fetches HOS data from Terminal API for all drivers with terminal_driver_id
  3. Updates drivers table HOS columns in batch

Driver Location

PATCH /api/drivers/

Update location for a specific driver.
terminal_driver_id
string
required
Terminal driver ID (e.g., drv_01D8ZQFGHVJ858NBF2Q7DV9MNC)
Request Body:
{
  "latitude": 40.7128,
  "longitude": -74.0060,
  "location_updated_at": "2025-11-17T19:30:00.000Z"
}
Response:
{
  "terminal_driver_id": "drv_01D8ZQFGHVJ858NBF2Q7DV9MNC",
  "latitude": 40.7128,
  "longitude": -74.0060,
  "location_updated_at": "2025-11-17T19:30:00.000Z",
  "updated_at": "2025-11-17T19:35:00.000Z"
}
How it works:
  1. Updates drivers table columns: latitude, longitude, location_updated_at, updated_at
  2. Uses SQL UPDATE with WHERE on terminal_driver_id
  3. Returns 404 if driver not found

GET /api/drivers/source//location

Get driver location by source_id (McLeod driver ID).
source_id
string
required
Driver source ID from provider system (e.g., M72323)
Response:
{
  "source_id": "M72323",
  "latitude": 40.7128,
  "longitude": -74.0060,
  "location_updated_at": "2025-11-17T19:30:00.000Z"
}
How it works:
  1. Queries drivers table by source_id column
  2. Returns latest row using window function
  3. Returns 404 if driver not found

Lane Preferences

PATCH /api/drivers//lane-preferences

Update lane preferences for a driver.
terminal_driver_id
string
required
Terminal driver ID (e.g., drv_01D8ZQFGHVJ858NBF2Q7DV9MNC)
Request Body:
{
  "lane_preference": ["Chicago-LA", "NYC-Miami"]
}
Pass empty array [] or null to clear preferences. Response:
{
  "terminal_driver_id": "drv_01D8ZQFGHVJ858NBF2Q7DV9MNC",
  "lane_preference": ["Chicago-LA", "NYC-Miami"],
  "updated_at": "2025-11-17T19:35:00.000Z"
}
How it works:
  1. Updates drivers.lane_preference column (PostgreSQL array)
  2. Returns 404 if driver not found

Driver Profiles

Driver profiles are stored in a separate driver_profiles table for user-editable data.

GET /api/drivers/profiles

Get all driver profiles. Response:
{
  "profiles": [
    {
      "id": 1,
      "terminal_driver_id": "drv_01D8ZQFGHVJ858NBF2Q7DV9MNC",
      "full_name": "John Smith",
      "phone_number": "+1234567890",
      "address": "123 Main St, Dallas, TX",
      "emergency_contact": "Jane Smith - 555-1234",
      "license_type": "A",
      "license_expiry_date": "2026-06-15",
      "hazmat_certification": "Valid",
      "medical_cert_expiry": "2025-12-01",
      "years_of_experience": 8,
      "lane_preference": "West Coast",
      "dispatcher": "Jane Doe",
      "operates_sunday": false,
      "operates_monday": true,
      "operates_tuesday": true,
      "operates_wednesday": true,
      "operates_thursday": true,
      "operates_friday": true,
      "operates_saturday": false,
      "driver_status": "Active",
      "created_at": "2025-01-15T10:00:00.000Z",
      "updated_at": "2025-11-17T19:30:00.000Z"
    }
  ],
  "count": 1
}
How it works:
  • Queries driver_profiles table, ordered by full_name
  • Returns all profile fields

GET /api/drivers/profile/

Get a single driver profile.
terminal_driver_id
string
required
Terminal driver ID (e.g., drv_01D8ZQFGHVJ858NBF2Q7DV9MNC)
Response: Same structure as single item in /profiles response.

PATCH /api/drivers/profile/

Update driver profile (partial updates supported).
terminal_driver_id
string
required
Terminal driver ID
Request Body (all fields optional):
{
  "full_name": "John A. Smith",
  "phone_number": "+1234567890",
  "address": "123 Main St, Dallas, TX",
  "emergency_contact": "Jane Smith - 555-1234",
  "license_type": "A",
  "license_expiry_date": "2026-06-15",
  "hazmat_certification": "Valid",
  "medical_cert_expiry": "2025-12-01",
  "years_of_experience": 8,
  "lane_preference": "West Coast",
  "dispatcher": "Jane Doe",
  "operates_sunday": false,
  "operates_monday": true,
  "driver_status": "Active"
}
Response: Updated profile object. How it works:
  1. Only updates fields provided in request body (partial update)
  2. Automatically sets updated_at timestamp
  3. Returns 404 if profile not found

POST /api/drivers/profile/backfill

Backfill driver_profiles table from drivers table. Creates profiles for drivers that don’t have one yet. Response:
{
  "total_drivers": 50,
  "profiles_created": 10,
  "profiles_skipped": 40,
  "errors": 0,
  "message": "Successfully created 10 new profiles, skipped 40 existing profiles from 50 drivers."
}
How it works:
  1. Queries all unique drivers from drivers table
  2. For each driver without a profile, creates new row in driver_profiles
  3. Copies: terminal_driver_id, full_name (from name parts), phone_number, dispatcher, driver_status
  4. Uses ON CONFLICT DO NOTHING - does NOT overwrite existing profiles

POST /api/drivers/profile/backfill-reset

⚠️ WARNING: Overwrites ALL existing profile data. Reset and backfill driver_profiles from drivers table. Creates new profiles and overwrites existing ones. Response:
{
  "total_drivers": 50,
  "profiles_created": 5,
  "profiles_overwritten": 45,
  "errors": 0,
  "message": "Successfully created 5 new profiles, overwrote 45 existing profiles from 50 drivers."
}
How it works:
  1. Queries all unique drivers from drivers table
  2. Uses ON CONFLICT DO UPDATE - overwrites ALL fields
  3. Resets editable fields (address, emergency_contact, etc.) to null/defaults
  4. User edits will be lost

Background Services

DriverPollingService

  • Interval: 60 seconds (when SSE clients connected), 300 seconds (idle)
  • Source: Terminal API /tsp/v1/drivers
  • Target: drivers table via upsert_drivers_batch()
  • Config: LOCATION_POLL_ENABLED=true

DriverHOSSyncService

  • Interval: Every 5 minutes
  • Source: Terminal API /tsp/v1/hos/available-time
  • Target: drivers table HOS columns via update_drivers_hos_batch()
  • Runs: Automatically as background task