> ## Documentation index
> Fetch the complete documentation index at: https://developer.rhombus.com/llms.txt
> Use it 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.

## Prerequisites

> **Note**: Before you begin, make sure you have:
>
> - A **Rhombus API key** with read access to cameras (generated in the [Rhombus Console](https://console.rhombussystems.com/settings/integrations/api-tokens/) under **Settings → Integrations & Developer Resources → API Tokens**). 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

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.

```python Python
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
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
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"]
  }'
```

### Request fields

- **`startTimeMs` (body, integer)**: Start of the time window (oldest) in epoch milliseconds.
- **`endTimeMs` (body, integer)**: End of the time window (newest) in epoch milliseconds.
- **`deviceUuidFilter` (body, string\[])**: Return only events from these camera UUIDs. ANDed with other filters.
- **`locationUuidFilter` (body, string\[])**: Return only events from these location UUIDs. ANDed with other filters.
- **`nameQuery` (body, string\[])**: Return events whose vehicle name matches one of these values. ORed with other queries.
- **`licensePlateExactQuery` (body, string\[])**: Return events whose plate exactly matches one of these values. ORed with other queries.
- **`vehicleLabelQuery` (body, string\[])**: Return events tagged with one of these vehicle labels. ORed with other queries.
- **`licensePlateFuzzyQuery` (body, string)**: Return events whose plate approximately matches this partial or complete plate, allowing for character misreads. ORed with other queries.
- **`unnamedQuery` (body, 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.

### Response fields

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

- **`uuid` (string)**: Unique identifier for the vehicle event.
- **`orgUuid` (string)**: Organization the event belongs to.
- **`deviceUuid` (string)**: UUID of the camera that reported the detection.
- **`locationUuid` (string)**: Location where the detection occurred.
- **`vehicleLicensePlate` (string)**: The recognized license plate string.
- **`matchingLicensePlates` (string\[])**: Plate strings considered full matches for this detection.
- **`partialLicensePlates` (string\[])**: Plate strings considered partial matches for this detection.
- **`imageS3Key` (string)**: S3 key for the full detection image. This is a storage key, not a URL.
- **`thumbnailS3Key` (string)**: S3 key for the detection thumbnail. This is a storage key, not a URL.
- **`eventTimestamp` (integer)**: When the detection occurred, in epoch milliseconds.
- **`name` (string)**: Vehicle name, if the plate is associated with a saved vehicle.

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

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

## 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.

```python Python
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
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
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
  }'
```

### Request fields

- **`licensePlate` (body, string, required)**: The plate number to search for.
- **`startTime` (body, integer)**: Start of the search window in epoch milliseconds. Note the field name is `startTime`, not `startTimeMs`.
- **`endTime` (body, integer)**: End of the search window in epoch milliseconds.
- **`deviceUuids` (body, string\[])**: Limit the search to these camera UUIDs.
- **`fuzzy` (body, boolean)**: When `true`, allows approximate matching for misread characters.

> **Warning**: The `forcedFuzziness` field is deprecated. Use the boolean `fuzzy` flag instead.

### Response fields

The `vehicleEvents` array contains all the [vehicle event fields](https://developer.rhombus.com/implementations/lpr-vehicle#response-fields) from Workflow 1, plus two search-specific fields:

- **`searchMatchedTerm` (string)**: The plate term that matched your query.
- **`searchMatchedType` (string)**: How the match was made (for example, exact versus fuzzy).

## 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

```python Python
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
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
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
  }'
```

- **`vehicleLicensePlate` (body, string, required)**: The plate that identifies this saved vehicle.
- **`createdAtMillis` (body, integer)**: Creation timestamp in epoch milliseconds.
- **`alert` (body, boolean)**: Whether to raise an alert when this vehicle is detected.
- **`trust` (body, boolean)**: Whether this vehicle is trusted (known/safe).
- **`name` (body, string)**: Display name for the vehicle.
- **`description` (body, string)**: Free-text description.
- **`thumbnailS3Key` (body, string)**: S3 key for a thumbnail image of the vehicle.

### List saved vehicles

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

```python Python
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
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
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 '{}'
```

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

- **`licensePlate` (string)**: The plate that identifies the saved vehicle.
- **`orgUuid` (string)**: Organization the vehicle belongs to.
- **`createdAtMillis` (integer)**: When the vehicle was saved, in epoch milliseconds.
- **`alert` (boolean)**: Whether detections raise an alert.
- **`trust` (boolean)**: Whether the vehicle is trusted.
- **`name` (string)**: Display name.
- **`description` (string)**: Free-text description.
- **`thumbnailS3Key` (string)**: S3 key for the vehicle thumbnail.

### 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`.

```python Python
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
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
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"
  }'
```

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.

```python Python
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
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
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 '{}'
```

### 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.

```python Python
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
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
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"]
  }'
```

### Delete a saved vehicle

Remove a vehicle from your watchlist by its plate.

```python Python
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
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
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"}'
```

> **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.

## 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`.

```python Python
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
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
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"
  }'
```

- **`deviceUuid` (body, string, required)**: The camera UUID to report on.
- **`timestampMs` (body, integer)**: Anchor time for the report, as a UNIX timestamp in milliseconds.
- **`interval` (body, string, required)**: Reporting bucket. One of `HOURLY`, `DAILY`, `WEEKLY`, or `MONTHLY`.

> **Warning**: The `dateLocal` field is deprecated. Use `timestampMs` instead.

The response `licensePlateEvents` array uses the same [vehicle event fields](https://developer.rhombus.com/implementations/lpr-vehicle#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.

```python Python
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
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
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
```

> **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.

## Use cases

- **Fleet and vendor tracking**: Save your fleet and approved vendor plates with the `trust` flag, then reconcile them against detection events to confirm on-time arrivals.
- **Watchlist alerting**: Save plates of interest with `alert: true` and pair detections with webhooks to notify security when a flagged vehicle is seen.
- **Parking and access analytics**: Use per-device reports to count daily or weekly vehicle traffic at a gate or lot entrance.
- **Investigation and audit**: Fuzzy-search a partial plate from an incident, then export the matching events as CSV for a report.

## Troubleshooting

**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.

**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.

**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.

**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.

**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](https://console.rhombussystems.com/settings/integrations/api-tokens/) under **Settings → Integrations & Developer Resources → API Tokens**.

## Next steps

- **[Faces & People Counting](https://developer.rhombus.com/implementations/faces-people-counting)**: Detect and identify people, and count occupancy alongside your vehicle analytics
- **[Webhook Notifications](https://developer.rhombus.com/webhooks)**: Receive real-time notifications when a watchlisted vehicle is detected
- **[API Reference](https://developer.rhombus.com/api-reference/vehicle-webservice/get-vehicle-events)**: Explore complete request and response schemas for every vehicle endpoint
