Skip to main content

Overview

Three V2 endpoints together give a complete picture of a vehicle’s current health:
EndpointData
GET /api/v2/vehicles/{id}/last-positionLive voltage, ignition state, speed, odometer, last GPS fix
GET /api/v2/battery-healthBattery voltage and day-ahead prediction results (company-wide)
GET /api/v2/vehicles/{id}/engine-codesActive OBD-II / CAN fault codes with descriptions and severity
All three join on the vehicle ID (DeviceId in position data, vehicleId in battery health, and the {id} path parameter in engine-codes). These are all the same integer vehicle identifier.

Step 1 — Get live position and status

GET /api/v2/vehicles/{id}/last-position returns the latest GPS fix for a single vehicle. Key health fields:
FieldTypeDescription
deviceIdintegerVehicle identifier — join key
voltagedoubleExternal battery voltage (V)
ignitionbooleanWhether ignition is currently on
speeddoubleLast reported speed (km/h)
odometerdoubleTotal odometer reading (km)
utcTimestringWhen this GPS fix was recorded (UTC, no Z suffix)
isOnlinebooleanWhether the device is currently connected
cURL
curl -s "https://api.telemax.com.au/api/v2/vehicles/1000/last-position" \
  -H "Authorization: Bearer YOUR_TOKEN"
Python
import requests

def get_position(vehicle_id: int, token: str) -> dict:
    r = requests.get(
        f"https://api.telemax.com.au/api/v2/vehicles/{vehicle_id}/last-position",
        headers={"Authorization": f"Bearer {token}"},
    )
    r.raise_for_status()
    return r.json()

Step 2 — Get battery health predictions

GET /api/v2/battery-health returns a paginated list of predictions for all vehicles in the company. No companyId parameter is needed — scope comes from the token.
Python
def get_all_battery_health(token: str) -> list:
    results = []
    page = 1
    while True:
        r = requests.get(
            "https://api.telemax.com.au/api/v2/battery-health",
            params={"page": page, "pageSize": 50},
            headers={"Authorization": f"Bearer {token}"},
        )
        r.raise_for_status()
        data = r.json()
        items = data.get("items") or []
        results.extend(items)
        if page * 50 >= data.get("totalCount", 0) or not items:
            break
        page += 1
    return results
Each item in items contains:
FieldDescription
vehicleIdVehicle identifier (join key)
vehicleNameVehicle display name
currentVoltageCurrent battery voltage (V)
bandOverall health band: "Critical", "Warning", "Fair", "Healthy"
healthScore.scoreHealth score out of 100
forecast.scoreEstimated days until maintenance needed
forecast.commentAI-generated forecast summary
badgesArray of active badge IDs (e.g. "HEALTHY", "PARK_DRAIN", "TREND_DOWN")
daysToReplaceEstimated days until battery replacement recommended
scoredOnDate the health score was last calculated (YYYY-MM-DD)

Step 3 — Get engine fault codes

GET /api/v2/vehicles/{id}/engine-codes returns paginated fault codes with full descriptions, severity ratings, and the location where the fault was detected.
cURL
curl -s "https://api.telemax.com.au/api/v2/vehicles/1000/engine-codes?page=1&pageSize=50" \
  -H "Authorization: Bearer YOUR_TOKEN"
Python
def get_engine_codes(vehicle_id: int, token: str) -> list:
    codes = []
    page = 1
    while True:
        r = requests.get(
            f"https://api.telemax.com.au/api/v2/vehicles/{vehicle_id}/engine-codes",
            params={"page": page, "pageSize": 50},
            headers={"Authorization": f"Bearer {token}"},
        )
        r.raise_for_status()
        data = r.json()
        codes.extend(data.get("items", []))
        if page >= data.get("numberOfPages", 1):
            break
        page += 1
    return codes
Each engine code item includes:
FieldDescription
codeRaw OBD-II code (e.g. P0420)
descriptionPlain-English fault description
severity"Low", "Medium", or "High"
whyThisMattersImpact on vehicle operation
possibleCausesLikely root causes
recommendedActionsSuggested remediation steps
detectedAtUTC timestamp when the fault was detected
location.addressReverse-geocoded address at detection

Step 4 — Join on vehicle ID

With all three data sources fetched, merge them into a single per-vehicle record:
import os, requests

API_BASE    = "https://api.telemax.com.au"
API_KEY     = os.environ["TELEMAX_API_KEY"]
VEHICLE_IDS = [1000, 1001, 1002]

# get_token() assumed from your authentication module

def build_health_record(vehicle_id: int, token: str, battery_map: dict) -> dict:
    pos   = get_position(vehicle_id, token)
    codes = get_engine_codes(vehicle_id, token)

    batt_entry = battery_map.get(vehicle_id, {})

    return {
        "name":           pos.get("deviceName", str(vehicle_id)),
        "voltage_v":      pos.get("voltage"),
        "ignition":       pos.get("ignition"),
        "speed_kmh":      pos.get("speed"),
        "odometer_km":    pos.get("odometer"),
        "last_seen":      pos.get("utcTime"),
        "band":           batt_entry.get("band", "N/A"),
        "health_score":   batt_entry.get("healthScore", {}).get("score"),
        "days_to_replace": batt_entry.get("daysToReplace"),
        "engine_codes":   [d["code"] for d in codes],
        "engine_severity":[d.get("severity") for d in codes],
    }

token      = get_token()
all_batt   = get_all_battery_health(token)
batt_map   = {b["vehicleId"]: b for b in all_batt}

print(f"{'Vehicle':<25} {'V':>5} {'Ign':<5} {'Band':>8} {'Engine Codes'}")
print("-" * 65)
for vid in VEHICLE_IDS:
    h = build_health_record(vid, token, batt_map)
    codes_str = ", ".join(h["engine_codes"]) or "none"
    ign_str   = "ON" if h["ignition"] else "off"
    print(
        f"{h['name']:<25} {h['voltage_v']:>5.1f} {ign_str:<5} "
        f"{h['band']:>8}  {codes_str}"
    )

Limitations

  • Safety score is a separate call. GET /api/v2/safety-score/{id} returns per-trip riskLevel / riskScore (0–100) / duration / distance for a single vehicle over a date range. It operates at trip granularity, not vehicle-snapshot granularity — use it alongside trip replay for driver safety dashboards.
  • Battery prediction is company-wide. GET /api/v2/battery-health fetches all vehicles. For large fleets, cache this response and join locally rather than calling it once per vehicle.

Gotchas

  • deviceId = vehicleId = engine-codes {id}. All three endpoints use the same integer vehicle identifier under different field names.
  • utcTime has no Z suffix but is always UTC — treat it as UTC when parsing.
  • Voltage is external battery voltage. Use voltage (the vehicle’s 12 V battery) for health monitoring. Do not confuse with internal device backup battery.
  • Engine code data is paginated in V2. Unlike V1 which returned an array-of-arrays, V2 returns a flat paginated items list — no flattening or deduplication needed.