> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/deployment/monitoring-and-analytics/vision-events/query-events.md).

# Query Events

## About

This page covers how to find specific [Vision Events](/deployment/monitoring-and-analytics/vision-events.md) - the timestamped records of what your deployed models observed - by filtering and searching them in the Vision Events dashboard or programmatically through the REST API. Narrow results by date range, event type, device, stream, workflow, detected class, or feedback status to audit production behavior and build reports.

## Web App

### Query and Filter Events

Find specific events using filters in the Vision Events dashboard or query them programmatically via the REST API.

#### Browse Events in the Dashboard

**Select a Use Case**

From the Vision Events page, click on a Use Case to view its events. Events are displayed in reverse chronological order.

<figure><img src="/files/IHQTHZPRJSXHhe8aFl1n" alt="" width="375"><figcaption></figcaption></figure>

**Filter Events**

Use the filter controls at the top of the events list to narrow results by:

* **Date range** - start and end timestamps
* **Event type** - quality\_check, inventory\_count, safety\_alert, custom, operator\_feedback
* **Device** - filter by device ID
* **Stream** - filter by stream or camera ID
* **Workflow** - filter by the workflow that generated events
* **Detection** - filter by a detected object class, with an optional confidence threshold
* **Feedback status** - correct, incorrect, inconclusive, or no feedback
* **Custom metadata** - filter by any custom metadata field and value
* **Warnings** - show only events that had ingestion warnings

You can also click on values in the event detail sidebar (such as device ID, stream, quality check result, or custom metadata values) to quickly add them as filters.

Filter chips are editable -- click on any active filter chip to modify its value or operator without having to remove and re-add it.

When filters are applied, a **total count** of matching events is displayed at the top of the results list. This count updates independently of the event list, so you can see how many events match your filters even while events are still loading.

<figure><img src="/files/eyalX7Vjfh3gxvclAkNV" alt="" width="375"><figcaption></figcaption></figure>

**View Event Details**

Click on any event in the list to view its full details:

* The source image and any output images
* All source metadata (device, stream, workflow)
* Object detections, classifications, and segmentations with their confidence scores
* Event-type-specific data (ex: pass/fail result, item count, alert severity)
* Custom metadata key-value pairs

**Draw Detections**

When an event contains prediction data (object detections, instance segmentations, or keypoints), a "Draw Detections" checkbox appears above the image. Enable it to overlay bounding boxes, segmentation polygons, and labels with confidence scores on top of the source image.

This is useful when your pipeline only persists the original input image and you want to visualize what the model detected without storing a separate output image.

{% hint style="info" %}
The checkbox is hidden when viewing a distinct output image, since those already have detections rendered.
{% endhint %}

**Auto-Finalized Events**

An event flagged as auto-finalized was closed automatically on the edge device before its video finished uploading, so the video is missing. The event still carries its result and still images. The event card shows an indicator, and the detail view shows the time it was finalized. This applies only to events synced through [Edge Device Backup](/deployment/monitoring-and-analytics/vision-events/send-events.md#edge-device-backup).

## HTTP API

### Query Events via the API

The query endpoint supports the same filters as the dashboard, plus cursor-based pagination. For the full list of parameters and response fields, see the [Vision Events API Reference](https://docs.roboflow.com/deployment/monitoring-and-analytics/vision-events#http-api).

#### Basic Query

```bash
curl -X POST "https://api.roboflow.com/vision-events/query" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "useCaseId": "assembly-line-qa",
    "startTime": "2026-03-01T00:00:00Z",
    "endTime": "2026-03-31T23:59:59Z",
    "limit": 25
  }'
```

**Response:**

```json
{
  "events": [
    {
      "eventId": "evt-789ghi",
      "eventType": "quality_check",
      "timestamp": "2026-03-30T14:30:00.000Z",
      "deviceId": "factory-cam-01",
      "streamId": "line-3",
      "images": [],
      "eventData": { "result": "fail" },
      "customMetadata": {
        "line_id": "line-3",
        "shift": "morning",
        "part_number": "PN-4421"
      }
    }
  ],
  "nextCursor": "eyJ0cyI6IjIwMjYtMDMtMzAifQ==",
  "hasMore": true
}
```

#### Pagination

Results are paginated using a cursor. If the response includes a `nextCursor` value and `hasMore` is `true`, pass the cursor in your next request to retrieve the next page:

```bash
curl -X POST "https://api.roboflow.com/vision-events/query" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "useCaseId": "assembly-line-qa",
    "limit": 25,
    "cursor": "eyJ0cyI6IjIwMjYtMDMtMzAifQ=="
  }'
```

Continue until `hasMore` is `false`.

#### Filter by Event Type

Query a single event type:

```json
{
  "useCaseId": "assembly-line-qa",
  "eventType": "quality_check"
}
```

Or multiple event types (max 20):

```json
{
  "useCaseId": "assembly-line-qa",
  "eventTypes": ["quality_check", "operator_feedback"]
}
```

#### Filter by Feedback Status

Use `feedbackStatus` to find events based on whether operators have reviewed them and how they were rated:

```json
{
  "useCaseId": "assembly-line-qa",
  "feedbackStatus": ["incorrect", "none"]
}
```

Valid values: `correct`, `incorrect`, `inconclusive`, `none`. Use `none` to find events that haven't been reviewed yet.

#### Filter by Custom Metadata

Use `customMetadataFilters` to filter events by your own metadata fields:

```json
{
  "useCaseId": "assembly-line-qa",
  "customMetadataFilters": [
    { "key": "line_id", "operator": "eq", "value": "line-3" },
    { "key": "shift", "operator": "eq", "value": "morning" }
  ]
}
```

### Query Vision Events

Query vision events with filters, time ranges, and pagination. This endpoint supports filtering by event type, device context, detection classes, custom metadata, and event-specific fields.

**Required scope:** `vision-events:read` or `device:read`

{% openapi src="/files/sCDP9kVopV4JkkRK7GDd" path="/vision-events/query" method="post" %}
[openapi.yaml](https://1583372177-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-dfdc1702ad3d1a62ad0a661e9609f6bbe2fc8d4c%2Fopenapi.yaml?alt=media)
{% endopenapi %}

#### Example Request

```bash
curl -X POST "https://api.roboflow.com/vision-events/query" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "useCaseId": "a1b3c8e1",
    "startTime": "2024-01-14T00:00:00Z",
    "endTime": "2024-01-15T23:59:59Z",
    "eventTypes": ["quality_check", "safety_alert"],
    "customMetadataFilters": [
      {
        "field": "temperature",
        "operator": "gt",
        "value": 70,
        "type": "number"
      }
    ],
    "limit": 50
  }'
```

#### Request Body Parameters

**Required fields:**

* **`useCaseId`** (string): The use case ID to query events for. See [Use Cases](https://docs.roboflow.com/deployment/monitoring-and-analytics/vision-events/use-cases) for how to find your use case ID.

**Time range filters:**

* **`startTime`** (string, ISO 8601, optional): Start of the time range.
* **`endTime`** (string, ISO 8601, optional): End of the time range.

**Event type filters:**

* **`eventTypes`** (array of strings, max 20, optional): Filter to one or more event types.

**Context filters:**

Each context filter is an object with `operator` and `value`:

* **`deviceId`** (object, optional): Filter by device. Operators: `eq`, `neq`.
* **`streamId`** (object, optional): Filter by stream. Operators: `eq`, `neq`.
* **`workflowId`** (object, optional): Filter by workflow. Operators: `eq`, `neq`.
* **`externalId`** (object, optional): Filter by external ID. Operators: `eq`, `neq`.

```json
{
  "deviceId": { "operator": "eq", "value": "camera-node-5" }
}
```

**Detection filter:**

* **`detection`** (object, optional): Filter events by detection class name, optionally compounded with a per-detection confidence threshold. Operators: `eq`, `neq`, `in`, `not_in`. For `in` and `not_in`, pass an array of strings as the value (max 50).
  * **`confidence`** (object, optional): Per-detection confidence threshold. Only supported with `eq` and `in` class operators. The class and confidence must match on the same detection.
    * **`operator`** (string): One of `gt`, `gte`, `lt`, `lte`.
    * **`value`** (number): Confidence threshold between 0 and 1.

```json
{
  "detection": { "operator": "in", "value": ["defect", "crack"] }
}
```

Filter by class with a minimum confidence:

```json
{
  "detection": {
    "operator": "eq",
    "value": "scratch",
    "confidence": { "operator": "gte", "value": 0.8 }
  }
}
```

{% hint style="info" %}
The `detection` filter was previously named `detectionClass`. The old name is no longer accepted.
{% endhint %}

**Image and warning filters:**

* **`imageCount`** (object, optional): Filter by number of images attached to the event. Operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`.
* **`hasWarnings`** (boolean, optional): Filter to events that have or do not have ingestion warnings.

```json
{
  "imageCount": { "operator": "gte", "value": 1 }
}
```

**Custom metadata filters:**

* **`customMetadataFilters`** (array, max 20, optional): Filter by custom metadata fields. Each filter has:
  * **`field`** (string): The metadata field name.
  * **`operator`** (string): Comparison operator.
  * **`value`**: The value to compare against.
  * **`type`** (string): The value type, one of `string`, `number`, or `boolean`.

Available operators by type:

| Type      | Operators                             |
| --------- | ------------------------------------- |
| `string`  | `eq`, `neq`, `in`, `not_in`           |
| `number`  | `eq`, `neq`, `gt`, `gte`, `lt`, `lte` |
| `boolean` | `eq`, `neq`                           |

**Event field filters:**

* **`eventFieldFilters`** (array, max 20, optional): Filter by event-specific fields. Each filter has:
  * **`column`** (string): One of `result`, `location`, `item_count`, `item_type`, `alert_type`, `severity`, or `feedback`.
  * **`operator`** (string): Comparison operator (`eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `not_in`).
  * **`value`**: The value to compare against.

```json
{
  "eventFieldFilters": [
    { "column": "result", "operator": "eq", "value": "fail" }
  ]
}
```

**Pagination:**

* **`cursor`** (string, optional): Cursor from a previous response to fetch the next page.
* **`limit`** (number, optional, default 100, max 1000): Number of events to return per page.

#### Example Response

{% tabs %}
{% tab title="200" %}

```json
{
  "events": [
    {
      "eventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "eventType": "quality_check",
      "timestamp": "2024-01-15T10:30:00.000Z",
      "images": [
        {
          "label": "inspection-photo",
          "objectDetections": [
            {
              "class": "defect",
              "x": 100,
              "y": 200,
              "width": 50,
              "height": 30,
              "confidence": 0.95
            }
          ]
        }
      ],
      "eventData": {
        "result": "fail",
        "externalId": "batch-001"
      },
      "customMetadata": {
        "line": "A1",
        "temperature": 72.5
      }
    }
  ],
  "hasMore": false,
  "lookbackDays": 14
}
```

When `hasMore` is `true`, use the `nextCursor` value in your next request to retrieve the next page of results:

```json
{
  "events": [...],
  "hasMore": true,
  "nextCursor": "eyJ0aW1lc3RhbXAiOiIyMDI0LTAxLTE1IiwiZXZlbnRJZCI6InFjLTAwMSJ9",
  "lookbackDays": 14
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid query: useCaseId is required"
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Insufficient permissions for this resource."
}
```

{% endtab %}
{% endtabs %}

## Python SDK

Query vision events with filters, time ranges, and pagination.

### Single Page Query

Use `query_vision_events()` to fetch a single page of results:

```python
import roboflow

roboflow.login()

rf = roboflow.Roboflow()
ws = rf.workspace()

page = ws.query_vision_events(
    "a1b3c8e1",                          # use case ID (required)
    event_type="quality_check",          # filter by single event type
    start_time="2024-01-14T00:00:00Z",   # ISO 8601 start time
    end_time="2024-01-15T23:59:59Z",     # ISO 8601 end time
    limit=50,                            # max events per page
)

for evt in page["events"]:
    print(evt["eventId"], evt["eventData"])
```

You can also pass additional filters as keyword arguments. These are forwarded directly to the API:

```python
page = ws.query_vision_events(
    "a1b3c8e1",
    event_types=["quality_check", "safety_alert"],
    deviceId={"operator": "eq", "value": "camera-node-5"},
    customMetadataFilters=[
        {"field": "temperature", "operator": "gt", "value": 70, "type": "number"}
    ],
    eventFieldFilters=[
        {"column": "result", "operator": "eq", "value": "fail"}
    ],
)
```

For manual pagination, use the `cursor` parameter with the `nextCursor` value from a previous response:

```python
all_events = []
page = ws.query_vision_events("a1b3c8e1", limit=100)
all_events.extend(page.get("events", []))

while page.get("hasMore"):
    page = ws.query_vision_events("a1b3c8e1", cursor=page["nextCursor"], limit=100)
    all_events.extend(page.get("events", []))
```

### Paginate Through All Results

Use `query_all_vision_events()` to automatically paginate through all matching events. It yields one page of events at a time:

```python
all_events = []

for page in ws.query_all_vision_events(
    "a1b3c8e1",
    event_type="quality_check",
    start_time="2024-01-14T00:00:00Z",
    end_time="2024-01-15T23:59:59Z",
):
    all_events.extend(page)

print(f"Found {len(all_events)} events")
```

For full details on available filters, operators, and response formats, see the [REST API reference](#http-api).
