Skip to main content

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 Go SDK

The official Go SDK for the Bookovia Telematics API provides a type-safe, high-performance client library for backend services, microservices, and enterprise integrations.

Features

  • Full Type Safety - Comprehensive structs and interfaces
  • Context Support - Built-in timeout and cancellation handling
  • Concurrent Operations - Goroutine-safe client with connection pooling
  • Automatic Retries - Configurable retry logic with exponential backoff
  • Error Handling - Detailed error types and messages
  • Performance Optimized - Efficient JSON marshaling and connection reuse

Installation

go get github.com/bookovia/go-sdk
Requirements: Go 1.19 or later

Quick Start

Initialize the Client

package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/bookovia/go-sdk"
)

func main() {
    // Initialize client with API key
    client := bookovia.NewClient("bkv_live_your_api_key_here")
    
    // Or with custom configuration
    client := bookovia.NewClient("bkv_live_your_api_key_here", &bookovia.Config{
        BaseURL:    "https://api.bookovia.com/v1",
        Timeout:    30 * time.Second,
        MaxRetries: 3,
    })
}

Start a Trip

func startTrip(client *bookovia.Client) {
    ctx := context.Background()
    
    trip, err := client.Trips.Start(ctx, &bookovia.StartTripRequest{
        VehicleID: "vehicle_123",
        DriverID:  "driver_456",
        StartLocation: &bookovia.Location{
            Latitude:  40.7128,
            Longitude: -74.0060,
        },
        Metadata: map[string]interface{}{
            "purpose": "delivery",
            "route":   "downtown",
        },
    })
    
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Trip started: %s\n", trip.TripID)
}

Upload Location Data

func uploadLocations(client *bookovia.Client, tripID string) {
    ctx := context.Background()
    
    locations := []*bookovia.LocationPoint{
        {
            Latitude:  40.7128,
            Longitude: -74.0060,
            Timestamp: time.Now(),
            Speed:     35,
            Heading:   180,
        },
        {
            Latitude:  40.7130,
            Longitude: -74.0058,
            Timestamp: time.Now().Add(30 * time.Second),
            Speed:     42,
            Heading:   175,
        },
    }
    
    err := client.Locations.BatchUpload(ctx, &bookovia.BatchUploadRequest{
        TripID:    tripID,
        Locations: locations,
    })
    
    if err != nil {
        log.Printf("Failed to upload locations: %v", err)
    }
}

API Reference

Client Configuration

type Config struct {
    BaseURL     string        // API base URL (default: https://api.bookovia.com/v1)
    Timeout     time.Duration // Request timeout (default: 30s)
    MaxRetries  int           // Maximum retry attempts (default: 3)
    RetryDelay  time.Duration // Initial retry delay (default: 1s)
    UserAgent   string        // Custom User-Agent header
    HTTPClient  *http.Client  // Custom HTTP client
}

Trip Management

Trip Lifecycle

// Start a new trip
func (c *Client) StartTrip(ctx context.Context, req *StartTripRequest) (*Trip, error)

// Stop an active trip  
func (c *Client) StopTrip(ctx context.Context, sessionID string) (*Trip, error)

// Pause an active trip
func (c *Client) PauseTrip(ctx context.Context, sessionID string) (*Trip, error)

// Resume a paused trip
func (c *Client) ResumeTrip(ctx context.Context, sessionID string) (*Trip, error)

Trip Information

// Get trip details
func (c *Client) GetTripDetails(ctx context.Context, tripID string) (*Trip, error)

// Get trip summary with analytics
func (c *Client) GetTripSummary(ctx context.Context, sessionID string) (map[string]interface{}, error)

// Export trip data in specified format
func (c *Client) ExportTrip(ctx context.Context, sessionID, format string) ([]byte, error)

// Update trip metadata
func (c *Client) UpdateTripMetadata(ctx context.Context, sessionID string, metadata map[string]interface{}) error

User Trip Queries

// Get all active trips for a user
func (c *Client) GetActiveTrips(ctx context.Context, userID string) ([]Trip, error)

// Get trip history for a user with optional status filter
func (c *Client) GetUserTripHistory(ctx context.Context, userID string, status string) ([]Trip, error)

Organization Trip Queries

// Get all active trips for an organization
func (c *Client) GetOrgActiveTrips(ctx context.Context, orgID string) ([]Trip, error)

// Get trip history for an organization with optional status filter
func (c *Client) GetOrgTripHistory(ctx context.Context, orgID string, status string) ([]Trip, error)

Vehicle Trip Queries

// Get all active trips for a vehicle
func (c *Client) GetVehicleActiveTrips(ctx context.Context, vehicleID string) ([]Trip, error)

// Get trip history for a vehicle with optional status filter
func (c *Client) GetVehicleTripHistory(ctx context.Context, vehicleID string, status string) ([]Trip, error)

Location Services

// Upload single location point
func (l *LocationService) Upload(ctx context.Context, req *LocationUploadRequest) error

// Batch upload multiple location points
func (l *LocationService) BatchUpload(ctx context.Context, req *BatchUploadRequest) error

// Get route for a trip
func (l *LocationService) GetRoute(ctx context.Context, tripID string) (*Route, error)

Safety Analytics

// Get safety score for a trip or driver
func (s *SafetyService) GetScore(ctx context.Context, req *SafetyScoreRequest) (*SafetyScore, error)

// Analyze driving behavior
func (s *SafetyService) AnalyzeBehavior(ctx context.Context, req *BehaviorAnalysisRequest) (*BehaviorAnalysis, error)

// Get harsh events
func (s *SafetyService) GetHarshEvents(ctx context.Context, filters *EventFilters) (*EventList, error)

Data Types

Core Structs

type Trip struct {
    TripID        string                 `json:"trip_id"`
    VehicleID     string                 `json:"vehicle_id"`
    DriverID      string                 `json:"driver_id,omitempty"`
    Status        TripStatus             `json:"status"`
    StartTime     time.Time              `json:"start_time"`
    EndTime       *time.Time             `json:"end_time,omitempty"`
    StartLocation *Location              `json:"start_location,omitempty"`
    EndLocation   *Location              `json:"end_location,omitempty"`
    Analytics     *TripAnalytics         `json:"analytics"`
    Metadata      map[string]interface{} `json:"metadata,omitempty"`
}

type Location struct {
    Latitude  float64 `json:"latitude"`
    Longitude float64 `json:"longitude"`
    Address   string  `json:"address,omitempty"`
}

type LocationPoint struct {
    Latitude  float64   `json:"latitude"`
    Longitude float64   `json:"longitude"`
    Timestamp time.Time `json:"timestamp"`
    Speed     float64   `json:"speed"`
    Heading   float64   `json:"heading"`
    Accuracy  float64   `json:"accuracy,omitempty"`
}

type TripAnalytics struct {
    DistanceKM       float64 `json:"distance_km"`
    DurationMinutes  int     `json:"duration_minutes"`
    MaxSpeedKMH      float64 `json:"max_speed_kmh"`
    AvgSpeedKMH      float64 `json:"avg_speed_kmh"`
    IdleTimeMinutes  int     `json:"idle_time_minutes"`
    LocationsCount   int     `json:"locations_count"`
    EventsCount      int     `json:"events_count"`
    SafetyScore      int     `json:"safety_score"`
    EcoScore         int     `json:"eco_score"`
}

Enums

type TripStatus string

const (
    TripStatusActive    TripStatus = "active"
    TripStatusCompleted TripStatus = "completed"
    TripStatusPaused    TripStatus = "paused"
    TripStatusCancelled TripStatus = "cancelled"
)

type EventType string

const (
    EventHarshAcceleration EventType = "harsh_acceleration"
    EventHarshBraking      EventType = "harsh_braking"
    EventHarshCornering    EventType = "harsh_cornering"
    EventSpeeding          EventType = "speeding"
    EventIdleExcessive     EventType = "idle_excessive"
)

Usage Examples

Query Active Trips

// Get all active trips for a user
func getUserActiveTrips(client *bookovia.Client, userID string) {
    ctx := context.Background()
    
    trips, err := client.GetActiveTrips(ctx, userID)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("User has %d active trips\n", len(trips))
    for _, trip := range trips {
        fmt.Printf("Trip %s: %s, %.2f km\n", 
            trip.ID, trip.Status, trip.DistanceMeters/1000)
    }
}

// Get all active trips for an organization
func getOrgActiveTrips(client *bookovia.Client, orgID string) {
    ctx := context.Background()
    
    trips, err := client.GetOrgActiveTrips(ctx, orgID)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Organization has %d active trips\n", len(trips))
}

// Get all active trips for a vehicle
func getVehicleActiveTrips(client *bookovia.Client, vehicleID string) {
    ctx := context.Background()
    
    trips, err := client.GetVehicleActiveTrips(ctx, vehicleID)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Vehicle has %d active trips\n", len(trips))
}

Query Trip History

// Get completed trips for a user
func getUserCompletedTrips(client *bookovia.Client, userID string) {
    ctx := context.Background()
    
    // Get completed trips (default)
    trips, err := client.GetUserTripHistory(ctx, userID, "completed")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("User has %d completed trips\n", len(trips))
    
    // Calculate total distance
    var totalDistance float64
    for _, trip := range trips {
        if trip.DistanceMeters != nil {
            totalDistance += *trip.DistanceMeters
        }
    }
    fmt.Printf("Total distance: %.2f km\n", totalDistance/1000)
}

// Get trip history for an organization with status filter
func getOrgTripHistory(client *bookovia.Client, orgID string) {
    ctx := context.Background()
    
    // Get all completed trips
    completedTrips, _ := client.GetOrgTripHistory(ctx, orgID, "completed")
    
    // Get all cancelled trips
    cancelledTrips, _ := client.GetOrgTripHistory(ctx, orgID, "cancelled")
    
    fmt.Printf("Completed: %d, Cancelled: %d\n", 
        len(completedTrips), len(cancelledTrips))
}

// Get trip history for a vehicle
func getVehicleTripHistory(client *bookovia.Client, vehicleID string) {
    ctx := context.Background()
    
    trips, err := client.GetVehicleTripHistory(ctx, vehicleID, "completed")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Vehicle has %d completed trips\n", len(trips))
}

Error Handling

The SDK provides specific error types for different scenarios:
// Handle different error types
trip, err := client.Trips.Start(ctx, req)
if err != nil {
    switch e := err.(type) {
    case *bookovia.AuthenticationError:
        log.Printf("Authentication failed: %v", e)
        // Handle auth error (check API key)
        
    case *bookovia.ValidationError:
        log.Printf("Validation error: %v", e)
        // Handle validation error (check request data)
        
    case *bookovia.RateLimitError:
        log.Printf("Rate limit exceeded, retry after: %v", e.RetryAfter)
        // Handle rate limiting (implement backoff)
        
    case *bookovia.NotFoundError:
        log.Printf("Resource not found: %v", e)
        // Handle not found (check resource ID)
        
    default:
        log.Printf("Unexpected error: %v", err)
        // Handle other errors
    }
}

Advanced Usage

Custom HTTP Client

// Use custom HTTP client with connection pooling
httpClient := &http.Client{
    Timeout: 60 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 10,
        IdleConnTimeout:     90 * time.Second,
    },
}

client := bookovia.NewClient("your-api-key", &bookovia.Config{
    HTTPClient: httpClient,
})

Concurrent Operations

func processTripsAsync(client *bookovia.Client, vehicleIDs []string) {
    var wg sync.WaitGroup
    tripChan := make(chan *bookovia.Trip, len(vehicleIDs))
    
    // Start trips concurrently
    for _, vehicleID := range vehicleIDs {
        wg.Add(1)
        go func(vID string) {
            defer wg.Done()
            
            trip, err := client.Trips.Start(context.Background(), &bookovia.StartTripRequest{
                VehicleID: vID,
            })
            
            if err != nil {
                log.Printf("Failed to start trip for vehicle %s: %v", vID, err)
                return
            }
            
            tripChan <- trip
        }(vehicleID)
    }
    
    wg.Wait()
    close(tripChan)
    
    // Process results
    for trip := range tripChan {
        fmt.Printf("Started trip: %s for vehicle: %s\n", trip.TripID, trip.VehicleID)
    }
}

Context with Timeout

func startTripWithTimeout(client *bookovia.Client) {
    // Create context with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    trip, err := client.Trips.Start(ctx, &bookovia.StartTripRequest{
        VehicleID: "vehicle_123",
    })
    
    if err != nil {
        if ctx.Err() == context.DeadlineExceeded {
            log.Println("Request timed out")
        } else {
            log.Printf("Request failed: %v", err)
        }
        return
    }
    
    fmt.Printf("Trip started: %s\n", trip.TripID)
}

Best Practices

Performance

  • Reuse Client Instances: Create one client instance per application
  • Use Context: Always pass context for timeout and cancellation control
  • Batch Operations: Use batch endpoints for multiple operations
  • Connection Pooling: Configure HTTP transport for high-throughput applications

Error Handling

// Implement retry logic with exponential backoff
func startTripWithRetry(client *bookovia.Client, req *bookovia.StartTripRequest, maxRetries int) (*bookovia.Trip, error) {
    var trip *bookovia.Trip
    var err error
    
    for attempt := 0; attempt <= maxRetries; attempt++ {
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        
        trip, err = client.Trips.Start(ctx, req)
        cancel()
        
        if err == nil {
            return trip, nil
        }
        
        // Check if error is retryable
        if rateLimitErr, ok := err.(*bookovia.RateLimitError); ok {
            time.Sleep(rateLimitErr.RetryAfter)
            continue
        }
        
        // For other retryable errors, use exponential backoff
        if attempt < maxRetries {
            delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second
            time.Sleep(delay)
        }
    }
    
    return nil, fmt.Errorf("failed after %d attempts: %w", maxRetries+1, err)
}

Testing

// Use interfaces for testing
type TripService interface {
    Start(ctx context.Context, req *StartTripRequest) (*Trip, error)
    Stop(ctx context.Context, tripID string, req *StopTripRequest) (*Trip, error)
}

// Mock implementation for testing
type MockTripService struct{}

func (m *MockTripService) Start(ctx context.Context, req *StartTripRequest) (*Trip, error) {
    return &Trip{
        TripID:    "test_trip_123",
        VehicleID: req.VehicleID,
        Status:    TripStatusActive,
        StartTime: time.Now(),
    }, nil
}

Examples

Fleet Management System

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "github.com/bookovia/go-sdk"
)

func main() {
    client := bookovia.NewClient("bkv_live_your_api_key")
    
    // Start trips for entire fleet
    vehicleIDs := []string{"truck_001", "truck_002", "truck_003"}
    
    for _, vehicleID := range vehicleIDs {
        trip, err := client.Trips.Start(context.Background(), &bookovia.StartTripRequest{
            VehicleID: vehicleID,
            Metadata: map[string]interface{}{
                "fleet_id": "fleet_alpha",
                "purpose":  "delivery",
            },
        })
        
        if err != nil {
            log.Printf("Failed to start trip for %s: %v", vehicleID, err)
            continue
        }
        
        fmt.Printf("Started trip %s for vehicle %s\n", trip.TripID, vehicleID)
    }
    
    // Monitor active trips
    time.Sleep(5 * time.Minute)
    
    trips, err := client.Trips.List(context.Background(), &bookovia.TripFilters{
        Status: bookovia.TripStatusActive,
    })
    
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Active trips: %d\n", len(trips.Trips))
    for _, trip := range trips.Trips {
        fmt.Printf("- %s: %s (%s)\n", trip.TripID, trip.VehicleID, trip.Status)
    }
}

Real-time Location Tracking

func trackVehicleLocations(client *bookovia.Client, tripID string) {
    ticker := time.NewTicker(30 * time.Second)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            // Simulate GPS reading
            location := &bookovia.LocationPoint{
                Latitude:  40.7128 + (rand.Float64()-0.5)*0.01,
                Longitude: -74.0060 + (rand.Float64()-0.5)*0.01,
                Timestamp: time.Now(),
                Speed:     float64(20 + rand.Intn(40)), // 20-60 km/h
                Heading:   float64(rand.Intn(360)),
                Accuracy:  5.0,
            }
            
            err := client.Locations.Upload(context.Background(), &bookovia.LocationUploadRequest{
                TripID:   tripID,
                Location: location,
            })
            
            if err != nil {
                log.Printf("Failed to upload location: %v", err)
            } else {
                fmt.Printf("Location uploaded for trip %s\n", tripID)
            }
        }
    }
}

Support


Ready to integrate? Check out our quickstart guide and API reference for more examples.