VisionAlert API Reference
Welcome to the Plate Recognizer VisionAlert API! Use our API to create camera monitoring logs and detect issues such as camera blockage, movement, blurry images, or glare.
For detailed instructions on how to set up VisionAlert, go here.
VisionAlert Cloud API​
Authentication​
All API calls must include an Authorization header containing the API Token in below format:
Authorization: Token YOUR_API_TOKEN
For the commands below, make sure to replace YOUR_API_TOKEN with your API Token. For example, Authorization: Token abcdef123456xxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Get your token from here.
Create Camera Monitoring Log​
This VisionAlert API endpoint creates a camera monitoring log by analyzing an uploaded image for issues such as camera blockage, movement, blurry images, or glare.
HTTP Request​
POST https://api.platerecognizer.com/v1/vision-alert/create-log/
- Content-Type:
multipart/form-data - The
CORSpolicy of this endpoint allows requests from all origins.
POST Parameters​
| Parameter | Required | Description |
|---|---|---|
| upload | Yes | The image file to be analyzed for camera issues. |
| camera_id | Yes | Unique identifier for the camera submitting the image for analysis. |
| tag | No | Tag to associate with the camera. If the tag does not exist, it will be created. If the camera is not already associated with the tag, it will be added. Existing tags are preserved. |
- Shell
- Python
# Upload an image for camera monitoring analysis
curl -X POST \
-H "Authorization: Token YOUR_API_TOKEN" \
-F "camera_id=camera1" \
-F "tag=TAG-XX" \
-F "upload=@/path/to/image.png" \
https://api.platerecognizer.com/v1/vision-alert/create-log/
import requests
# Upload an image for camera monitoring analysis
with open('/path/to/image.png', 'rb') as image_file:
response = requests.post(
'https://api.platerecognizer.com/v1/vision-alert/create-log/',
files={'upload': image_file},
data={
'camera_id': 'camera1',
'tag': 'TAG-XX'
},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response​
The API will merely receive send images and return a success message. This is because VisionAlert analyzes all the footage asynchronously, making the results available through the VisionAlert dashboard or webhooks if configured, within an hour from the last image was uploaded.
If successful, the API will return:
{
"message": "Log created successfully."
}
Otherwise, the response is an error message, such as the following:
{
"message": "Camera already uploaded a log recently."
}
The above response indicates that the camera has already uploaded a log recently, and the API will not process the request.
Rate Limits​
- 1 request per second, for any camera is applied, as per our general API rate limiting policy.
- 1 request every 15 minutes for each camera, meaning that each camera can only upload one image every 15 minutes for analysis.
Errors​
| Error Code | Meaning |
|---|---|
| 400 | Bad Request: Missing required parameters or invalid image format |
| 401 | Unauthorized: Invalid or missing API token |
| 403 | Forbidden: VisionAlert is not enabled for your account |
| 429 | Too Many Requests: Rate limit exceeded |
The following endpoints let you retrieve licenses, cameras, logs, and alerts. You can only access resources belonging to your own licenses.
Base URL: https://app.platerecognizer.com/v1/vision-alert/
Pagination​
The camera, log, and alert list endpoints use cursor-based pagination. Their responses are wrapped in a pagination envelope instead of returning a bare array:
{
"next": "https://app.platerecognizer.com/v1/vision-alert/5/cameras/?cursor=cD0yMDI2LTA0LTEw",
"previous": null,
"results": []
}
| Field | Type | Description |
|---|---|---|
next | string | null | Opaque URL of the next page, or null on the last page |
previous | string | null | Opaque URL of the previous page, or null on the first page |
results | array | Items for the current page |
To page through results, follow the next and previous URLs returned in each response. These embed an opaque cursor value — do not construct or modify cursors yourself. Results are ordered newest-first by created.
Query Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
page_size | integer | No | Items per page (default 50, max 200) |
List Licenses endpoint is not paginated and returns a bare array.
Date Filtering​
The log and alert list endpoints accept start and end query parameters to filter results by their created time. Each accepts either:
- a date —
YYYY-MM-DD - a full ISO 8601 timestamp —
2026-06-29T14:30:00Z
Naive timestamps (no UTC offset) are assumed to be in the server timezone.
| Param | Date form (YYYY-MM-DD) | Timestamp form |
|---|---|---|
start | created >= start (00:00 of day) | created >= timestamp |
end | created <= end (23:59:59 of day) | created <= timestamp (exact) |
Example:
GET https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/logs/?start=2026-06-29T00:00:00Z&end=2026-06-29T12:00:00Z
Invalid values return 400 with:
Enter a valid date (YYYY-MM-DD) or ISO 8601 timestamp.
List Licenses​
Retrieve all VisionAlert licenses for the authenticated user, ordered by most recent first.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/licenses/
- Shell
- Python
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/licenses/"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/licenses/',
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
Returns a JSON array of license objects.
[
{
"id": 5,
"code": "LIC-ABC123",
"size": 50,
"va_type": "meraki",
"expiration": "2027-01-15T00:00:00Z",
"created": "2026-01-15T10:30:00Z",
"modified": "2026-04-10T14:22:00Z"
}
]
Response Fields​
| Field | Type | Description |
|---|---|---|
id | integer | License ID (used as license_id in other endpoints) |
code | string | License code |
size | integer | Maximum number of cameras allowed |
va_type | string | License type (e.g. meraki, openeye, ftp, nx) |
expiration | datetime | When the license expires |
created | datetime | When the license was created |
modified | datetime | When the license was last updated |
List Cameras​
Retrieve all cameras under a specific VisionAlert license.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/{license_id}/cameras/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
Query Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter cameras by latest log status. Possible values: normal, anomaly, under_review, offline, config_issue, no_data, pending_retry |
- Shell
- Python
# List all cameras for license ID 5
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/"
# Filter by status
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/?status=anomaly"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/5/cameras/',
params={'status': 'anomaly'},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
Returns a paginated list of camera objects, ordered by most recent first (newest created first).
{
"next": null,
"previous": null,
"results": [
{
"id": 42,
"serial": "Q2GV-ABCD-1234",
"name": "Front Entrance",
"license": "LIC-ABC123",
"tags": ["site-a", "floor-1"],
"notes": "Installed 2026-01-15",
"latest_status": "normal",
"created": "2026-01-15T10:30:00Z",
"modified": "2026-04-10T14:22:00Z"
}
]
}
Response Fields​
| Field | Type | Description |
|---|---|---|
id | integer | Camera ID |
serial | string | Camera serial number |
name | string | Camera display name |
license | string | License code |
tags | string[] | List of tag names assigned to the camera |
notes | string | Optional notes for this camera |
latest_status | string | null | Status from the most recent log. null if no logs exist (equivalent to no_data) |
created | datetime | When the camera was registered |
modified | datetime | When the camera was last updated |
List Camera Logs​
Retrieve log entries for a specific camera under a license.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/{license_id}/cameras/{serial}/logs/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
serial | string | Camera serial number |
Query Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
start | date | datetime | No | Filter logs created on or after this date or timestamp. See Date Filtering. |
end | date | datetime | No | Filter logs created up to this date or timestamp (whole day inclusive for dates). See Date Filtering. |
status | string | No | Filter by log status. Possible values: normal, anomaly, under_review, offline, config_issue, no_data, pending_retry |
This endpoint is paginated.
- Shell
- Python
# Logs for camera C1 within a date range
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/logs/?start=2026-04-01&end=2026-04-10"
# Only anomaly logs
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/logs/?status=anomaly"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/logs/',
params={'start': '2026-04-01', 'end': '2026-04-10', 'status': 'anomaly'},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
Returns a paginated list of camera log objects, ordered by most recent first.
{
"next": null,
"previous": null,
"results": [
{
"id": 1001,
"camera_serial": "Q2GV-ABCD-1234",
"camera_name": "Front Entrance",
"status": "anomaly",
"anomalies": {
"Blur": 0.87,
"Obstruction": 0.65
},
"snapshot": "https://app.platerecognizer.com/media/camera_snapshot/04/10/1430_aB3cD_front.jpg",
"created": "2026-04-10T14:30:00Z"
}
]
}
Response Fields​
| Field | Type | Description |
|---|---|---|
id | integer | Log entry ID |
camera_serial | string | Serial of the camera that generated this log |
camera_name | string | Display name of the camera |
status | string | Log status (normal, anomaly, under_review, offline, config_issue, pending_retry) |
anomalies | object | {} | Dictionary of detected anomalies and their scores. Only includes anomalies that exceed the camera's configured thresholds. Empty object if none. |
snapshot | string | null | Absolute URL to the snapshot image. null if no snapshot is available. |
created | datetime | When the log was created |
List License Logs​
Retrieve log entries across all cameras under a license. Useful for reviewing recent activity for an entire site without iterating over cameras one by one.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/{license_id}/logs/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
Query Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
start | date | datetime | No | Filter logs created on or after this date or timestamp. See Date Filtering. |
end | date | datetime | No | Filter logs created up to this date or timestamp (whole day inclusive for dates). See Date Filtering. |
status | string | No | Filter by log status. Possible values: normal, anomaly, under_review, offline, config_issue, no_data, pending_retry |
serial | string | No | Filter by camera serial number |
tag | string | No | Filter by a tag name assigned to the camera |
This endpoint is paginated.
- Shell
- Python
# All logs for license ID 5 within a date range
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/logs/?start=2026-04-01&end=2026-04-10"
# Anomaly logs for a specific camera serial
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/logs/?serial=Q2GV-ABCD-1234&status=anomaly"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/5/logs/',
params={'start': '2026-04-01', 'end': '2026-04-10', 'tag': 'site-a'},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
Returns a paginated list of camera log objects across all cameras under the license, ordered by most recent first. Each object has the same fields as List Camera Logs.
{
"next": null,
"previous": null,
"results": [
{
"id": 1001,
"camera_serial": "Q2GV-ABCD-1234",
"camera_name": "Front Entrance",
"status": "anomaly",
"anomalies": {
"Blur": 0.87
},
"snapshot": "https://app.platerecognizer.com/media/camera_snapshot/04/10/1430_aB3cD_front.jpg",
"created": "2026-04-10T14:30:00Z"
},
{
"id": 1000,
"camera_serial": "Q2GV-EFGH-5678",
"camera_name": "Parking Lot B",
"status": "normal",
"anomalies": {},
"snapshot": "https://app.platerecognizer.com/media/camera_snapshot/04/10/1415_kL7mN_lot.jpg",
"created": "2026-04-10T14:15:00Z"
}
]
}
Delete Camera​
Delete a camera under a license. This also removes the camera's logs and reference images.
HTTP Request​
DELETE https://app.platerecognizer.com/v1/vision-alert/{license_id}/cameras/{serial}/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
serial | string | Camera serial number |
- Shell
- Python
# Delete camera C1 from license ID 5
curl -X DELETE \
-H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/"
import requests
response = requests.delete(
'https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/',
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.status_code) # 204
Response 204 No Content​
Deletion successful. Returns 404 Not Found if no camera with that serial exists under the license.
Get Camera Reference Image​
Retrieve the URL of the camera's current reference image. The reference image is the baseline used to detect anomalies such as camera movement or obstruction.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/{license_id}/cameras/{serial}/reference/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
serial | string | Camera serial number |
- Shell
- Python
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/reference/"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/reference/',
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
{
"reference_image": "https://app.platerecognizer.com/media/camera_reference/01/15/0900_xY9zW_front.jpg"
}
reference_image is null if no reference image has been set for the camera.
Set Camera Reference Image​
Upload a new reference image for a camera. The uploaded image becomes the camera's current reference; the system retains previous reference images for historical alerts.
HTTP Request​
POST https://app.platerecognizer.com/v1/vision-alert/{license_id}/cameras/{serial}/reference/
- Content-Type:
multipart/form-data
POST Parameters​
| Parameter | Required | Description |
|---|---|---|
| upload | Yes | The image file to set as the reference. |
- Shell
- Python
curl -X POST \
-H "Authorization: Token YOUR_API_TOKEN" \
-F "upload=@/path/to/image.jpg" \
"https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/reference/"
import requests
with open('/path/to/image.jpg', 'rb') as image_file:
response = requests.post(
'https://app.platerecognizer.com/v1/vision-alert/5/cameras/C1/reference/',
files={'upload': image_file},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 201 Created​
{
"message": "Reference image updated."
}
Errors​
| Error Code | Meaning |
|---|---|
| 400 | Bad Request: No image provided, or the file is not a valid image |
| 404 | Not Found: No camera with that serial exists under the license |
List Anomaly Alerts​
Retrieve anomaly alerts generated for a license.
HTTP Request​
GET https://app.platerecognizer.com/v1/vision-alert/{license_id}/alerts/
Path Parameters​
| Parameter | Type | Description |
|---|---|---|
license_id | integer | ID of the VisionAlert license |
Query Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
start | date | datetime | No | Filter alerts created on or after this date or timestamp. See Date Filtering. |
end | date | datetime | No | Filter alerts created up to this date or timestamp (whole day inclusive for dates). See Date Filtering. |
license | string | No | Filter by license code |
sent | boolean | No | Filter by whether the alert notification was sent (true/false) |
- Shell
- Python
# All sent alerts for a license
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/alerts/?sent=true"
# Alerts within a date range
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.platerecognizer.com/v1/vision-alert/5/alerts/?start=2026-04-01&end=2026-04-14"
import requests
response = requests.get(
'https://app.platerecognizer.com/v1/vision-alert/5/alerts/',
params={'sent': 'true', 'start': '2026-04-01', 'end': '2026-04-14'},
headers={'Authorization': 'Token YOUR_API_TOKEN'}
)
print(response.json())
Response 200 OK​
Returns a paginated list of anomaly alert objects, ordered by most recent first.
{
"next": null,
"previous": null,
"results": [
{
"id": 500,
"license": "LIC-ABC123",
"sent": true,
"cameras": [
{
"serial": "Q2GV-ABCD-1234",
"name": "Front Entrance",
"status": "Anomaly",
"anomalies": {
"Blur": 0.87
},
"snapshot": "https://app.platerecognizer.com/media/camera_snapshot/04/10/1430_aB3cD_front.jpg",
"reference_image": "https://app.platerecognizer.com/media/camera_reference/01/15/0900_xY9zW_front.jpg"
},
{
"serial": "Q2GV-EFGH-5678",
"name": "Parking Lot B",
"status": "Offline",
"anomalies": {},
"snapshot": null,
"reference_image": null
}
],
"created": "2026-04-10T15:00:00Z"
}
]
}
Response Fields​
| Field | Type | Description |
|---|---|---|
id | integer | Alert ID |
license | string | License code |
sent | boolean | Whether notification (email/webhook) was sent for this alert |
cameras | object[] | List of cameras involved in this alert |
cameras[].serial | string | Camera serial number |
cameras[].name | string | Camera display name |
cameras[].status | string | Camera status display label (e.g. "Anomaly", "Offline", "Normal") |
cameras[].anomalies | object | Detected anomalies with scores, above threshold. Empty object if none. |
cameras[].snapshot | string | null | URL to the snapshot that triggered this alert. null if no snapshot is available. |
cameras[].reference_image | string | null | URL to the camera's reference image at the time of the alert. null if none is set. |
created | datetime | When the alert was created |
Status Codes Summary​
| Code | Description |
|---|---|
200 | Success — returns the requested data |
201 | Created — resource created successfully |
204 | No Content — resource deleted successfully |
400 | Bad Request — Missing or invalid parameters |
401 | Unauthorized — Invalid or missing API token |
403 | Forbidden — Resource does not belong to the authenticated user |
404 | Not Found — Resource does not exist under your license |
Enum Reference​
Camera / Log Status​
| Value | Description |
|---|---|
normal | Camera is operating normally |
anomaly | Anomaly detected (blur, obstruction, glare, or position change) |
under_review | Log is awaiting manual review |
offline | Camera is offline / unreachable |
config_issue | Configuration error |
no_data | No logs received yet |
pending_retry | Processing failed, scheduled for retry |
Anomaly Types​
| Key | Description |
|---|---|
Blur | Image blur detected |
Obstruction | Camera view is obstructed |
Glare | Glare or overexposure detected |
Position change | Camera has shifted position |