Register a tracker in a vehicle
Scopes: devices:read, devices:write, vehicles:write, telemetry:read.
1. Choose the protocol and class
curl -s "https://api.zaitrack.app/v1/codecs" -H "Authorization: Bearer $KEY" | jq '.items'
curl -s "https://api.zaitrack.app/v1/device-classes" -H "Authorization: Bearer $KEY" | jq '.items'
The codecs are the protocols ZAITRACK decodes (Built-in codecs); a GPS tracker's class is
gps-tracker.
2. Register the device
externalId is the tracker's identity, usually its IMEI: 6 to 32 capital letters, digits or hyphens.
DEVICE_ID=$(curl -s -X POST "https://api.zaitrack.app/v1/devices" \
-H "Authorization: Bearer $KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"externalId": "356307042441013", "manufacturer": "Teltonika", "model": "FMC130",
"codecId": "teltonika.codec8e", "deviceClass": "gps-tracker"}' | jq -r '.id')
Use a codecId from step 1. A new device is manufactured until it reports.
3. Create the vehicle and bind the device
VEHICLE_ID=$(curl -s -X POST "https://api.zaitrack.app/v1/vehicles" \
-H "Authorization: Bearer $KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"make": "Volvo", "model": "FH16", "year": 2024, "assetClass": "heavy-truck",
"registration": {"country": "SA", "plate": "ABC 1234"}, "fuelType": "diesel"}' | jq -r '.id')
curl -s -X POST "https://api.zaitrack.app/v1/vehicles/$VEHICLE_ID/devices" \
-H "Authorization: Bearer $KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d "{\"deviceId\": \"$DEVICE_ID\"}" | jq '.attachedDevices'
A device can be bound before it ever connects. Binding a device that is bound to another vehicle is refused
(409).
4. Read its positions
Once the tracker reports:
curl -s "https://api.zaitrack.app/v1/positions/latest?deviceId=$DEVICE_ID" \
-H "Authorization: Bearer $KEY" | jq '.positions'
curl -s "https://api.zaitrack.app/v1/devices/$DEVICE_ID/track?from=2026-10-28T00:00:00Z&to=2026-10-28T12:00:00Z&limit=500" \
-H "Authorization: Bearer $KEY" | jq '{points: (.points | length), truncated}'
positions/latest takes several deviceIds, repeated or comma-separated. Both calls are in the telemetry rate
class (10 per second): poll the latest positions of many devices in one call rather than one call per device.