Skip to main content
GET
/
v1
/
trips
/
{sessionId}
/
with-analytics
Get Trip with Analytics
curl --request GET \
  --url https://api.bookovia.com/v1/trips/{sessionId}/with-analytics \
  --header 'X-API-Key: <api-key>'
{
  "success": true,
  "data": {
    "trip": {
      "id": "<string>",
      "org_id": "<string>",
      "vehicle_id": "<string>",
      "user_id": "<string>",
      "status": "<string>",
      "purpose": "<string>",
      "start_time": "<string>",
      "end_time": "<string>",
      "duration_seconds": 123,
      "distance_meters": 123
    },
    "analytics": {
      "total_gps_points": 123,
      "calculated_miles": 123,
      "calculated_km": 123,
      "avg_speed_kmh": 123,
      "max_speed_kmh": 123,
      "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 Trip with Analytics endpoint combines trip metadata from Postgres with calculated analytics from DuckDB, providing a complete view of the trip including GPS-derived metrics.
This endpoint performs a hybrid query: Trip metadata from Postgres + Analytics from DuckDB .duckdb file

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/with-analytics \
  -H "X-API-Key: bkv_test_your_api_key_here"

Response

success
boolean
Whether the request was successful
data
object
Combined trip and analytics data

Success Response

{
  "success": true,
  "data": {
    "trip": {
      "id": "trip-abc-123",
      "org_id": "org-456",
      "vehicle_id": "vehicle-789",
      "user_id": "user-321",
      "status": "recording",
      "purpose": "business",
      "start_time": "2026-04-29T12:00:00Z",
      "end_time": null,
      "duration_seconds": null,
      "distance_meters": null
    },
    "analytics": {
      "total_gps_points": 180,
      "calculated_miles": 15.327,
      "calculated_km": 24.664,
      "avg_speed_kmh": 48.5,
      "max_speed_kmh": 82.3,
      "data_source": "duckdb_parquet"
    }
  }
}

Error Responses

404 Not Found

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

How It Works

Two-Stage Query

1. Query Postgres for trip metadata
   ├─ Trip ID, org, vehicle, driver
   ├─ Status, purpose, timestamps
   └─ Basic distance/duration

2. Query DuckDB for GPS analytics  
   ├─ Total GPS points collected
   ├─ Accurate calculated distance
   ├─ Speed statistics
   └─ Time range of data

Why Two Databases?

Data TypeStorageReason
Trip MetadataPostgresTransactional data, ACID guarantees
GPS AnalyticsDuckDBFast aggregations on millions of points
DuckDB can calculate SUM(distance) across 1 million GPS points in 30ms, while Postgres would take 2-5 seconds for the same query.

Use Cases

Driver Performance Dashboard

async function getDriverPerformanceReport(tripId) {
  const trip = await client.trips.getWithAnalytics(tripId);
  
  return {
    driverId: trip.data.trip.user_id,
    tripDuration: trip.data.trip.duration_seconds,
    totalDistance: trip.data.analytics.calculated_miles,
    avgSpeed: trip.data.analytics.avg_speed_kmh,
    maxSpeed: trip.data.analytics.max_speed_kmh,
    dataQuality: trip.data.analytics.total_gps_points > 100 ? 'good' : 'poor'
  };
}

Fleet Management Report

async def generate_fleet_report(trip_ids):
    trips = []
    
    for trip_id in trip_ids:
        trip = await client.trips.get_with_analytics(trip_id)
        trips.append({
            'vehicle_id': trip['data']['trip']['vehicle_id'],
            'distance': trip['data']['analytics']['calculated_miles'],
            'avg_speed': trip['data']['analytics']['avg_speed_kmh'],
            'status': trip['data']['trip']['status']
        })
    
    return trips

Trip Validation

// Validate trip has enough GPS data
Future<bool> validateTripQuality(String tripId) async {
  final trip = await sdk.getTripWithAnalytics(tripId);
  final analytics = trip['data']['analytics'];
  
  // Need at least 100 GPS points for accurate mileage
  return analytics['total_gps_points'] >= 100;
}

Performance

OperationResponse TimeDetails
Postgres Query5-10msTrip metadata lookup (indexed by trip_id)
DuckDB Query10-30msAnalytics aggregation on location_points
Total15-40msParallel execution, returns combined result

Comparison with Other Endpoints

EndpointData ReturnedUse CaseResponse Time
Get Trip (Simple)Postgres metadata onlyBasic trip info5-10ms
Get Mileage (Hybrid)DuckDB analytics onlyLive distance tracking10-30ms
Get Trip with Analytics (Hybrid)Both Postgres + DuckDBComplete trip report15-40ms

Rate Limits

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

Best Practices

When to Use

Use this endpoint when:
  • Generating trip reports that need both metadata and analytics
  • Building comprehensive dashboards
  • Validating trip data quality
  • Exporting trip data with analytics
Don’t use when:
  • Only need live mileage → Use GET /mileage instead (faster)
  • Only need trip status → Use GET /trips/:id instead
  • Polling frequently → Cache results

Caching Strategy

// Cache analytics for 30 seconds (updates aren't that frequent)
const cache = new Map();

async function getTripWithAnalyticsCache d(tripId) {
  const cacheKey = `trip-analytics-${tripId}`;
  const cached = cache.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < 30000) {
    return cached.data;
  }
  
  const data = await client.trips.getWithAnalytics(tripId);
  cache.set(cacheKey, { data, timestamp: Date.now() });
  return data;
}

Next Steps

Get Real-Time Mileage

Get just the mileage without trip metadata (faster)

Fleet Analytics

View analytics across all vehicles

Driver Performance

View driver-specific performance metrics

Upload GPS Batch

Upload GPS data to power these analytics