> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file to discover all available pages before exploring further.

# License Plate Recognition & Vehicles

> Query license plate detection events, search plates with fuzzy matching, build a watchlist of saved vehicles, run per-device reports, and export vehicle data as CSV with the Rhombus API.

## Overview

Rhombus cameras with License Plate Recognition (LPR) detect vehicles and read their license plates as they pass through a scene. Each detection becomes a vehicle event that records the plate, the reporting camera and location, a captured image, and the time it was seen.

Through the API, you can:

* **Query detection events** across your organization, filtered by device, location, plate, name, or label
* **Search a specific plate** with exact or fuzzy matching to find every time it was seen
* **Build a watchlist** of saved vehicles ("plates of interest") with alert and trust flags, names, and labels
* **Run per-device reports** that bucket detections by hour, day, week, or month
* **Export vehicle events** as CSV for external analysis or record keeping

<Note>
  Every vehicle event timestamp is reported in **epoch milliseconds**, but the field name differs by endpoint (`startTimeMs`, `startTime`, `timestampMs`, `createdAtMillis`, `eventTimestamp`). Each section below calls out the exact field to use. There is no region, state, or numeric confidence field on vehicle events — do not expect one.
</Note>

## Prerequisites

<Note>
  Before you begin, make sure you have:

  * A **Rhombus API key** with read access to cameras (generated in the Rhombus Console under Settings > API). Reporting a misread event additionally requires the **`MANAGE_LICENSEPLATES`** permission, and CSV export requires the **`REPORT_ADMINISTRATION`** permission.
  * At least one **LPR-capable camera** deployed and reading plates at a location
  * The **device UUID** of that camera, which you can retrieve from the camera endpoints or the Rhombus Console
</Note>

All requests are `POST` to `https://api2.rhombussystems.com` and authenticate with the `x-auth-scheme` and `x-auth-apikey` headers shown in every example.

## Workflow 1: Query recent detections

Use `getVehicleEvents` to retrieve detection events across your organization. This is the primary endpoint for pulling LPR activity into a dashboard or report.

The request combines two kinds of criteria that behave differently:

* **Filter fields** (`deviceUuidFilter`, `locationUuidFilter`) are **ANDed** — a returned event must satisfy *all* filters you provide.
* **Query fields** (`nameQuery`, `licensePlateExactQuery`, `vehicleLabelQuery`, `licensePlateFuzzyQuery`, `unnamedQuery`) are **ORed** — a returned event must satisfy *at least one* query you provide.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  # Query the last 24 hours of detections from one camera
  now_ms = int(time.time() * 1000)
  one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/getVehicleEvents",
      headers=headers,
      json={
          "startTimeMs": one_day_ago_ms,
          "endTimeMs": now_ms,
          "deviceUuidFilter": ["YOUR_CAMERA_UUID"]
      }
  )

  data = response.json()
  for event in data.get("events", []):
      plate = event.get("vehicleLicensePlate")
      ts = event.get("eventTimestamp")
      device = event.get("deviceUuid")
      print(f"[{ts}] {plate} seen by {device}")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneDayAgo = now - (24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/getVehicleEvents', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      startTimeMs: oneDayAgo,
      endTimeMs: now,
      deviceUuidFilter: ['YOUR_CAMERA_UUID']
    })
  });

  const data = await response.json();
  for (const event of data.events || []) {
    console.log(`[${new Date(event.eventTimestamp).toISOString()}] ${event.vehicleLicensePlate} seen by ${event.deviceUuid}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/getVehicleEvents \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "startTimeMs": 1712620800000,
      "endTimeMs": 1712707200000,
      "deviceUuidFilter": ["YOUR_CAMERA_UUID"]
    }'
  ```
</CodeGroup>

### Request fields

<ParamField body="startTimeMs" type="integer">
  Start of the time window (oldest) in epoch milliseconds.
</ParamField>

<ParamField body="endTimeMs" type="integer">
  End of the time window (newest) in epoch milliseconds.
</ParamField>

<ParamField body="deviceUuidFilter" type="string[]">
  Return only events from these camera UUIDs. ANDed with other filters.
</ParamField>

<ParamField body="locationUuidFilter" type="string[]">
  Return only events from these location UUIDs. ANDed with other filters.
</ParamField>

<ParamField body="nameQuery" type="string[]">
  Return events whose vehicle name matches one of these values. ORed with other queries.
</ParamField>

<ParamField body="licensePlateExactQuery" type="string[]">
  Return events whose plate exactly matches one of these values. ORed with other queries.
</ParamField>

<ParamField body="vehicleLabelQuery" type="string[]">
  Return events tagged with one of these vehicle labels. ORed with other queries.
</ParamField>

<ParamField body="licensePlateFuzzyQuery" type="string">
  Return events whose plate approximately matches this partial or complete plate, allowing for character misreads. ORed with other queries.
</ParamField>

<ParamField body="unnamedQuery" type="boolean">
  If `false`, return only events that have a name; if `true`, return only events without a name. Omit if not needed. ORed with other queries.
</ParamField>

### Response fields

The response contains an `events` array. Each event has these fields:

<ResponseField name="uuid" type="string">
  Unique identifier for the vehicle event.
</ResponseField>

<ResponseField name="orgUuid" type="string">
  Organization the event belongs to.
</ResponseField>

<ResponseField name="deviceUuid" type="string">
  UUID of the camera that reported the detection.
</ResponseField>

<ResponseField name="locationUuid" type="string">
  Location where the detection occurred.
</ResponseField>

<ResponseField name="vehicleLicensePlate" type="string">
  The recognized license plate string.
</ResponseField>

<ResponseField name="matchingLicensePlates" type="string[]">
  Plate strings considered full matches for this detection.
</ResponseField>

<ResponseField name="partialLicensePlates" type="string[]">
  Plate strings considered partial matches for this detection.
</ResponseField>

<ResponseField name="imageS3Key" type="string">
  S3 key for the full detection image. This is a storage key, not a URL.
</ResponseField>

<ResponseField name="thumbnailS3Key" type="string">
  S3 key for the detection thumbnail. This is a storage key, not a URL.
</ResponseField>

<ResponseField name="eventTimestamp" type="integer">
  When the detection occurred, in epoch milliseconds.
</ResponseField>

<ResponseField name="name" type="string">
  Vehicle name, if the plate is associated with a saved vehicle.
</ResponseField>

<Warning>
  `imageS3Key` and `thumbnailS3Key` are S3 storage keys, not directly viewable image URLs. Use the media and footage endpoints to retrieve the image bytes.
</Warning>

<Note>
  The `getRecentVehicleEvents`, `getRecentVehicleEventsByLocation`, and `getRecentVehicleEventsForVehicle` endpoints are legacy. Prefer `getVehicleEvents` for new integrations — its filter/query model supersedes them.
</Note>

## Workflow 2: Search a plate with fuzzy matching

When you have a specific plate to track down, `searchLicensePlates` finds every event that matches it. Enable `fuzzy` to tolerate character misreads — helpful when a plate is partially obscured or the original read was imperfect.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  one_week_ago_ms = now_ms - (7 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/search/searchLicensePlates",
      headers=headers,
      json={
          "licensePlate": "ABC123",
          "startTime": one_week_ago_ms,
          "endTime": now_ms,
          "fuzzy": True
      }
  )

  data = response.json()
  for hit in data.get("vehicleEvents", []):
      plate = hit.get("vehicleLicensePlate")
      matched = hit.get("searchMatchedTerm")
      match_type = hit.get("searchMatchedType")
      print(f"{plate} matched '{matched}' ({match_type}) at {hit.get('eventTimestamp')}")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/search/searchLicensePlates', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      licensePlate: 'ABC123',
      startTime: oneWeekAgo,
      endTime: now,
      fuzzy: true
    })
  });

  const data = await response.json();
  for (const hit of data.vehicleEvents || []) {
    console.log(`${hit.vehicleLicensePlate} matched '${hit.searchMatchedTerm}' (${hit.searchMatchedType})`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/search/searchLicensePlates \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "licensePlate": "ABC123",
      "startTime": 1712102400000,
      "endTime": 1712707200000,
      "fuzzy": true
    }'
  ```
</CodeGroup>

### Request fields

<ParamField body="licensePlate" type="string" required>
  The plate number to search for.
</ParamField>

<ParamField body="startTime" type="integer">
  Start of the search window in epoch milliseconds. Note the field name is `startTime`, not `startTimeMs`.
</ParamField>

<ParamField body="endTime" type="integer">
  End of the search window in epoch milliseconds.
</ParamField>

<ParamField body="deviceUuids" type="string[]">
  Limit the search to these camera UUIDs.
</ParamField>

<ParamField body="fuzzy" type="boolean">
  When `true`, allows approximate matching for misread characters.
</ParamField>

<Warning>
  The `forcedFuzziness` field is deprecated. Use the boolean `fuzzy` flag instead.
</Warning>

### Response fields

The `vehicleEvents` array contains all the [vehicle event fields](#response-fields) from Workflow 1, plus two search-specific fields:

<ResponseField name="searchMatchedTerm" type="string">
  The plate term that matched your query.
</ResponseField>

<ResponseField name="searchMatchedType" type="string">
  How the match was made (for example, exact versus fuzzy).
</ResponseField>

## Workflow 3: Build a watchlist of saved vehicles

A saved vehicle is a "plate of interest" you want to track. Each saved vehicle carries an `alert` flag (notify when seen) and a `trust` flag (treat as known/safe), plus an optional name, description, and labels. Saving a vehicle also lets Rhombus attach the `name` to future detection events for that plate.

### Save a vehicle

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/saveVehicle",
      headers=headers,
      json={
          "vehicleLicensePlate": "ABC123",
          "createdAtMillis": int(time.time() * 1000),
          "name": "Delivery Van",
          "description": "White Ford Transit - approved vendor",
          "alert": True,
          "trust": True
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/saveVehicle', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      vehicleLicensePlate: 'ABC123',
      createdAtMillis: Date.now(),
      name: 'Delivery Van',
      description: 'White Ford Transit - approved vendor',
      alert: true,
      trust: true
    })
  });

  console.log(await response.json());
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/saveVehicle \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "vehicleLicensePlate": "ABC123",
      "createdAtMillis": 1712707200000,
      "name": "Delivery Van",
      "description": "White Ford Transit - approved vendor",
      "alert": true,
      "trust": true
    }'
  ```
</CodeGroup>

<ParamField body="vehicleLicensePlate" type="string" required>
  The plate that identifies this saved vehicle.
</ParamField>

<ParamField body="createdAtMillis" type="integer">
  Creation timestamp in epoch milliseconds.
</ParamField>

<ParamField body="alert" type="boolean">
  Whether to raise an alert when this vehicle is detected.
</ParamField>

<ParamField body="trust" type="boolean">
  Whether this vehicle is trusted (known/safe).
</ParamField>

<ParamField body="name" type="string">
  Display name for the vehicle.
</ParamField>

<ParamField body="description" type="string">
  Free-text description.
</ParamField>

<ParamField body="thumbnailS3Key" type="string">
  S3 key for a thumbnail image of the vehicle.
</ParamField>

### List saved vehicles

Retrieve every saved vehicle in your organization. The request body is empty.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/getVehicles",
      headers=headers,
      json={}
  )

  data = response.json()
  for vehicle in data.get("vehicles", []):
      print(f"{vehicle.get('licensePlate')}: {vehicle.get('name')} "
            f"(alert={vehicle.get('alert')}, trust={vehicle.get('trust')})")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/getVehicles', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({})
  });

  const data = await response.json();
  for (const vehicle of data.vehicles || []) {
    console.log(`${vehicle.licensePlate}: ${vehicle.name} (alert=${vehicle.alert}, trust=${vehicle.trust})`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/getVehicles \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{}'
  ```
</CodeGroup>

Each entry in the `vehicles` array is a saved vehicle:

<ResponseField name="licensePlate" type="string">
  The plate that identifies the saved vehicle.
</ResponseField>

<ResponseField name="orgUuid" type="string">
  Organization the vehicle belongs to.
</ResponseField>

<ResponseField name="createdAtMillis" type="integer">
  When the vehicle was saved, in epoch milliseconds.
</ResponseField>

<ResponseField name="alert" type="boolean">
  Whether detections raise an alert.
</ResponseField>

<ResponseField name="trust" type="boolean">
  Whether the vehicle is trusted.
</ResponseField>

<ResponseField name="name" type="string">
  Display name.
</ResponseField>

<ResponseField name="description" type="string">
  Free-text description.
</ResponseField>

<ResponseField name="thumbnailS3Key" type="string">
  S3 key for the vehicle thumbnail.
</ResponseField>

### Add and remove labels

Labels group saved vehicles into categories such as "employee," "vendor," or "flagged." Add a label to a plate with `addVehicleLabel` and remove it with `removeVehicleLabel`.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/addVehicleLabel",
      headers=headers,
      json={
          "vehicleLicensePlate": "ABC123",
          "label": "Approved Vendor"
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/addVehicleLabel', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      vehicleLicensePlate: 'ABC123',
      label: 'Approved Vendor'
    })
  });

  console.log(await response.json());
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/addVehicleLabel \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "vehicleLicensePlate": "ABC123",
      "label": "Approved Vendor"
    }'
  ```
</CodeGroup>

To see every label assigned across your organization, call `getVehicleLabelsForOrg`. Its response contains a `vehicleLabels` map keyed by license plate, where each value is the set of labels on that plate.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/getVehicleLabelsForOrg",
      headers=headers,
      json={}
  )

  labels = response.json().get("vehicleLabels", {})
  for plate, plate_labels in labels.items():
      print(f"{plate}: {', '.join(plate_labels)}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/getVehicleLabelsForOrg', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({})
  });

  const data = await response.json();
  for (const [plate, plateLabels] of Object.entries(data.vehicleLabels || {})) {
    console.log(`${plate}: ${plateLabels.join(', ')}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/getVehicleLabelsForOrg \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{}'
  ```
</CodeGroup>

### Associate past events with a saved vehicle

If a plate was detected before you saved it as a vehicle, use `associateEventsToVehicle` to attach those historical detection events to the saved vehicle. Pass the event UUIDs (from Workflow 1 or 2) and the plate.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/associateEventsToVehicle",
      headers=headers,
      json={
          "vehicleLicensePlate": "ABC123",
          "eventUuids": ["EVENT_UUID_1", "EVENT_UUID_2"]
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/associateEventsToVehicle', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      vehicleLicensePlate: 'ABC123',
      eventUuids: ['EVENT_UUID_1', 'EVENT_UUID_2']
    })
  });

  console.log(await response.json());
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/associateEventsToVehicle \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "vehicleLicensePlate": "ABC123",
      "eventUuids": ["EVENT_UUID_1", "EVENT_UUID_2"]
    }'
  ```
</CodeGroup>

### Delete a saved vehicle

Remove a vehicle from your watchlist by its plate.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/vehicle/deleteVehicle",
      headers=headers,
      json={
          "vehicleLicensePlate": "ABC123"
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/vehicle/deleteVehicle', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      vehicleLicensePlate: 'ABC123'
    })
  });

  console.log(await response.json());
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/vehicle/deleteVehicle \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{"vehicleLicensePlate": "ABC123"}'
  ```
</CodeGroup>

<Tip>
  When a detection is misread or attributed to the wrong plate, report it with `reportVehicleEvent` (passing the event's `eventUuid`). This feedback helps improve recognition accuracy. Reporting requires the `MANAGE_LICENSEPLATES` permission on your API key.
</Tip>

## Workflow 4: Per-device reports and CSV export

### Per-device report

`getLicensePlatesByDevice` returns license plate detections for a single camera, bucketed by a reporting interval. Provide the anchor time as `timestampMs` (epoch milliseconds) and choose an `interval`.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/report/getLicensePlatesByDevice",
      headers=headers,
      json={
          "deviceUuid": "YOUR_CAMERA_UUID",
          "timestampMs": int(time.time() * 1000),
          "interval": "DAILY"
      }
  )

  data = response.json()
  for event in data.get("licensePlateEvents", []):
      print(f"{event.get('vehicleLicensePlate')} at {event.get('eventTimestamp')}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/report/getLicensePlatesByDevice', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      deviceUuid: 'YOUR_CAMERA_UUID',
      timestampMs: Date.now(),
      interval: 'DAILY'
    })
  });

  const data = await response.json();
  for (const event of data.licensePlateEvents || []) {
    console.log(`${event.vehicleLicensePlate} at ${event.eventTimestamp}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/report/getLicensePlatesByDevice \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "deviceUuid": "YOUR_CAMERA_UUID",
      "timestampMs": 1712707200000,
      "interval": "DAILY"
    }'
  ```
</CodeGroup>

<ParamField body="deviceUuid" type="string" required>
  The camera UUID to report on.
</ParamField>

<ParamField body="timestampMs" type="integer">
  Anchor time for the report, as a UNIX timestamp in milliseconds.
</ParamField>

<ParamField body="interval" type="string" required>
  Reporting bucket. One of `HOURLY`, `DAILY`, `WEEKLY`, or `MONTHLY`.
</ParamField>

<Warning>
  The `dateLocal` field is deprecated. Use `timestampMs` instead.
</Warning>

The response `licensePlateEvents` array uses the same [vehicle event fields](#response-fields) described in Workflow 1.

### Export to CSV

`export/vehicleEventsV2` streams matching vehicle events as CSV. It accepts the **same request body as `getVehicleEvents`** (Workflow 1) — the filter and query fields, ANDed and ORed the same way — and returns `text/csv` directly in the response body rather than JSON. This endpoint requires the `REPORT_ADMINISTRATION` permission.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  thirty_days_ago_ms = now_ms - (30 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/export/vehicleEventsV2",
      headers=headers,
      json={
          "startTimeMs": thirty_days_ago_ms,
          "endTimeMs": now_ms,
          "deviceUuidFilter": ["YOUR_CAMERA_UUID"]
      }
  )

  with open("vehicle_events.csv", "w") as f:
      f.write(response.text)
  print("Exported vehicle events to vehicle_events.csv")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const thirtyDaysAgo = now - (30 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/export/vehicleEventsV2', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      startTimeMs: thirtyDaysAgo,
      endTimeMs: now,
      deviceUuidFilter: ['YOUR_CAMERA_UUID']
    })
  });

  // Response is CSV text, not JSON
  const csvData = await response.text();
  console.log(csvData);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/export/vehicleEventsV2 \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "startTimeMs": 1710115200000,
      "endTimeMs": 1712707200000,
      "deviceUuidFilter": ["YOUR_CAMERA_UUID"]
    }' \
    -o vehicle_events.csv
  ```
</CodeGroup>

<Note>
  `export/vehicleEventsV2` supersedes the older `export/vehicleEvents` endpoint, which is deprecated. Use V2 for new integrations — it accepts the richer `getVehicleEvents` filter/query model.
</Note>

## Use cases

<CardGroup cols={2}>
  <Card title="Fleet and vendor tracking" icon="truck">
    Save your fleet and approved vendor plates with the `trust` flag, then reconcile them against detection events to confirm on-time arrivals.
  </Card>

  <Card title="Watchlist alerting" icon="triangle-exclamation">
    Save plates of interest with `alert: true` and pair detections with webhooks to notify security when a flagged vehicle is seen.
  </Card>

  <Card title="Parking and access analytics" icon="chart-column">
    Use per-device reports to count daily or weekly vehicle traffic at a gate or lot entrance.
  </Card>

  <Card title="Investigation and audit" icon="magnifying-glass">
    Fuzzy-search a partial plate from an incident, then export the matching events as CSV for a report.
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="My time filter returns no events">
    Confirm you are sending **epoch milliseconds**, not seconds, and that you are using the correct field name for the endpoint: `startTimeMs`/`endTimeMs` for `getVehicleEvents` and `export/vehicleEventsV2`, `startTime`/`endTime` for `searchLicensePlates`, and `timestampMs` for `getLicensePlatesByDevice`. A value in seconds will resolve to 1970 and return nothing.
  </Accordion>

  <Accordion title="A plate I know was seen doesn't appear in search results">
    LPR reads can vary by lighting, angle, and speed. Set `fuzzy: true` on `searchLicensePlates` to tolerate character misreads, and check `matchingLicensePlates` and `partialLicensePlates` on returned events for near matches.
  </Accordion>

  <Accordion title="getVehicleEvents returns more than I expected">
    Remember that query fields (`nameQuery`, `licensePlateExactQuery`, `vehicleLabelQuery`, `licensePlateFuzzyQuery`, `unnamedQuery`) are ORed — an event only has to match one of them. Filter fields (`deviceUuidFilter`, `locationUuidFilter`) are ANDed. Narrow results by moving criteria into filters or reducing the number of queries.
  </Accordion>

  <Accordion title="I can't view the image from imageS3Key">
    `imageS3Key` and `thumbnailS3Key` are S3 storage keys, not URLs you can open directly. Use the Rhombus media and footage endpoints to fetch the image content for a given key.
  </Accordion>

  <Accordion title="reportVehicleEvent returns a permission error">
    Reporting a misread event requires the `MANAGE_LICENSEPLATES` permission on your API key. CSV export requires `REPORT_ADMINISTRATION`. Generate or update your key with the needed permissions in the Rhombus Console under Settings > API.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Faces & People Counting" icon="users" href="/implementations/faces-people-counting">
    Detect and identify people, and count occupancy alongside your vehicle analytics
  </Card>

  <Card title="Webhook Notifications" icon="webhook" href="/webhooks">
    Receive real-time notifications when a watchlisted vehicle is detected
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/overview">
    Explore complete request and response schemas for every vehicle endpoint
  </Card>
</CardGroup>
