Skip to main content
GET
/
v1
/
analytics
/
safety-score
/
{trip_id}
Get Safety Score
curl --request GET \
  --url https://api.bookovia.com/v1/analytics/safety-score/{trip_id} \
  --header 'X-API-Key: <api-key>'
{
  "error": {
    "code": "trip_not_found",
    "message": "Trip not found or insufficient data for safety analysis",
    "details": "Trip must have at least 50 location points and 10 minutes duration"
  }
}

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 Safety Score endpoint provides comprehensive safety analysis for completed trips, including detailed scoring methodology, driving behavior breakdown, risk factors, and personalized improvement recommendations for drivers and fleet managers.
Safety scores are calculated using advanced machine learning models that analyze acceleration patterns, braking behavior, cornering, speed compliance, and contextual factors.

Authentication

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

Request

trip_id
string
required
Unique identifier for the trip to analyze safety score for
include_breakdown
boolean
default:"true"
Whether to include detailed scoring breakdown by category
include_benchmarks
boolean
default:"false"
Whether to include comparison with driver/fleet/industry averages
include_recommendations
boolean
default:"true"
Whether to include personalized safety improvement recommendations
compare_period
string
Time period for benchmark comparison: “30d”, “90d”, “1y”

Request Example

curl -X GET "https://api.bookovia.com/v1/analytics/safety-score/trip_1234567890abcdef?include_breakdown=true&include_benchmarks=true" \
  -H "X-API-Key: bkv_test_your_api_key_here"

Response

trip_id
string
Unique identifier for the analyzed trip
overall_safety_score
integer
Overall safety score from 0-100 (higher is safer)
score_grade
string
Letter grade representation: “A”, “B”, “C”, “D”, “F”
analysis_timestamp
string
ISO 8601 timestamp when the safety analysis was completed
trip_context
object
Contextual information that influenced the safety score
score_breakdown
object
Detailed breakdown of safety score components
risk_factors
array
Identified risk factors that negatively impacted the score

Success Response

{
  "trip_id": "trip_1234567890abcdef",
  "overall_safety_score": 87,
  "score_grade": "B+",
  "analysis_timestamp": "2024-04-13T12:20:00Z",
  "trip_context": {
    "distance_km": 45.2,
    "duration_minutes": 105,
    "road_types": {
      "highway_percentage": 65.0,
      "city_percentage": 30.0,
      "rural_percentage": 5.0
    },
    "weather_conditions": "clear",
    "traffic_density": "moderate",
    "time_of_day": "morning",
    "day_of_week": "tuesday"
  },
  "score_breakdown": {
    "acceleration_score": 92,
    "braking_score": 78,
    "cornering_score": 95,
    "speed_compliance_score": 85,
    "following_distance_score": 88,
    "distraction_score": 91,
    "consistency_score": 89,
    "score_weights": {
      "acceleration": 0.15,
      "braking": 0.20,
      "cornering": 0.15,
      "speed_compliance": 0.25,
      "following_distance": 0.15,
      "distraction": 0.05,
      "consistency": 0.05
    }
  },
  "risk_factors": [
    {
      "factor_id": "harsh_braking_001",
      "factor_type": "harsh_braking",
      "severity": "moderate",
      "frequency": 2,
      "score_impact": 8,
      "description": "Two moderate harsh braking events detected during city driving",
      "timestamps": [
        "2024-04-13T11:22:15Z",
        "2024-04-13T11:45:30Z"
      ],
      "locations": [
        {"latitude": 40.7298, "longitude": -73.9973},
        {"latitude": 40.7412, "longitude": -73.9897}
      ]
    },
    {
      "factor_id": "speed_exceed_001",
      "factor_type": "speed_violation",
      "severity": "low",
      "frequency": 1,
      "score_impact": 5,
      "description": "Brief speed limit exceedance on highway segment",
      "duration_seconds": 45,
      "max_speed_over_limit": 8,
      "location": {"latitude": 40.7589, "longitude": -73.9612}
    }
  ],
  "positive_indicators": [
    {
      "indicator_type": "smooth_acceleration",
      "frequency": 18,
      "score_bonus": 3,
      "description": "Consistently smooth acceleration patterns"
    },
    {
      "indicator_type": "safe_following_distance",
      "percentage": 92.5,
      "score_bonus": 2,
      "description": "Maintained safe following distance 92.5% of the time"
    }
  ],
  "benchmarks": {
    "vs_driver_average": {
      "driver_id": "driver_456",
      "driver_30d_average": 82,
      "comparison": "+5 points above driver average",
      "percentile": 68
    },
    "vs_fleet_average": {
      "organization_id": "org_abcdef123456",
      "fleet_30d_average": 79,
      "comparison": "+8 points above fleet average",
      "percentile": 75
    },
    "vs_industry_benchmark": {
      "industry_segment": "commercial_delivery",
      "industry_average": 76,
      "comparison": "+11 points above industry average",
      "percentile": 82
    }
  },
  "recommendations": [
    {
      "category": "braking",
      "priority": "high",
      "title": "Improve braking smoothness",
      "description": "Focus on earlier brake application to avoid harsh braking events, especially in city driving conditions",
      "specific_actions": [
        "Increase following distance in traffic",
        "Anticipate traffic light changes",
        "Practice gradual deceleration techniques"
      ],
      "potential_improvement": "+5-8 safety score points"
    },
    {
      "category": "speed_management", 
      "priority": "medium",
      "title": "Maintain consistent speed compliance",
      "description": "Monitor speed more closely on highway segments to avoid exceeding limits",
      "specific_actions": [
        "Use cruise control on highways when appropriate",
        "Set speed limit alerts on navigation system",
        "Practice checking speedometer regularly"
      ],
      "potential_improvement": "+2-4 safety score points"
    }
  ],
  "improvement_potential": {
    "maximum_possible_score": 95,
    "current_score": 87,
    "improvement_points_available": 8,
    "primary_focus_areas": ["braking", "speed_compliance"],
    "estimated_timeline": "2-4 weeks with focused practice"
  }
}

Error Responses

{
  "error": {
    "code": "trip_not_found",
    "message": "Trip not found or insufficient data for safety analysis",
    "details": "Trip must have at least 50 location points and 10 minutes duration"
  }
}

SDK Examples

import Bookovia from '@bookovia/javascript-sdk';

const client = new Bookovia('bkv_test_your_api_key');

// Get comprehensive safety analysis
const safetyAnalysis = await client.analytics.getSafetyScore('trip_1234567890abcdef', {
  includeBreakdown: true,
  includeBenchmarks: true,
  includeRecommendations: true,
  comparePeriod: '30d'
});

console.log(`Safety Score: ${safetyAnalysis.overallSafetyScore} (${safetyAnalysis.scoreGrade})`);

// Display risk factors
console.log('\nRisk Factors:');
safetyAnalysis.riskFactors.forEach(risk => {
  console.log(`- ${risk.factorType}: ${risk.description} (Impact: -${risk.scoreImpact} points)`);
});

// Display improvement recommendations
console.log('\nRecommendations for improvement:');
safetyAnalysis.recommendations.forEach(rec => {
  console.log(`${rec.priority.toUpperCase()}: ${rec.title}`);
  console.log(`  ${rec.description}`);
  console.log(`  Potential improvement: ${rec.potentialImprovement}`);
});

// Driver performance dashboard
const createSafetyDashboard = async (driverTrips) => {
  const analyses = await Promise.all(
    driverTrips.map(tripId => 
      client.analytics.getSafetyScore(tripId, { includeBenchmarks: true })
    )
  );
  
  const averageScore = analyses.reduce((sum, a) => sum + a.overallSafetyScore, 0) / analyses.length;
  const trendDirection = analyses.length > 1 ? 
    (analyses[analyses.length - 1].overallSafetyScore > analyses[0].overallSafetyScore ? 'improving' : 'declining') : 
    'stable';
  
  return {
    averageScore,
    trendDirection,
    totalTrips: analyses.length,
    riskPatterns: analyses.flatMap(a => a.riskFactors)
      .reduce((acc, risk) => {
        acc[risk.factorType] = (acc[risk.factorType] || 0) + 1;
        return acc;
      }, {}),
    recommendations: analyses.flatMap(a => a.recommendations)
      .filter(rec => rec.priority === 'high')
  };
};

// Fleet safety comparison
const compareFleetSafety = async (vehicleTrips) => {
  const fleetAnalyses = {};
  
  for (const [vehicleId, tripIds] of Object.entries(vehicleTrips)) {
    const vehicleScores = await Promise.all(
      tripIds.map(tripId => client.analytics.getSafetyScore(tripId))
    );
    
    fleetAnalyses[vehicleId] = {
      averageScore: vehicleScores.reduce((sum, s) => sum + s.overallSafetyScore, 0) / vehicleScores.length,
      totalTrips: vehicleScores.length,
      riskCount: vehicleScores.reduce((sum, s) => sum + s.riskFactors.length, 0)
    };
  }
  
  // Rank vehicles by safety performance
  const rankings = Object.entries(fleetAnalyses)
    .sort(([,a], [,b]) => b.averageScore - a.averageScore)
    .map(([vehicleId, analysis], index) => ({
      rank: index + 1,
      vehicleId,
      ...analysis
    }));
  
  return {
    fleetAverage: Object.values(fleetAnalyses)
      .reduce((sum, a) => sum + a.averageScore, 0) / Object.keys(fleetAnalyses).length,
    rankings,
    topPerformer: rankings[0],
    needsImprovement: rankings.filter(r => r.averageScore < 75)
  };
};

Use Cases

Driver Performance Management

// Comprehensive driver performance management system
class DriverPerformanceManager {
  constructor(client) {
    this.client = client;
    this.performanceThresholds = {
      excellent: 90,
      good: 80,
      acceptable: 70,
      needsImprovement: 60
    };
  }
  
  async generateDriverPerformanceReport(driverId, evaluationPeriod = '30d') {
    // Get all trips for the driver in the period
    const trips = await this.getDriverTrips(driverId, evaluationPeriod);
    
    // Analyze safety scores for all trips
    const safetyAnalyses = await Promise.all(
      trips.map(trip => 
        this.client.analytics.getSafetyScore(trip.trip_id, {
          includeBreakdown: true,
          includeBenchmarks: true,
          includeRecommendations: true
        })
      )
    );
    
    // Generate comprehensive performance analysis
    return this.generatePerformanceAnalysis(driverId, safetyAnalyses, evaluationPeriod);
  }
  
  generatePerformanceAnalysis(driverId, safetyAnalyses, period) {
    const scores = safetyAnalyses.map(a => a.overallSafetyScore);
    const currentAverage = scores.reduce((sum, score) => sum + score, 0) / scores.length;
    
    // Trend analysis
    const trendAnalysis = this.calculatePerformanceTrend(scores);
    
    // Behavior analysis
    const behaviorAnalysis = this.analyzeBehaviorPatterns(safetyAnalyses);
    
    // Risk assessment
    const riskAssessment = this.assessRiskProfile(safetyAnalyses);
    
    // Generate coaching recommendations
    const coachingPlan = this.generateCoachingPlan(behaviorAnalysis, riskAssessment);
    
    return {
      driverId,
      evaluationPeriod: period,
      overallPerformance: {
        currentScore: Math.round(currentAverage),
        grade: this.calculateGrade(currentAverage),
        performanceLevel: this.getPerformanceLevel(currentAverage),
        trend: trendAnalysis,
        totalTripsAnalyzed: safetyAnalyses.length
      },
      behaviorAnalysis,
      riskAssessment,
      coachingPlan,
      benchmarkComparison: this.extractBenchmarkData(safetyAnalyses),
      nextEvaluationDate: this.calculateNextEvaluationDate(currentAverage, trendAnalysis.direction)
    };
  }
  
  calculatePerformanceTrend(scores) {
    if (scores.length < 3) return { direction: 'insufficient_data', stability: 'unknown' };
    
    const recentScores = scores.slice(-Math.min(5, scores.length));
    const olderScores = scores.slice(0, Math.min(5, scores.length));
    
    const recentAverage = recentScores.reduce((sum, s) => sum + s, 0) / recentScores.length;
    const olderAverage = olderScores.reduce((sum, s) => sum + s, 0) / olderScores.length;
    
    const difference = recentAverage - olderAverage;
    const standardDeviation = this.calculateStandardDeviation(scores);
    
    let direction;
    if (Math.abs(difference) < 2) direction = 'stable';
    else if (difference > 0) direction = 'improving';
    else direction = 'declining';
    
    return {
      direction,
      changePoints: Math.abs(Math.round(difference)),
      stability: standardDeviation < 5 ? 'consistent' : standardDeviation < 10 ? 'variable' : 'volatile',
      volatility: standardDeviation
    };
  }
  
  analyzeBehaviorPatterns(safetyAnalyses) {
    const behaviors = {
      acceleration: [],
      braking: [],
      cornering: [],
      speedCompliance: [],
      followingDistance: [],
      distraction: []
    };
    
    // Aggregate behavior scores
    safetyAnalyses.forEach(analysis => {
      const breakdown = analysis.scoreBreakdown;
      behaviors.acceleration.push(breakdown.accelerationScore);
      behaviors.braking.push(breakdown.brakingScore);
      behaviors.cornering.push(breakdown.corneringScore);
      behaviors.speedCompliance.push(breakdown.speedComplianceScore);
      behaviors.followingDistance.push(breakdown.followingDistanceScore);
      behaviors.distraction.push(breakdown.distractionScore);
    });
    
    // Calculate averages and identify strengths/weaknesses
    const behaviorSummary = {};
    const strengths = [];
    const weaknesses = [];
    
    for (const [behavior, scores] of Object.entries(behaviors)) {
      const average = scores.reduce((sum, s) => sum + s, 0) / scores.length;
      const trend = this.calculateBehaviorTrend(scores);
      
      behaviorSummary[behavior] = {
        averageScore: Math.round(average),
        trend: trend.direction,
        consistency: trend.consistency,
        grade: this.calculateGrade(average)
      };
      
      if (average >= 85) strengths.push(behavior);
      if (average < 75) weaknesses.push(behavior);
    }
    
    return {
      behaviorScores: behaviorSummary,
      strengths,
      weaknesses,
      primaryFocusArea: weaknesses[0] || null
    };
  }
  
  assessRiskProfile(safetyAnalyses) {
    const allRiskFactors = [];
    const riskFrequency = {};
    let totalScoreImpact = 0;
    
    safetyAnalyses.forEach(analysis => {
      analysis.riskFactors.forEach(risk => {
        allRiskFactors.push(risk);
        riskFrequency[risk.factorType] = (riskFrequency[risk.factorType] || 0) + 1;
        totalScoreImpact += risk.scoreImpact;
      });
    });
    
    // Calculate risk metrics
    const avgRisksPerTrip = allRiskFactors.length / safetyAnalyses.length;
    const mostCommonRisk = Object.entries(riskFrequency)
      .sort(([,a], [,b]) => b - a)[0];
    
    // Determine risk level
    let riskLevel;
    if (avgRisksPerTrip < 0.5) riskLevel = 'low';
    else if (avgRisksPerTrip < 1.5) riskLevel = 'moderate';
    else if (avgRisksPerTrip < 3) riskLevel = 'high';
    else riskLevel = 'critical';
    
    return {
      riskLevel,
      avgRisksPerTrip: Math.round(avgRisksPerTrip * 10) / 10,
      totalRiskIncidents: allRiskFactors.length,
      avgScoreImpactPerTrip: Math.round(totalScoreImpact / safetyAnalyses.length),
      mostCommonRiskType: mostCommonRisk ? mostCommonRisk[0] : null,
      riskFrequencyDistribution: riskFrequency,
      recentRiskTrend: this.analyzeRiskTrend(safetyAnalyses)
    };
  }
  
  generateCoachingPlan(behaviorAnalysis, riskAssessment) {
    const coachingPlan = {
      priority: this.determineCoachingPriority(behaviorAnalysis, riskAssessment),
      focusAreas: [],
      recommendedActions: [],
      timeframe: '',
      expectedImprovement: ''
    };
    
    // Identify focus areas based on weaknesses
    if (behaviorAnalysis.weaknesses.length > 0) {
      coachingPlan.focusAreas = behaviorAnalysis.weaknesses.slice(0, 2); // Top 2 weaknesses
    }
    
    // Add risk-based focus areas
    if (riskAssessment.mostCommonRiskType) {
      coachingPlan.focusAreas.push(`risk_reduction_${riskAssessment.mostCommonRiskType}`);
    }
    
    // Generate specific actions
    coachingPlan.recommendedActions = this.generateSpecificActions(
      behaviorAnalysis.weaknesses,
      riskAssessment.mostCommonRiskType,
      coachingPlan.priority
    );
    
    // Set timeframe and expectations
    switch (coachingPlan.priority) {
      case 'high':
        coachingPlan.timeframe = '2-3 weeks';
        coachingPlan.expectedImprovement = '5-10 points';
        break;
      case 'medium':
        coachingPlan.timeframe = '1-2 months';
        coachingPlan.expectedImprovement = '3-7 points';
        break;
      case 'low':
        coachingPlan.timeframe = '2-3 months';
        coachingPlan.expectedImprovement = '2-5 points';
        break;
    }
    
    return coachingPlan;
  }
  
  // Helper methods
  calculateStandardDeviation(values) {
    const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
    const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
    return Math.sqrt(variance);
  }
  
  calculateGrade(score) {
    if (score >= 95) return 'A+';
    if (score >= 90) return 'A';
    if (score >= 85) return 'B+';
    if (score >= 80) return 'B';
    if (score >= 75) return 'C+';
    if (score >= 70) return 'C';
    if (score >= 65) return 'D+';
    if (score >= 60) return 'D';
    return 'F';
  }
  
  getPerformanceLevel(score) {
    if (score >= this.performanceThresholds.excellent) return 'excellent';
    if (score >= this.performanceThresholds.good) return 'good';
    if (score >= this.performanceThresholds.acceptable) return 'acceptable';
    return 'needs_improvement';
  }
}

// Usage example
const performanceManager = new DriverPerformanceManager(client);

const driverReport = await performanceManager.generateDriverPerformanceReport('driver_456', '30d');

console.log('Driver Performance Report');
console.log('========================');
console.log(`Current Score: ${driverReport.overallPerformance.currentScore} (${driverReport.overallPerformance.grade})`);
console.log(`Performance Level: ${driverReport.overallPerformance.performanceLevel}`);
console.log(`Trend: ${driverReport.overallPerformance.trend.direction}`);

console.log('\nBehavior Analysis:');
console.log(`Strengths: ${driverReport.behaviorAnalysis.strengths.join(', ') || 'None identified'}`);
console.log(`Weaknesses: ${driverReport.behaviorAnalysis.weaknesses.join(', ') || 'None identified'}`);

console.log('\nRisk Assessment:');
console.log(`Risk Level: ${driverReport.riskAssessment.riskLevel}`);
console.log(`Avg Risks per Trip: ${driverReport.riskAssessment.avgRisksPerTrip}`);

console.log('\nCoaching Recommendations:');
console.log(`Priority: ${driverReport.coachingPlan.priority}`);
console.log(`Timeframe: ${driverReport.coachingPlan.timeframe}`);
console.log(`Expected Improvement: ${driverReport.coachingPlan.expectedImprovement}`);

Best Practices

Score Interpretation

  • 90-100: Excellent safety performance, role model driver
  • 80-89: Good performance with minor areas for improvement
  • 70-79: Average performance requiring moderate coaching
  • 60-69: Below average, needs focused improvement plan
  • Below 60: Poor performance requiring immediate intervention
Consider external factors that affect scoring:
  • Weather conditions and visibility
  • Traffic density and road conditions
  • Time of day and driver fatigue levels
  • Vehicle type and load characteristics

Integration Strategies

// Regular safety score monitoring
const monitorFleetSafety = async () => {
  const activeTrips = await client.trips.list({ status: 'completed', limit: 100 });
  
  for (const trip of activeTrips.trips) {
    const safetyScore = await client.analytics.getSafetyScore(trip.trip_id);
    
    if (safetyScore.overallSafetyScore < 70) {
      await alertFleetManager(trip.driver_id, safetyScore);
    }
  }
};

setInterval(monitorFleetSafety, 24 * 60 * 60 * 1000); // Daily
  • Use safety scores for personalized training programs
  • Track improvement over time with trend analysis
  • Implement recognition programs for high performers
  • Create peer mentoring based on safety expertise

Next Steps

Behavior Analysis

Deep dive into specific driving behaviors and patterns

Harsh Events

Analyze specific safety events and incidents

Crash Risk

Predictive crash risk assessment and prevention

Fleet Management

Fleet-wide safety analytics and management