Skip to main content

Overview

Three endpoints together give a complete picture of a vehicle’s current health:
EndpointData
POST /api/GetLastPositionDataLive voltage, ignition state, speed, odometer, last GPS fix
POST /api/GetCompanyVehiclesBatteryHealthBattery voltage trend and day-ahead prediction results
GET /api/devices/{id}/dtc-codesActive OBD-II / CAN fault codes from the vehicle handler
All three join on the vehicle IDDeviceId in position data, vehicleId in battery health, and the {id} path parameter in DTC codes. These are all the same legacy integer vehicle identifier.
DTC description and severity fields are present in the schema but are empty in the current backend. Display the raw code value and resolve meaning externally via the SAE J1979 or ISO 15031-6 standard. See Known Issues.

Step 1 — Get live position and status

GetLastPositionData 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)
cURL
curl -s -X POST \
  "https://api.telemax.com.au/api/GetLastPositionData?id=1000" \
  -H "Authorization: Bearer YOUR_TOKEN"
Python
import requests

def get_position(vehicle_id: int, token: str) -> dict:
    r = requests.post(
        "https://api.telemax.com.au/api/GetLastPositionData",
        params={"id": vehicle_id},
        headers={"Authorization": f"Bearer {token}"},
    )
    r.raise_for_status()
    return r.json()

Step 2 — Get battery health predictions

GetCompanyVehiclesBatteryHealth returns a paged list of battery predictions. Iterate over all pages using numberOfPages:
Python
def get_all_battery_health(company_id: int, token: str) -> list:
    results = []
    page = 1
    while True:
        r = requests.post(
            "https://api.telemax.com.au/api/GetCompanyVehiclesBatteryHealth",
            params={"compId": company_id, "page": page, "pageSize": 50},
            headers={"Authorization": f"Bearer {token}"},
        )
        r.raise_for_status()
        data = r.json()
        results.extend(data.get("items", []))
        if page >= data.get("numberOfPages", 1):
            break
        page += 1
    return results
Each item in items contains:
FieldDescription
vehicleIdVehicle identifier (join key)
currentVoltageCurrent battery voltage (V)
predictionResultsArray of prediction objects
Each prediction object has:
  • BatteryPredictionValue — label such as "Good", "Fair", "Poor"
  • PredictionConfidence — label such as "High", "Medium", "Low"
  • predictionForDay — integer (days ahead this prediction applies to)

Step 3 — Get DTC fault codes

GET /api/devices/{id}/dtc-codes returns the active diagnostic trouble codes from the vehicle’s OBD-II / CAN handler. The response is an array of arrays — flatten and deduplicate by code:
Python
def get_dtc_codes(vehicle_id: int, token: str) -> list[str]:
    r = requests.get(
        f"https://api.telemax.com.au/api/devices/{vehicle_id}/dtc-codes",
        headers={"Authorization": f"Bearer {token}"},
    )
    r.raise_for_status()
    raw = r.json()          # array-of-arrays of DtcDto
    seen = set()
    codes = []
    for group in raw:
        for dtc in group:
            code = dtc.get("code", "")
            if code and code not in seen:
                seen.add(code)
                codes.append(code)
    return codes
description and severity on DtcDto are empty in the current backend. Only code is populated. Resolve fault meanings via the SAE J1979 / ISO 15031-6 standard or your OEM documentation.

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"
COMPANY_ID = 85
VEHICLE_IDS = [1000, 1001, 1002]   # replace with your fleet

# — fetch helpers (get_token() assumed from authentication module) —

def build_health_record(vehicle_id: int, token: str) -> dict:
    pos     = get_position(vehicle_id, token)
    battery = {b["vehicleId"]: b for b in get_all_battery_health(COMPANY_ID, token)}
    dtcs    = get_dtc_codes(vehicle_id, token)

    batt_entry = battery.get(vehicle_id, {})
    top_pred   = next(
        (p for p in sorted(
            batt_entry.get("predictionResults", []),
            key=lambda p: p.get("predictionForDay", 0)
        )),
        None,
    )

    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"),
        "battery_pred": top_pred["BatteryPredictionValue"] if top_pred else "N/A",
        "dtc_codes":  dtcs,
    }

token = get_token()
print(f"{'Vehicle':<25} {'V':>5} {'Ign':<5} {'Battery':>8} {'DTCs'}")
print("-" * 60)
for vid in VEHICLE_IDS:
    h = build_health_record(vid, token)
    dtc_str = ", ".join(h["dtc_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['battery_pred']:>8}  {dtc_str}"
    )

Limitations

  • DTC description and severity are empty. The DtcDto.description and DtcDto.severity fields are present in the schema but the backend does not populate them. Display the raw code value and resolve the meaning externally using the SAE J1979 or ISO 15031-6 fault code database.
  • Safety score is a separate call. GetSafetyScore returns per-trip riskLevel / riskScore (0–100) / duration / distance for a single vehicle over a date range. It is not included here because it operates at trip granularity, not vehicle-snapshot granularity — use it alongside trip replay for driver safety dashboards.
  • Battery prediction results are company-wide. GetCompanyVehiclesBatteryHealth fetches all vehicles in the company. For large fleets, cache this response and join locally rather than calling it once per vehicle.

Gotchas

  • DeviceId = vehicleId = DTC {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. InternalBatteryVoltage (on the PositionDto) is the device’s internal backup battery, not the vehicle’s 12 V battery. Use Voltage for vehicle health.