Skip to main content
GET
/
v1
/
trips
/
{sessionId}
/
mileage
Get Real-Time Mileage
curl --request GET \
  --url https://api.bookovia.com/v1/trips/{sessionId}/mileage \
  --header 'X-API-Key: <api-key>'
{
  "success": true,
  "data": {
    "trip_id": "<string>",
    "status": "<string>",
    "total_miles": 123,
    "total_km": 123,
    "total_meters": 123,
    "data_points": 123,
    "avg_speed_kmh": 123,
    "max_speed_kmh": 123,
    "first_point_at": "<string>",
    "last_point_at": "<string>",
    "data_source": "<string>"
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.bookovia.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Get Real-Time Mileage endpoint returns the current distance traveled and trip analytics for an active trip. This endpoint queries the DuckDB WARM tier for trips less than 48 hours old, providing 10-30ms response times.
This endpoint calculates mileage from GPS data, not odometer readings. Distance is computed using the Haversine formula between consecutive GPS points uploaded via the GPS Batch endpoint.

Authentication

This endpoint requires authentication via API key in the X-API-Key header. Required permissions: trips:read

Path Parameters

sessionId
string
required
The trip ID to query

Request Example

curl https://api.bookovia.com/v1/trips/trip-abc-123/mileage \
  -H "X-API-Key: bkv_test_your_api_key_here"

Response

success
boolean
Whether the request was successful
data
object
Trip mileage and analytics data

Success Response

{
  "success": true,
  "data": {
    "trip_id": "trip-abc-123",
    "status": "recording",
    "total_miles": 15.327,
    "total_km": 24.664,
    "total_meters": 24664.0,
    "data_points": 180,
    "avg_speed_kmh": 48.5,
    "max_speed_kmh": 82.3,
    "first_point_at": "2026-04-29T12:00:00Z",
    "last_point_at": "2026-04-29T12:15:00Z",
    "data_source": "duckdb_parquet"
  }
}

Error Responses

404 Not Found

{
  "success": false,
  "error": "Trip not found"
}

400 Bad Request

{
  "success": false,
  "error": "Trip is not active (status: completed)"
}

How It Works

Query Strategy (Hybrid Approach)

The backend uses a hybrid query strategy based on trip age:

1. Recent Trips (Less than 48 hours old)

  • Source: DuckDB .duckdb file (WARM tier)
  • Query: SELECT SUM(distance_from_previous_meters) / 1609.34 FROM location_points WHERE trip_id = ?
  • Response Time: 10-30ms
  • Location: /data/telemetry/telemetry.duckdb

2. Older Trips (More than 48 hours old)

  • Source: DuckDB .duckdb + Parquet PVC (COLD tier)
  • Query: Queries both storage tiers and sums results
  • Response Time: 50-200ms
  • Location: /data/telemetry/location_points/year=YYYY/month=MM/day=DD/*.parquet

Distance Calculation

Distance is calculated using the Haversine formula:
For each consecutive pair of GPS points:
  distance = haversine(lat1, lng1, lat2, lng2)
  
Total Distance = SUM(all distances between consecutive points)
This provides GPS-based mileage which is:
  • ✅ More accurate than odometer readings
  • ✅ Works even when odometer is not available
  • ✅ Captures actual path traveled (not straight-line distance)

Performance

Response Times

Trip AgeStorage TierTypical Response TimeMax Expected
Less than 48 hoursDuckDB .duckdb10-30ms50ms
More than 48 hoursDuckDB + Parquet50-200ms500ms

Optimization Tips

  1. Poll Interval: Query every 10-30 seconds for live updates
  2. Caching: Cache results client-side for smooth UI updates
  3. Batch Queries: Use Trip Analytics endpoint for multiple metrics

Use Cases

Live Fleet Dashboard

// Update live mileage every 10 seconds
setInterval(async () => {
  const mileage = await client.trips.getMileage('trip-abc-123');
  updateDashboard({
    distance: mileage.data.total_miles,
    avgSpeed: mileage.data.avg_speed_kmh,
    dataPoints: mileage.data.data_points
  });
}, 10000);

Driver Mobile App

// Show live mileage to driver
Timer.periodic(Duration(seconds: 15), (timer) async {
  final mileage = await sdk.getCurrentTripMileage();
  
  setState(() {
    currentMiles = mileage['data']['total_miles'];
    currentSpeed = mileage['data']['avg_speed_kmh'];
  });
});

Delivery Tracking

# Check if driver has reached expected mileage
async def check_delivery_progress(trip_id, expected_miles):
    mileage = await client.trips.get_mileage(trip_id)
    
    if mileage['data']['total_miles'] >= expected_miles:
        await notify_customer("Driver is approaching delivery location")

Comparison with Stop Trip

EndpointUse CaseTrip StatusResponse SpeedMileage Source
Get MileageLive trackingActive (recording/paused)10-30msDuckDB query
Stop TripFinalize tripAny50-100msDuckDB query + Postgres update
Both endpoints use the same underlying DuckDB query, but Stop Trip also updates the Postgres trip record with the final mileage value.

Rate Limits

  • Standard: 60 requests per minute
  • Professional: 300 requests per minute
  • Enterprise: 1,000 requests per minute

Best Practices

Polling Strategy

// Good: Poll every 10-30 seconds
const pollMileage = setInterval(async () => {
  const mileage = await client.trips.getMileage(tripId);
  updateUI(mileage);
}, 15000); // 15 seconds

// Bad: Poll too frequently
// Don't poll faster than every 5 seconds

Error Handling

import asyncio

async def get_mileage_with_retry(trip_id, max_retries=3):
    for attempt in range(max_retries):
        try:
            return await client.trips.get_mileage(trip_id)
        except Exception as e:
            if attempt < max_retries - 1:
                await asyncio.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise

Caching

// Cache mileage results for smooth UI
let cachedMileage = null;
let lastFetch = 0;

async function getMileageWithCache(tripId) {
  const now = Date.now();
  
  // Return cached value if less than 10 seconds old
  if (cachedMileage && (now - lastFetch) < 10000) {
    return cachedMileage;
  }
  
  cachedMileage = await client.trips.getMileage(tripId);
  lastFetch = now;
  return cachedMileage;
}

Next Steps

Upload GPS Batch

Upload GPS points to enable mileage calculation

Stop Trip

Finalize trip and get final mileage

Trip Analytics

Get comprehensive trip analytics with vehicle details

Flutter SDK

Use the Flutter SDK for automatic mileage tracking