Devices
A “device” is a tracked device or vehicle, scoped to the key’s owner: a key only sees the devices its owner has access to.
| Field | Type | Notes |
|---|---|---|
id |
string | same as imei |
imei |
string | |
name |
string | null | |
plate |
string | null | license plate |
device_model |
string | null | hardware model |
odometer_km |
number | null | |
status |
enum | moving | parked | offline | unknown |
groups |
string[] | groups the device belongs to |
location |
object | null | null if no position is known |
location.latitude / location.longitude |
number | |
location.speed_kmh |
number | |
location.recorded_at |
string (ISO 8601) | null | |
updated_at |
string (ISO 8601) | null |
GET /api/v2/devices
Section titled “GET /api/v2/devices”List of devices the key has access to. Permission: read_devices.
| Parameter | Default | Range | Notes |
|---|---|---|---|
limit |
50 | 1–200 | clamped at the edges, never rejected |
offset |
0 | ≥ 0 |
curl https://api.aitrack.it/api/v2/devices?limit=10 \ -H "X-API-Key: $AITRACK_API_KEY"const res = await fetch('https://api.aitrack.it/api/v2/devices?limit=10', { headers: { 'X-API-Key': process.env.AITRACK_API_KEY },});const { data, meta } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices", headers={"X-API-Key": api_key}, params={"limit": 10}, timeout=10,)data = res.json()["data"]{ "data": [ { "id": "352093081452312", "imei": "352093081452312", "name": "Furgone 1", "plate": "AB123CD", "device_model": "FMB920", "odometer_km": 84213, "status": "moving", "groups": ["Consegne"], "location": { "latitude": 45.4642, "longitude": 9.19, "speed_kmh": 52, "recorded_at": "2026-07-14T09:00:00.000Z" }, "updated_at": "2026-07-14T09:00:03.000Z" } ], "meta": { "pagination": { "limit": 10, "offset": 0, "count": 1 } }}GET /api/v2/devices/nearest
Section titled “GET /api/v2/devices/nearest”The device closest to a coordinate, and how far it is. Permission: read_locations.
| Parameter | Required | Value |
|---|---|---|
lat |
yes | latitude, -90 to 90 |
lng |
yes | longitude, -180 to 180 |
limit |
no | how many to return, 1–50. Default 1 |
max_km |
no | discard anything beyond this radius (km) |
curl -H "X-API-Key: $AITRACK_API_KEY" \ "https://api.aitrack.it/api/v2/devices/nearest?lat=45.4642&lng=9.19&limit=3"const url = new URL('https://api.aitrack.it/api/v2/devices/nearest');url.searchParams.set('lat', '45.4642');url.searchParams.set('lng', '9.19');url.searchParams.set('limit', '3');
const res = await fetch(url, { headers: { 'X-API-Key': process.env.AITRACK_API_KEY } });const { data, meta } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices/nearest", headers={"X-API-Key": api_key}, params={"lat": 45.4642, "lng": 9.19, "limit": 3}, timeout=10,)nearest = res.json()["data"]{ "data": [ { "id": "359000000000001", "imei": "359000000000001", "name": "Furgone 1", "plate": "AB123CD", "status": "moving", "location": { "latitude": 45.4642, "longitude": 9.19, "speed_kmh": 52, "recorded_at": "2026-07-14T09:00:00.000Z" }, "distance_km": 0.412 } ], "meta": { "query": { "lat": 45.4642, "lng": 9.19, "limit": 3, "max_km": null }, "distance": "straight_line_km" }}Missing coordinates → 400 COORDINATES_REQUIRED. Coordinates out of range or not numeric → 400 INVALID_COORDINATES. No device with a known position (or none within max_km) → data is an empty list, not an error.
GET /api/v2/devices/{imei}
Section titled “GET /api/v2/devices/{imei}”A single device. Permission: read_devices. Non-existent IMEI — or not yours — → 404 DEVICE_NOT_FOUND (the two cases aren’t distinguished, so as not to reveal the existence of an IMEI outside your scope).
curl https://api.aitrack.it/api/v2/devices/352093081452312 \ -H "X-API-Key: $AITRACK_API_KEY"const res = await fetch('https://api.aitrack.it/api/v2/devices/352093081452312', { headers: { 'X-API-Key': process.env.AITRACK_API_KEY },});const { data } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices/352093081452312", headers={"X-API-Key": api_key}, timeout=10,)device = res.json()["data"]GET /api/v2/devices/{imei}/location
Section titled “GET /api/v2/devices/{imei}/location”Latest known position. Permission: read_locations. 404 LOCATION_NOT_FOUND if the device hasn’t reported anything yet.
curl https://api.aitrack.it/api/v2/devices/352093081452312/location \ -H "X-API-Key: $AITRACK_API_KEY"const res = await fetch( 'https://api.aitrack.it/api/v2/devices/352093081452312/location', { headers: { 'X-API-Key': process.env.AITRACK_API_KEY } },);const { data } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices/352093081452312/location", headers={"X-API-Key": api_key}, timeout=10,)location = res.json()["data"]{ "data": { "latitude": 45.4642, "longitude": 9.19, "altitude_m": 122, "speed_kmh": 52, "recorded_at": "2026-07-14T09:00:00.000Z" }}GET /api/v2/devices/{imei}/history
Section titled “GET /api/v2/devices/{imei}/history”Position history. Permission: read_history.
| Parameter | Default | Range | Notes |
|---|---|---|---|
from |
— | ISO 8601 | window start |
to |
— | ISO 8601 | window end |
limit |
500 | 1–1000 | clamped |
How far back the window actually reaches depends on your plan: the server trims requests that go further back than the plan retains.
curl -H "X-API-Key: $AITRACK_API_KEY" \ "https://api.aitrack.it/api/v2/devices/352093081452312/history?from=2026-07-14T00:00:00Z&to=2026-07-14T23:59:59Z&limit=500"const url = new URL('https://api.aitrack.it/api/v2/devices/352093081452312/history');url.searchParams.set('from', '2026-07-14T00:00:00Z');url.searchParams.set('to', '2026-07-14T23:59:59Z');url.searchParams.set('limit', '500');
const res = await fetch(url, { headers: { 'X-API-Key': process.env.AITRACK_API_KEY } });const { data, meta } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices/352093081452312/history", headers={"X-API-Key": api_key}, params={ "from": "2026-07-14T00:00:00Z", "to": "2026-07-14T23:59:59Z", "limit": 500, }, timeout=10,)points = res.json()["data"]{ "data": [ { "latitude": 45.4642, "longitude": 9.19, "speed_kmh": 52, "heading": 91, "satellites": 11, "recorded_at": "2026-07-14T09:00:00.000Z" } ], "meta": { "pagination": { "limit": 500, "offset": 0, "count": 1 } }}GET /api/v2/devices/{imei}/commands
Section titled “GET /api/v2/devices/{imei}/commands”The command queue, read-only. Permission: send_commands.
| Parameter | Default | Values | Notes |
|---|---|---|---|
status |
pending,sent |
csv of pending | sent | canceled |
status filter |
limit |
50 | 1–100 | clamped |
curl -H "X-API-Key: $AITRACK_API_KEY" \ "https://api.aitrack.it/api/v2/devices/352093081452312/commands?status=pending,sent&limit=50"const url = new URL('https://api.aitrack.it/api/v2/devices/352093081452312/commands');url.searchParams.set('status', 'pending,sent');
const res = await fetch(url, { headers: { 'X-API-Key': process.env.AITRACK_API_KEY } });const { data } = await res.json();res = requests.get( "https://api.aitrack.it/api/v2/devices/352093081452312/commands", headers={"X-API-Key": api_key}, params={"status": "pending,sent"}, timeout=10,)commands = res.json()["data"]{ "data": [ { "id": 91, "type": "engine_lock", "status": "pending", "queued_at": "2026-07-14T09:00:00.000Z", "sent_at": null } ], "meta": { "pagination": { "limit": 50, "offset": 0, "count": 1 } }}See also Errors & limits for the full meaning of HTTP codes and error.code values.