Skip to main content

Tracking Service API Documentation

Base URL

/api/tracking (internal root path)

Routes are exposed at:

  • /api/positions - Position data
  • /api/events - Event data
  • /api/geofences - Geofence management

📘 TypeScript Interfaces

Use these interfaces for your frontend integration.

// Position Object
export interface Position {
id: number;
deviceId: number;
protocol: string | null;
serverTime: string | null; // ISO 8601
deviceTime: string | null; // ISO 8601
fixTime: string | null; // ISO 8601
valid: boolean;
latitude: number;
longitude: number;
altitude: number;
speed: number; // knots
course: number; // degrees
accuracy: number;
address: string | null;
attributes: Record<string, any>;
}

// Event Object
export interface Event {
id: number;
type: string;
eventTime: string | null; // ISO 8601
deviceId: number;
positionId: number | null;
geofenceId: number | null;
maintenanceId: number | null;
attributes: Record<string, any>;
}

// Event Types
export type EventType =
| 'deviceOnline'
| 'deviceOffline'
| 'deviceUnknown'
| 'deviceInactive'
| 'deviceMoving'
| 'deviceStopped'
| 'deviceOverspeed'
| 'deviceFuelDrop'
| 'deviceFuelIncrease'
| 'geofenceEnter'
| 'geofenceExit'
| 'alarm'
| 'ignitionOn'
| 'ignitionOff'
| 'maintenance'
| 'textMessage'
| 'driverChanged'
| 'commandResult';

// Geofence Object
export interface Geofence {
id: number;
name: string;
description: string | null;
area: string; // WKT format
calendarId: number | null;
attributes: Record<string, any>;
}

// Geofence Create Request
export interface GeofenceCreateRequest {
name: string;
description?: string;
area: string; // WKT: CIRCLE, POLYGON, or LINESTRING
calendarId?: number;
attributes?: Record<string, any>;
}

// Geofence Update Request
export interface GeofenceUpdateRequest {
name?: string;
description?: string;
area?: string;
calendarId?: number;
attributes?: Record<string, any>;
}

// Health Check Response
export interface HealthResponse {
status: 'healthy' | 'degraded';
service: string;
ready: boolean;
database: 'connected' | 'disconnected';
}

🛠️ Frontend Integration Guide

1. Authentication

All tracking endpoints require authentication. The gateway validates JWT tokens and passes X-User-Id header to the service.

Frontend Requirement: You MUST include the JWT token in the Authorization header for all authenticated requests.

await fetch('/api/positions/', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});

2. Speed Units

Speed values are stored in knots. Convert for display:

  • 1 knot = 1.852 km/h
  • 1 knot = 1.151 mph

3. Error Handling

StatusMeaningAction
401 UnauthorizedNot logged inRedirect to login
403 ForbiddenAccess denied to device/geofenceShow access error
404 Not FoundResource not foundShow not found error
400 Bad RequestInvalid request dataShow validation error

📡 Endpoints

1. Positions

Get Positions

GET /api/positions/

  • Auth Required: Yes
  • Query Params:
    • deviceId: Filter by device ID
    • id: Get specific position IDs (can repeat)
    • from: Start time (ISO 8601) - required with to for history
    • to: End time (ISO 8601) - required with from for history
  • Response: Position[]

Get latest position for device:

GET /api/positions/?deviceId=123

Get position history:

GET /api/positions/?deviceId=123&from=2024-12-01T00:00:00Z&to=2024-12-08T00:00:00Z

Get latest positions for all user's devices:

GET /api/positions/

Delete Positions

DELETE /api/positions/

  • Auth Required: Yes
  • Permission: Owner only (shared users cannot delete history)
  • Query Params (all required):
    • deviceId: Device ID
    • from: Start time (ISO 8601)
    • to: End time (ISO 8601)
  • Response: 204 No Content
  • Errors:
    • 403 Forbidden: User doesn't own this device or lacks permission

2. Events

List Events

GET /api/events/

  • Auth Required: Yes
  • Query Params:
    • deviceId: Filter by device ID (optional)
    • from: Start time (ISO 8601)
    • to: End time (ISO 8601)
    • type: Filter by event type
  • Response: Event[] (max 1000)

Get events for device:

GET /api/events/?deviceId=123&from=2024-12-01T00:00:00Z&to=2024-12-08T00:00:00Z

Get overspeed events:

GET /api/events/?type=deviceOverspeed

Get Event

GET /api/events/{id}

  • Auth Required: Yes
  • Response: Event
  • Errors:
    • 403 Forbidden: User doesn't own the device that generated this event
    • 404 Not Found: Event doesn't exist

3. Geofences

List Geofences

GET /api/geofences/

  • Auth Required: Yes
  • Query Params:
    • userId: Filter by user (optional)
    • all: Get all accessible geofences (optional)
  • Response: Geofence[]

Create Geofence

POST /api/geofences/

  • Auth Required: Yes
  • Content-Type: application/json
  • Body: GeofenceCreateRequest

Circle Example:

{
"name": "Office",
"description": "Main office building",
"area": "CIRCLE (45.4654 9.1859, 100)"
}

Format: CIRCLE (latitude longitude, radius_in_meters)

Polygon Example:

{
"name": "Warehouse Zone",
"description": "Warehouse perimeter",
"area": "POLYGON ((45.4654 9.1859, 45.4655 9.1860, 45.4656 9.1858, 45.4654 9.1859))"
}

Format: POLYGON ((lat1 lon1, lat2 lon2, ..., lat1 lon1)) - must close the polygon

  • Response: 201 Created Geofence
  • Errors:
    • 400 Bad Request: Invalid area format

Get Geofence

GET /api/geofences/{id}

  • Auth Required: Yes
  • Response: Geofence
  • Errors:
    • 403 Forbidden: User doesn't own this geofence
    • 404 Not Found: Geofence doesn't exist

Update Geofence

PUT /api/geofences/{id}

  • Auth Required: Yes
  • Content-Type: application/json
  • Body: GeofenceUpdateRequest
{
"name": "Updated Name",
"description": "Updated description"
}
  • Response: Geofence
  • Errors:
    • 400 Bad Request: Invalid area format
    • 403 Forbidden: User doesn't own this geofence
    • 404 Not Found: Geofence doesn't exist

Delete Geofence

DELETE /api/geofences/{id}

  • Auth Required: Yes
  • Response: 204 No Content
  • Errors:
    • 403 Forbidden: User doesn't own this geofence
    • 404 Not Found: Geofence doesn't exist

4. Health

Health Check (Public)

GET /api/tracking/health

  • Auth Required: No
  • Response:
{
"status": "healthy",
"service": "tracking-service",
"ready": true,
"database": "connected"
}