Skip to main content

Vehicles & dashcams

Everything in this API hangs off one identifier: the dashcam's serial number (psn). Events, trips, reports, geofence alerts, SD-card recordings and webhooks all carry it, and GET /v1/devices is the list that tells you which ones exist.

A vehicle is not a separate resource. A dashcam has a vehicle profile (vehicle), and that profile is what carries the licence plate and VIN.

The list returns the whole record

GET /v1/devices and GET /v1/devices/{psn} return the same field set. The list is not a summary: every row carries fwVersion, vehicle, sim, battery, entitlement, cameraPosition and requiredCameraLimit, joined once per page.

That matters for the most common screen anyone builds on this API — a fleet table with plates. It takes one call:

curl -s "https://openapi.fleeta.io/v1/devices?perPage=100" \
-H "Authorization: Bearer $FLEETA_API_KEY" \
| jq -r '.data[] | [.psn, .vehicle.plate // "—", .status] | @tsv'

Call GET /v1/devices/{psn} when you already hold a single PSN — from a webhook, an event row, or a link someone opened. Do not call it in a loop over the list; that is the pattern this endpoint exists to remove, and on a Standard plan it can spend a month's call budget on one dashboard's refresh cycle.

Before 2026-09-09

vehicle, sim, battery and requiredCameraLimit were on the detail view only, and a fleet table needed 1 + N calls. Nothing was removed when they were added to the list, and no field changed type. DeviceDetail remains in the spec and the SDK as an alias of Device.

q searches the dashcam name and PSN only. It does not search vehicle fields — filter vehicle.plate or vehicle.tag on the rows the list returns.

Reading the fields

FieldShapeWhat it means
psnstringSerial number. The identity everywhere in this API.
namestringThe dashcam's name, as shown in the web viewer. Writable.
modelstringHardware model reported by the dashcam.
categorycloud | wifiWhich kind of dashcam. See below.
statusdriving | parked | offlineConnection and motion state.
lastConnectedAtRFC 3339 UTC, nullableLast time the dashcam talked to the cloud.
fwVersionstring, nullableFirmware currently installed. GET /v1/devices/{psn}/firmware adds the latest available.
connectivitylte | wifi | nullHow the dashcam reaches the cloud. null when it never reported.
groupIdstring, nullableGroup the dashcam belongs to.
vehicleobjectVehicle profile — see below. {} when none is assigned.
simobject, nullableAPN and masked ICCID — see below.
batteryobjectExternal battery pack — see below.
entitlementcovered | over_limitWhether a camera seat covers this dashcam.
cameraPositioninteger, nullableSeat number, newest registration first.
requiredCameraLimitinteger, nullableFor an over_limit dashcam, the camera count that would cover it. null when already covered.

vehicle — the plate lives here

"vehicle": { "vin": "1FTBW2CM8JKA12001", "plate": "WA-4821",
"maker": "Ford", "model": "Transit 350", "year": 2024,
"tag": "Long-haul" }
  • No vehicle assigned reads as {}, not null, and not a missing key. Individual fields inside it can be null or an empty string when only part of the profile was filled in, so treat "empty" as "not registered" rather than reading a blank plate as a real one.
  • tag is read-only. It is the free-text label the web viewer groups vehicles by. PUT /v1/devices/{psn} ignores it and preserves whatever is stored — set it in the web viewer.
  • vehicle.model is the vehicle's model (Transit 350). The top-level model is the dashcam's model (DR770X BOX PRO). They are different fields with the same name at two levels; a table that shows one as the other is the most common mix-up here.

sim — your organization's record only

sim carries the mobile plan the dashcam uses: apn, and iccid masked to its last four digits.

null means the API holds no SIM record that belongs to your organization — most often because the dashcam has no LTE plan, but also when its SIM record still names a previous owner. That is deliberate: a dashcam that changed hands can have more than one SIM row, and returning the earlier owner's APN and ICCID to the current one would be a data leak. The record repairs itself the next time the dashcam reports its SIM.

The list and the detail view resolve sim the same way and always agree.

battery — absent is not zero

"battery": { "connected": true, "level": 82, "temperature": 31,
"updatedAt": "2026-07-13T02:04:00Z" }

When no external battery pack is attached, the object is {"connected": false} and level and temperature are not present at all. Render that as "no battery", never as 0% — a ?? 0 in a client turns "nothing attached" into "flat battery", which reads as an emergency. GET /v1/devices/{psn}/battery returns the same object on its own.

Cloud vs Wi-Fi dashcams

category splits the inventory in two:

  • cloud — a cloud-connected dashcam. Every feature of this API applies.
  • wifi — a Wi-Fi-only dashcam. It is listed so your count matches what you own, but it has no cloud link: it is always offline, and cloud-only features (location, trips, events, video, SD-card access, recall, settings, reboot, GPS export, PUT) answer 422 cloud_only for its PSN — not 404, because the dashcam does exist.

Pass category=cloud when you only want the dashcams those features apply to.

status and what "online" means

status has three values: driving, parked and offline. Both driving and parked are connected — there is no online value, so ask for the two:

GET /v1/devices?status=driving
GET /v1/devices?status=parked

A status outside the enum answers 400 invalid_parameter with the accepted values in allowed. It used to be ignored, which meant status=online — the most natural thing to try — returned the entire fleet and looked like a filter that did nothing.

lastConnectedBefore filters on the server for dashcams that have not connected recently; it takes either a relative value (30d) or an absolute timestamp.

Camera seats

A subscription covers a number of cameras. Dashcams are assigned seats newest-registration first; anything beyond the count is over_limit.

An over_limit dashcam stays listed and readable — its rows, events, statistics and reports are all there. What it cannot do is anything that reaches the device or its media: video, SD-card listing, metadata, recall, playback and reboot answer 403 camera_limit_exceeded, and the body carries requiredCameraLimit so you can tell the operator exactly what to raise it to. Raising the camera count in the Fleeta web viewer (Account › Subscription) is picked up within 5 minutes with no key reissue.

Full rules, including the cameras block and the entitlement filter: Rate Limits › Camera seats.

Writing

PUT /v1/devices/{psn} — name and vehicle profile

Scope devices:write. Send name, vehicle, or both; sending neither answers 422 invalid_field.

curl -X PUT "https://openapi.fleeta.io/v1/devices/$PSN" \
-H "Authorization: Bearer $FLEETA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Truck-01", "vehicle": { "plate": "WA-4821", "year": 2024 } }'
  • name is 1–64 characters.
  • vehicle is a partial update: fields you leave out keep their stored values. At least one of vin, plate, maker, model, year must be present.
  • year is an integer between 1900 and 2100; null or "" clears it.
  • tag is ignored (read-only, above).
  • Renaming a dashcam to the name it already has is a no-op, not an error.
  • The response is the full updated record, re-read from storage — not a local echo of what you sent.

POST /v1/devices — pre-register

Registers PSNs before installation, in batches, with per-row success and failure. A pre-registered dashcam stays pending until it first connects. Registration is also subject to the camera count: registering past it answers 403 camera_limit_exceeded.

POST /v1/devices/{psn}/reboot

Reboots a cloud dashcam. It must be online; an over_limit dashcam answers 403 camera_limit_exceeded.

What lives elsewhere

You wantGo to
Firmware version and whether an update existsGET /v1/devices/{psn}/firmware
The dashcam's recording settingsDevice settings
Recordings on the SD card, thumbnails, playbackSD Recordings
Safety events and clipsSafety events
Where the fleet is right nowGET /v1/fleet/locations
Which errors mean whatErrors