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.
Bookovia JavaScript SDK
The official JavaScript SDK for the Bookovia Telematics API provides seamless integration for web applications and Node.js backends with universal compatibility.Features
- ✅ Universal Compatibility - Works in browser and Node.js environments
- ✅ Promise-based API - Modern async/await and Promise support
- ✅ Automatic Retries - Built-in retry logic with exponential backoff
- ✅ Request/Response Transformation - Automatic JSON handling
- ✅ TypeScript Definitions - Full TypeScript support included
- ✅ Lightweight - Minimal dependencies and small bundle size
Installation
npm
npm install @bookovia/javascript-sdk
yarn
yarn add @bookovia/javascript-sdk
CDN (Browser)
<script src="https://unpkg.com/@bookovia/javascript-sdk@latest/dist/bookovia.min.js"></script>
Quick Start
Initialize the Client
// ES6 Modules
import Bookovia from '@bookovia/javascript-sdk';
// CommonJS
const Bookovia = require('@bookovia/javascript-sdk');
// Initialize client
const client = new Bookovia('bkv_live_your_api_key_here');
// With custom configuration
const client = new Bookovia('bkv_live_your_api_key_here', {
baseUrl: 'https://api.bookovia.com/v1',
timeout: 30000,
retryCount: 3,
debug: false
});
Browser Usage
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@bookovia/javascript-sdk@latest/dist/bookovia.min.js"></script>
</head>
<body>
<script>
const client = new Bookovia('bkv_live_your_api_key_here');
// Your code here
</script>
</body>
</html>
Start a Trip
async function startTrip() {
try {
const trip = await client.trips.start({
vehicleId: 'vehicle_123',
driverId: 'driver_456',
startLocation: {
latitude: 40.7128,
longitude: -74.0060
},
metadata: {
purpose: 'delivery',
route: 'downtown'
}
});
console.log('Trip started:', trip.tripId);
return trip;
} catch (error) {
console.error('Failed to start trip:', error);
}
}
Upload Location Data
async function uploadLocations(tripId) {
const locations = [
{
latitude: 40.7128,
longitude: -74.0060,
timestamp: new Date().toISOString(),
speed: 35,
heading: 180
},
{
latitude: 40.7130,
longitude: -74.0058,
timestamp: new Date(Date.now() + 30000).toISOString(),
speed: 42,
heading: 175
}
];
try {
await client.locations.batchUpload({
tripId: tripId,
locations: locations
});
console.log('Locations uploaded successfully');
} catch (error) {
console.error('Failed to upload locations:', error);
}
}
API Reference
Client Configuration
const client = new Bookovia(apiKey, {
baseUrl: 'https://api.bookovia.com/v1', // API base URL
timeout: 30000, // Request timeout in milliseconds
retryCount: 3, // Number of retry attempts
retryDelay: 1000, // Initial retry delay in milliseconds
debug: false, // Enable debug logging
defaultHeaders: {}, // Additional headers for all requests
// Request/Response interceptors
requestInterceptor: (config) => config,
responseInterceptor: (response) => response
});
Trip Management
User Trip Queries
// Get all active trips for a user
const activeTrips = await client.getUserActiveTrips('user_123');
console.log(`User has ${activeTrips.data.count} active trips`);
// Get trip history for a user
const completedTrips = await client.getUserTripHistory('user_123', 'completed');
const allHistory = await client.getUserTripHistory('user_123'); // defaults to completed
Organization Trip Queries
// Get all active trips for an organization
const orgActiveTrips = await client.getOrgActiveTrips('org_123');
console.log(`Organization has ${orgActiveTrips.data.count} active trips`);
// Get trip history for an organization
const orgHistory = await client.getOrgTripHistory('org_123', 'completed');
const cancelledTrips = await client.getOrgTripHistory('org_123', 'cancelled');
Vehicle Trip Queries
// Get all active trips for a vehicle
const vehicleActiveTrips = await client.getVehicleActiveTrips('vehicle_123');
// Get trip history for a vehicle
const vehicleHistory = await client.getVehicleTripHistory('vehicle_123', 'completed');
Legacy Methods
// Get trip details
const trip = await client.trips.get('tripId');
// Get trip summary with analytics
const summary = await client.trips.getSummary('tripId');
Location Services
// Upload single location
await client.locations.upload({
tripId: 'trip_123',
latitude: 40.7128,
longitude: -74.0060,
timestamp: new Date().toISOString(),
speed: 35,
heading: 180,
accuracy: 5 // Optional
});
// Batch upload locations
await client.locations.batchUpload({
tripId: 'trip_123',
locations: [
{
latitude: 40.7128,
longitude: -74.0060,
timestamp: '2024-04-13T10:30:00Z',
speed: 35,
heading: 180
}
// ... more locations
]
});
// Get route for trip
const route = await client.locations.getRoute('tripId');
// Find nearby locations
const nearby = await client.locations.findNearby({
latitude: 40.7128,
longitude: -74.0060,
radius: 1000 // meters
});
Safety Analytics
// Get safety score
const score = await client.safety.getScore({
tripId: 'trip_123', // OR
driverId: 'driver_456', // OR
vehicleId: 'vehicle_123',
dateRange: { // Optional
start: '2024-01-01',
end: '2024-01-31'
}
});
// Analyze driving behavior
const analysis = await client.safety.analyzeBehavior({
tripId: 'trip_123'
});
// Get harsh events
const events = await client.safety.getHarshEvents({
tripId: 'trip_123', // Optional
eventType: 'harsh_braking', // Optional
severity: 'medium', // Optional
limit: 50
});
// Get crash risk assessment
const risk = await client.safety.getCrashRisk({
driverId: 'driver_456',
timeframe: '30days'
});
Fleet Management
// Get fleet overview
const overview = await client.fleet.getOverview();
// List vehicles
const vehicles = await client.fleet.getVehicles({
status: 'active', // Optional
limit: 100
});
// Get vehicle utilization
const utilization = await client.fleet.getUtilization({
vehicleId: 'vehicle_123', // Optional
timeframe: '7days'
});
// Get fleet optimization suggestions
const optimization = await client.fleet.getOptimization({
fleetId: 'fleet_456'
});
Data Types
Trip Object
{
tripId: 'trip_1234567890',
vehicleId: 'vehicle_123',
driverId: 'driver_456',
status: 'active', // active | completed | paused | cancelled
startTime: '2024-04-13T10:30:00Z',
endTime: null,
startLocation: {
latitude: 40.7128,
longitude: -74.0060,
address: 'New York, NY'
},
endLocation: null,
analytics: {
distanceKm: 45.7,
durationMinutes: 67,
maxSpeedKmh: 85,
avgSpeedKmh: 42,
idleTimeMinutes: 12,
locationsCount: 892,
eventsCount: 3,
safetyScore: 87,
ecoScore: 92
},
metadata: {
purpose: 'delivery',
route: 'downtown'
}
}
Location Point
{
latitude: 40.7128,
longitude: -74.0060,
timestamp: '2024-04-13T10:30:00Z',
speed: 35, // km/h
heading: 180, // degrees (0-360)
accuracy: 5, // meters
altitude: 10 // meters (optional)
}
Error Handling
The SDK throws specific error types for different scenarios:try {
const trip = await client.trips.start({
vehicleId: 'vehicle_123'
});
} catch (error) {
if (error instanceof Bookovia.AuthenticationError) {
console.error('Authentication failed:', error.message);
// Handle auth error (check API key)
} else if (error instanceof Bookovia.ValidationError) {
console.error('Validation error:', error.message);
console.error('Invalid fields:', error.fields);
// Handle validation error
} else if (error instanceof Bookovia.RateLimitError) {
console.error('Rate limit exceeded, retry after:', error.retryAfter);
// Handle rate limiting
} else if (error instanceof Bookovia.NotFoundError) {
console.error('Resource not found:', error.message);
// Handle not found error
} else {
console.error('Unexpected error:', error);
}
}
Error Types
// Available error classes
Bookovia.AuthenticationError // 401 - Invalid API key
Bookovia.ValidationError // 400 - Invalid request data
Bookovia.NotFoundError // 404 - Resource not found
Bookovia.RateLimitError // 429 - Rate limit exceeded
Bookovia.ServerError // 500+ - Server errors
Bookovia.NetworkError // Network connectivity issues
Advanced Usage
Custom Request Interceptors
const client = new Bookovia('your-api-key', {
requestInterceptor: (config) => {
// Add custom headers
config.headers['X-Custom-Header'] = 'custom-value';
// Log requests in debug mode
if (process.env.NODE_ENV === 'development') {
console.log('Request:', config);
}
return config;
},
responseInterceptor: (response) => {
// Log response times
console.log('Response time:', response.responseTime, 'ms');
return response;
}
});
Retry Logic with Custom Backoff
async function startTripWithRetry(client, tripData, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await client.trips.start(tripData);
} catch (error) {
lastError = error;
// Don't retry for certain error types
if (error instanceof Bookovia.AuthenticationError ||
error instanceof Bookovia.ValidationError) {
throw error;
}
if (attempt < maxRetries) {
const delay = Math.pow(2, attempt - 1) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
console.log(`Retry attempt ${attempt} after ${delay}ms`);
}
}
}
throw lastError;
}
Real-time Location Streaming
class LocationTracker {
constructor(client) {
this.client = client;
this.intervalId = null;
}
start(tripId, intervalMs = 30000) {
this.intervalId = setInterval(async () => {
try {
// Get current location (browser geolocation API)
const position = await this.getCurrentPosition();
await this.client.locations.upload({
tripId: tripId,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
timestamp: new Date().toISOString(),
speed: position.coords.speed || 0,
heading: position.coords.heading || 0,
accuracy: position.coords.accuracy
});
console.log('Location uploaded successfully');
} catch (error) {
console.error('Failed to upload location:', error);
}
}, intervalMs);
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
getCurrentPosition() {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 30000
});
});
}
}
// Usage
const tracker = new LocationTracker(client);
tracker.start('trip_123', 30000); // Upload every 30 seconds
Browser Integration
<!DOCTYPE html>
<html>
<head>
<title>Bookovia Fleet Tracker</title>
<script src="https://unpkg.com/@bookovia/javascript-sdk@latest/dist/bookovia.min.js"></script>
</head>
<body>
<div id="status">Initializing...</div>
<button id="startTrip">Start Trip</button>
<button id="stopTrip" disabled>Stop Trip</button>
<script>
const client = new Bookovia('bkv_live_your_api_key');
let currentTrip = null;
let tracker = null;
document.getElementById('startTrip').onclick = async () => {
try {
currentTrip = await client.trips.start({
vehicleId: 'web_vehicle_001',
metadata: { source: 'web_app' }
});
document.getElementById('status').textContent =
`Trip started: ${currentTrip.tripId}`;
document.getElementById('startTrip').disabled = true;
document.getElementById('stopTrip').disabled = false;
// Start location tracking
startLocationTracking();
} catch (error) {
alert('Failed to start trip: ' + error.message);
}
};
document.getElementById('stopTrip').onclick = async () => {
try {
if (tracker) {
clearInterval(tracker);
tracker = null;
}
await client.trips.stop(currentTrip.tripId);
document.getElementById('status').textContent = 'Trip completed';
document.getElementById('startTrip').disabled = false;
document.getElementById('stopTrip').disabled = true;
} catch (error) {
alert('Failed to stop trip: ' + error.message);
}
};
function startLocationTracking() {
tracker = setInterval(async () => {
if (navigator.geolocation && currentTrip) {
navigator.geolocation.getCurrentPosition(async (position) => {
try {
await client.locations.upload({
tripId: currentTrip.tripId,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
timestamp: new Date().toISOString(),
speed: position.coords.speed || 0,
accuracy: position.coords.accuracy
});
document.getElementById('status').textContent =
`Tracking trip: ${currentTrip.tripId}`;
} catch (error) {
console.error('Location upload failed:', error);
}
});
}
}, 30000); // Every 30 seconds
}
</script>
</body>
</html>
Testing
Jest Testing Example
// __tests__/bookovia.test.js
import Bookovia from '@bookovia/javascript-sdk';
// Mock the SDK for testing
jest.mock('@bookovia/javascript-sdk');
describe('Bookovia SDK', () => {
let client;
beforeEach(() => {
client = new Bookovia('test_api_key');
});
test('should start a trip successfully', async () => {
const mockTrip = {
tripId: 'trip_123',
vehicleId: 'vehicle_123',
status: 'active'
};
client.trips.start.mockResolvedValue(mockTrip);
const result = await client.trips.start({
vehicleId: 'vehicle_123'
});
expect(result).toEqual(mockTrip);
expect(client.trips.start).toHaveBeenCalledWith({
vehicleId: 'vehicle_123'
});
});
test('should handle authentication errors', async () => {
const authError = new Bookovia.AuthenticationError('Invalid API key');
client.trips.start.mockRejectedValue(authError);
await expect(client.trips.start({ vehicleId: 'test' }))
.rejects.toThrow('Invalid API key');
});
});
Examples
Fleet Dashboard
class FleetDashboard {
constructor(apiKey) {
this.client = new Bookovia(apiKey);
this.activeTrips = new Map();
}
async initialize() {
// Load active trips
const trips = await this.client.trips.list({ status: 'active' });
trips.trips.forEach(trip => {
this.activeTrips.set(trip.tripId, trip);
});
console.log(`Loaded ${this.activeTrips.size} active trips`);
}
async startFleetTrip(vehicleId, driverId) {
try {
const trip = await this.client.trips.start({
vehicleId: vehicleId,
driverId: driverId,
metadata: {
fleet: 'main_fleet',
startedBy: 'dashboard'
}
});
this.activeTrips.set(trip.tripId, trip);
console.log(`Started trip ${trip.tripId} for vehicle ${vehicleId}`);
return trip;
} catch (error) {
console.error(`Failed to start trip for ${vehicleId}:`, error);
throw error;
}
}
async getFleetStatus() {
const status = {
totalVehicles: 0,
activeTrips: this.activeTrips.size,
totalDistance: 0,
avgSafetyScore: 0
};
for (const trip of this.activeTrips.values()) {
if (trip.analytics) {
status.totalDistance += trip.analytics.distanceKm || 0;
status.avgSafetyScore += trip.analytics.safetyScore || 0;
}
}
if (this.activeTrips.size > 0) {
status.avgSafetyScore /= this.activeTrips.size;
}
return status;
}
}
// Usage
const dashboard = new FleetDashboard('bkv_live_your_api_key');
await dashboard.initialize();
const status = await dashboard.getFleetStatus();
console.log('Fleet Status:', status);
Support
- npm Package: @bookovia/javascript-sdk
- GitHub: github.com/bookovia/javascript-sdk
- Issues: GitHub Issues
- Email: support@bookovia.com
Ready to integrate? Check out our quickstart guide and API reference for more examples.