Skip to content

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.

On this page

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

Prerequisites

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.
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}")

Request fields

startTimeMsintegerbody

Start of the time window (oldest) in epoch milliseconds.

endTimeMsintegerbody

End of the time window (newest) in epoch milliseconds.

deviceUuidFilterstring[]body

Return only events from these camera UUIDs. ANDed with other filters.

locationUuidFilterstring[]body

Return only events from these location UUIDs. ANDed with other filters.

nameQuerystring[]body

Return events whose vehicle name matches one of these values. ORed with other queries.

licensePlateExactQuerystring[]body

Return events whose plate exactly matches one of these values. ORed with other queries.

vehicleLabelQuerystring[]body

Return events tagged with one of these vehicle labels. ORed with other queries.

licensePlateFuzzyQuerystringbody

Return events whose plate approximately matches this partial or complete plate, allowing for character misreads. ORed with other queries.

unnamedQuerybooleanbody

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:

uuidstring

Unique identifier for the vehicle event.

orgUuidstring

Organization the event belongs to.

deviceUuidstring

UUID of the camera that reported the detection.

locationUuidstring

Location where the detection occurred.

vehicleLicensePlatestring

The recognized license plate string.

matchingLicensePlatesstring[]

Plate strings considered full matches for this detection.

partialLicensePlatesstring[]

Plate strings considered partial matches for this detection.

imageS3Keystring

S3 key for the full detection image. This is a storage key, not a URL.

thumbnailS3Keystring

S3 key for the detection thumbnail. This is a storage key, not a URL.

eventTimestampinteger

When the detection occurred, in epoch milliseconds.

namestring

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.

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.

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')}")

Request fields

licensePlatestringbodyrequired

The plate number to search for.

startTimeintegerbody

Start of the search window in epoch milliseconds. Note the field name is startTime, not startTimeMs.

endTimeintegerbody

End of the search window in epoch milliseconds.

deviceUuidsstring[]body

Limit the search to these camera UUIDs.

fuzzybooleanbody

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 from Workflow 1, plus two search-specific fields:

searchMatchedTermstring

The plate term that matched your query.

searchMatchedTypestring

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

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())
vehicleLicensePlatestringbodyrequired

The plate that identifies this saved vehicle.

createdAtMillisintegerbody

Creation timestamp in epoch milliseconds.

alertbooleanbody

Whether to raise an alert when this vehicle is detected.

trustbooleanbody

Whether this vehicle is trusted (known/safe).

namestringbody

Display name for the vehicle.

descriptionstringbody

Free-text description.

thumbnailS3Keystringbody

S3 key for a thumbnail image of the vehicle.

List saved vehicles

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

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')})")

Each entry in the vehicles array is a saved vehicle:

licensePlatestring

The plate that identifies the saved vehicle.

orgUuidstring

Organization the vehicle belongs to.

createdAtMillisinteger

When the vehicle was saved, in epoch milliseconds.

alertboolean

Whether detections raise an alert.

trustboolean

Whether the vehicle is trusted.

namestring

Display name.

descriptionstring

Free-text description.

thumbnailS3Keystring

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.

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())

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.

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)}")

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.

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())

Delete a saved vehicle

Remove a vehicle from your watchlist by its plate.

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())
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.

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')}")
deviceUuidstringbodyrequired

The camera UUID to report on.

timestampMsintegerbody

Anchor time for the report, as a UNIX timestamp in milliseconds.

intervalstringbodyrequired

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

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")

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 under Settings → Integrations & Developer Resources → API Tokens.

Next steps