Vision Services
This page explains how to interact with Cartrack Vision cameras through the Fleet API, covering video clip requests, status tracking, livestreaming, and custom camera uploads.
This service is available exclusively for accounts with the Cartrack Vision API option enabled. If you receive HTTP 403, contact your Cartrack customer success manager to enable access. After activation, allow 5 to 10 minutes for the configuration to propagate before making API calls.
Which Endpoint Should I Use?
Use this mapping based on what you want to accomplish:
| Goal | Endpoint |
|---|---|
| Request a video clip from a vehicle camera | Create Video Requests |
| Retrieve downloaded video clips | Get Video Requests |
| Check the processing status of video requests | Get Video Requests Status |
| Get a real-time livestream link for a vehicle | Video Livestream Requests |
| Check whether a vehicle's cameras are currently online | Get Vision Camera Online Status |
| Upload a single video from a custom camera device | Upload Video |
| Upload multiple videos from custom camera device(s) | Bulk Upload Videos |
1) Requesting and Retrieving Video Clips
How It Works
A video request is not an immediate download. When you submit a request, you are instructing the camera device to locate the requested footage on its local storage and upload it to the Cartrack server. The clip only becomes available to download once the camera has completed that upload.
This means the full flow depends on two things outside the API's control: the camera must be online with sufficient network coverage, and the requested footage must still exist on the device's local storage. If the camera has poor or no connectivity at the time of the request, it will retry automatically and the clip will remain in Pending until it can be fully uploaded.
How Video Requests Are Created
Video requests can be created from three different sources. GET /vision/videos/requests returns all requests regardless of origin. You will see requests you did not create via the API.
| Source | How |
|---|---|
| Fleet API | POST /vision/videos/requests (programmatic, from your integration) |
| Camera AI | Automatic. The DVR triggers a request when it detects a configured event (fatigue, distraction, cell phone usage, etc.) |
| Fleetweb | Manual. A fleet operator requests a clip through the web portal |
Clip Lifecycle
After a request is created, its status_id progresses through several states. The url field is null until the clip reaches status 3 (Complete).
Key status codes to handle in your integration:
| status_id | Label | Meaning |
|---|---|---|
| 1 | Pending | Request queued, waiting for camera to upload |
| 2 | In Progress | Camera is uploading the footage |
| 3 | Complete | Footage is ready. url is populated |
| 5 | Does Not Exist | Requested time range not found on camera storage |
| 6 | Timeout | Camera did not respond within the allowed window |
Downloading the Clip
Once a request reaches Complete, its url is a ready-to-use link to the footage. The URL is durable - fetch it immediately, or store it in your own system and retrieve it later. Treat the URL as opaque: do not parse it or depend on its host or path structure.
If your application plays the clip back in a browser rather than just downloading it, the same origin restriction described under Browser Playback and CORS applies. Fetch the clip through your own backend and re-serve it to your frontend rather than pointing browser JS at the url directly.
Limitations
Network coverage. The camera must be online and have sufficient network connectivity to upload footage. If the vehicle is in a low-coverage area when the request is placed, it will remain in Pending until coverage is restored. There is no guarantee of when, or whether, that happens.
FIFO local storage. DVR cameras store footage locally with a fixed capacity. When storage is full, the oldest footage is overwritten. If you place a request for footage from several days ago and the camera has been recording continuously since, that segment may no longer exist on the device. This results in a Does Not Exist (status 5) or Timeout (status 6) outcome. Request footage as soon as possible after the event of interest.
Polling Pattern
To track a clip from creation to completion, poll GET /vision/videos/requests and inspect the status_id field on each request. Poll at a reasonable interval; every 30 to 60 seconds is sufficient. Stop polling when status_id reaches a terminal state (3, 5, or 6).
GET /vision/videos/status is a static reference table that returns the full list of status codes and their descriptions. It is not a per-request status endpoint and does not need to be polled.
2) Video Livestream
What It Means
Request a real-time livestream link for a specific vehicle. The API returns a URL your application can use to display a live camera feed.
Response
The response is an HTTP 200 with two arrays: data (cameras that started streaming) and failed_cameras (cameras that could not, each with a status and a human-readable message). A request can partially succeed, so 200 does not mean every camera is streaming - always read both arrays. Even when every requested camera fails, the HTTP status is still 200 with an empty data array; a non-200 means the request itself failed, not an individual camera.
Each entry in data carries an is_hls flag: true when its url is an HLS playlist, false for a WebSocket stream. The streaming format is fixed per account, so all cameras in a response share the same is_hls value.
For HLS streams, each data entry also includes an expires_at timestamp for when that URL stops working; request a fresh livestream before then to keep watching. WebSocket entries have expires_at: null. Treat the url as opaque and do not depend on its host or path.
Error: Camera Not Online
If the vehicle's DVR camera is currently offline, the API returns HTTP 409:
HTTP 409
{"error":{"code":409,"message":"Livestream unavailable: Digital Video Recorder is offline"}}
This indicates the camera device itself is unreachable; the Fleet API is functioning normally. A 409 here is a device-state conflict, not a server error, so do not retry it in a loop. Surface it to the user as a camera availability issue and let them decide when to retry.
To avoid the 409 altogether, check the camera's current state with GET /vision/status before requesting a livestream. See Camera Online Status.
Developer Considerations
- Livestream links are short-lived. For HLS streams,
expires_attells you exactly when a URL stops working; request a fresh one before then. Do not cache links across sessions, and treat them as opaque (do not depend on host or path). - The link is tied to the vehicle registration passed in the path (
/vision/livestream/{registration}). - If a vehicle has multiple cameras, the response may include multiple stream links in
data, and any that could not start infailed_cameras. - Handle
409from this endpoint as a camera state issue, not a server failure. Do not retry it in a loop; let the user trigger the retry manually.
Browser Playback and CORS
The livestream url is meant to be relayed through your own backend, not handed directly to browser JavaScript (hls.js, Video.js, a <video> tag) on your own website. The streaming backend enforces an origin check on the actual media request, separate from the URL itself. A request with no Origin header, or an Origin on *.cartrack.com, succeeds; any other Origin is rejected with 403 and no CORS header - which browsers surface as an opaque CORS failure rather than a readable error.
There is currently no self-service way to get your domain allowed for direct browser playback. Fetch the .m3u8 playlist and its segments server-side and re-serve them to your own frontend, so the browser stays same-origin against your own domain. Do not assume cross-origin browser playback will work without prior arrangement.
3) Uploading Video from Custom Camera Devices
What It Means
If your fleet uses third-party camera hardware that is not a native Cartrack Vision device, you can push recorded video into Cartrack Vision using the upload endpoints. This allows non-Cartrack cameras to be integrated into the same video management workflow.
Single vs. Bulk Upload
- Single upload (
POST /vision/video/upload): Upload one video file per request. Best for real-time or low-volume ingest. - Bulk upload (
POST /vision/video/bulk-upload): Upload multiple video files in a single request. Best for batch ingest from a device that stores footage locally and syncs periodically.
Developer Considerations
- Ensure the vehicle registration in the upload payload matches an active contract with the Vision API VAS enabled, or the upload will be rejected.
- For bulk uploads, treat each file's result individually — a partial failure does not necessarily reject the entire batch.
- Validate file format and size requirements against the API schema before uploading to avoid unnecessary rejections.
4) Camera Online Status
What It Means
GET /vision/status returns the current online state of the Vision cameras on the account, one entry per camera-capable vehicle. Use it to find out whether a camera can be reached right now, before placing a video request or asking for a livestream.
Status Values
| status | Meaning |
|---|---|
online | The device is connected and at least one camera channel is currently active |
offline | The device is connected with no active channel, is not currently reporting status, or has never sent status data |
standby | The device is connected but idle. This is a normal state, not a fault |
Each entry also carries a cameras array giving the per-channel state, so a vehicle can be online overall while one of its channels is not.
A vehicle appears in the response as soon as its hardware is camera-capable, even if its device has never reported a status. In that case status is offline and cameras is an empty array, because the number of channels on the device is not known yet. A vehicle whose hardware has no camera at all is never returned.
Filtering
The response covers the whole account by default and is paginated with filter[page] and filter[limit]. Narrow it with:
| Filter | Behavior |
|---|---|
filter[vehicle_id] | Exact vehicle ID |
filter[registration] | Case-insensitive exact match, not a partial match |
filter[status] | online, offline or standby, case-insensitive |
filter[camera_id] | A single channel from 1 to 8, instead of every channel |
filter[camera_id] behaves differently from the others. A vehicle whose device is not known to have that channel installed is dropped from the response entirely, even though it would have appeared as offline without the filter. So an absent vehicle under this filter means "no such channel", not "channel offline".
Streaming Protocol Support
This endpoint currently supports accounts on the HLS video streaming protocol only. An account on the WebSocket protocol receives HTTP 422. Support for WebSocket accounts is planned for a future release. The protocol is fixed per account, so this is an account-level outcome rather than something that varies per request.
Developer Considerations
- The endpoint is rate limited to 6 requests per minute, which is stricter than most of the API. See Rate Limiting. Set
limitas high as your fleet needs (up to the max of1000) and filter client-side rather than polling per vehicle — at 6 requests/minute, paging through more than a page or two per check eats your whole budget fast. - Treat this as a point-in-time reading. A camera can drop off between the status check and the livestream request, so still handle the livestream
409. standbyis not an error. Do not surface it to users as a fault.- An
offlinevehicle with an emptycamerasarray has simply never reported. It is not the same as a device that reported every channel down, and it is worth distinguishing in your UI.
Recommended Integration Pattern
- Confirm the Vision API VAS is active on the target account before integrating (test with any Vision endpoint; a 403 means the VAS is not yet configured).
- Check camera availability with
GET /vision/statusbefore acting on a specific vehicle, so a request is not placed against a device that cannot answer. - For clip retrieval: submit the request, poll for status, then fetch the clip once it reaches a ready state.
- For livestream: request a fresh link per session and do not reuse expired links.
- For custom camera uploads: match video metadata (vehicle registration, timestamp) precisely to ensure footage is correctly associated in the Cartrack platform.