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.
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
| Field | Shape | What it means |
|---|---|---|
psn | string | Serial number. The identity everywhere in this API. |
name | string | The dashcam's name, as shown in the web viewer. Writable. |
model | string | Hardware model reported by the dashcam. |
category | cloud | wifi | Which kind of dashcam. See below. |
status | driving | parked | offline | Connection and motion state. |
lastConnectedAt | RFC 3339 UTC, nullable | Last time the dashcam talked to the cloud. |
fwVersion | string, nullable | Firmware currently installed. GET /v1/devices/{psn}/firmware adds the latest available. |
connectivity | lte | wifi | null | How the dashcam reaches the cloud. null when it never reported. |
groupId | string, nullable | Group the dashcam belongs to. |
vehicle | object | Vehicle profile — see below. {} when none is assigned. |
sim | object, nullable | APN and masked ICCID — see below. |
battery | object | External battery pack — see below. |
entitlement | covered | over_limit | Whether a camera seat covers this dashcam. |
cameraPosition | integer, nullable | Seat number, newest registration first. |
requiredCameraLimit | integer, nullable | For 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
{}, notnull, and not a missing key. Individual fields inside it can benullor 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. tagis 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.modelis the vehicle's model (Transit 350). The top-levelmodelis 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 alwaysoffline, and cloud-only features (location, trips, events, video, SD-card access, recall, settings, reboot, GPS export,PUT) answer422 cloud_onlyfor its PSN — not404, 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 } }'
nameis 1–64 characters.vehicleis a partial update: fields you leave out keep their stored values. At least one ofvin,plate,maker,model,yearmust be present.yearis an integer between 1900 and 2100;nullor""clears it.tagis 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 want | Go to |
|---|---|
| Firmware version and whether an update exists | GET /v1/devices/{psn}/firmware |
| The dashcam's recording settings | Device settings |
| Recordings on the SD card, thumbnails, playback | SD Recordings |
| Safety events and clips | Safety events |
| Where the fleet is right now | GET /v1/fleet/locations |
| Which errors mean what | Errors |
Related links
- Getting Started — the first three calls
- Rate Limits — monthly call limit, camera seats, volume quotas
- Tenant Isolation — what a key can and cannot see
- Sandbox — a 12-vehicle demo fleet, no dashcam needed