Skip to main content

How This Helps

Saved views capture filter states as named, reusable queries attached to a dataset. Every view automatically tracks how result counts change over time as new media arrives, and alerting notifies all dataset collaborators when new matches are detected.

Prerequisites

  • A Visual Layer Cloud account with API access.
  • A valid JWT token. See Authentication.
  • A dataset ID. Find it in the browser URL when viewing a dataset (https://app.visual-layer.com/dataset/<dataset_id>/data) or via the Datasets API.

Create a View

Save the current filter state of a dataset as a named view. Monitoring is enabled automatically on all new views, and alerting defaults to enabled.
POST /api/v1/dataset/{dataset_id}/views
Authorization: Bearer <jwt>
Content-Type: multipart/form-data
Pass filter parameters as query parameters on the URL. The view name is sent as a form field.

Parameters

ParameterLocationTypeRequiredDescription
dataset_idpathUUIDYesThe dataset to attach the view to.
nameform fieldstringYesDisplay name for the view. Must be unique within the dataset.
entity_typequerystringNoEntity filter: IMAGES, OBJECTS, or VIDEOS.
thresholdquerynumberNoSimilarity threshold (0–1).
captionquerystringNoSemantic search query to save with the view.
vqlquerystringNoURL-encoded VQL filter array.

Example

curl -X POST \
  -H "Authorization: Bearer <jwt>" \
  -F "name=Damaged windshields" \
  "https://app.visual-layer.com/api/v1/dataset/<dataset_id>/views?threshold=0&entity_type=IMAGES"

Response (200)

{
  "id": "94431831-ceeb-4e21-8c5b-84c78783bd4b",
  "dataset_id": "a981fc0c-2d1f-11f1-a7ca-d2580fa2deac",
  "name": "Damaged windshields",
  "created_at": "2026-03-31T16:47:19.264591",
  "created_by": {
    "user_id": "8f2f00c0-8446-49de-935f-0e9e058cb2a8",
    "email": "rachel@cheyfitz.me",
    "name": "Rachel Cheyfitz"
  },
  "filters": {
    "entity_type": "IMAGES",
    "threshold": "0",
    "caption": null,
    "vql": []
  },
  "stats": {
    "n_images": -1,
    "n_objects": -1,
    "n_video_frames": -1
  },
  "monitoring_enabled": true,
  "monitoring_started_at": "2026-03-31T16:47:19.264591",
  "alerting_enabled": true,
  "total_results": 0,
  "last_results": null
}
Save the id from the response for use with trend, alerting, and delete operations.
The stats fields show -1 at creation time because the view has not yet been evaluated against any data batch. Values populate after the first monitoring evaluation.

List Views

Retrieve all saved views for a dataset, including their current monitoring state and result counts.
GET /api/v1/dataset/{dataset_id}/views
Authorization: Bearer <jwt>

Parameters

ParameterLocationTypeRequiredDescription
dataset_idpathUUIDYesThe dataset to list views for.

Example

curl -H "Authorization: Bearer <jwt>" \
  "https://app.visual-layer.com/api/v1/dataset/<dataset_id>/views"

Response (200)

{
  "views": [
    {
      "id": "94431831-ceeb-4e21-8c5b-84c78783bd4b",
      "dataset_id": "a981fc0c-2d1f-11f1-a7ca-d2580fa2deac",
      "name": "Damaged windshields",
      "created_at": "2026-03-31T16:47:19.264591",
      "created_by": {
        "user_id": "8f2f00c0-8446-49de-935f-0e9e058cb2a8",
        "email": "rachel@cheyfitz.me",
        "name": "Rachel Cheyfitz"
      },
      "filters": {
        "entity_type": "IMAGES",
        "threshold": "1",
        "caption": null,
        "vql": []
      },
      "stats": {
        "n_images": 1875,
        "n_objects": 0,
        "n_video_frames": 0
      },
      "monitoring_enabled": true,
      "monitoring_started_at": "2026-03-31T16:47:19.264591",
      "alerting_enabled": true,
      "total_results": 1875,
      "last_results": "2026-03-31T17:02:08.056090"
    }
  ]
}

Delete a View

Remove a saved view and its associated trend data from a dataset.
DELETE /api/v1/dataset/{dataset_id}/views/{view_id}
Authorization: Bearer <jwt>

Parameters

ParameterLocationTypeRequiredDescription
dataset_idpathUUIDYesThe dataset the view belongs to.
view_idpathUUIDYesThe view to delete.

Example

curl -X DELETE \
  -H "Authorization: Bearer <jwt>" \
  "https://app.visual-layer.com/api/v1/dataset/<dataset_id>/views/<view_id>"
A successful request returns HTTP 200 with a null body. Deleting a view also removes its trend history and stops all associated alerting.

Get View Trend Data

Retrieve the monitoring trend history for a view. Each data point represents one batch evaluation, showing how many new items matched the view filters when that batch was processed.
GET /api/v1/dataset/{dataset_id}/views/{view_id}/trend
Authorization: Bearer <jwt>

Parameters

ParameterLocationTypeRequiredDescription
dataset_idpathUUIDYesThe dataset the view belongs to.
view_idpathUUIDYesThe view to retrieve trend data for. Monitoring must be enabled.

Example

curl -H "Authorization: Bearer <jwt>" \
  "https://app.visual-layer.com/api/v1/dataset/<dataset_id>/views/<view_id>/trend"

Response (200)

{
  "points": [
    {
      "timestamp": "2026-03-31T17:02:08.056090",
      "batch_id": "a863a595-5aaf-45d3-89a9-073a73d59671",
      "count": 1875,
      "cumulative": 1875
    }
  ],
  "total_results": 1875,
  "last_results": "2026-03-31T17:02:08.056090"
}

Trend Point Fields

FieldTypeDescription
timestampdatetimeWhen the batch was processed.
batch_idUUIDThe media batch that was evaluated.
countintegerNumber of new items matching the view filters in this batch.
cumulativeintegerRunning total of all matching items across all evaluated batches.
Returns HTTP 400 if monitoring is not enabled for the view. Returns HTTP 404 if the view does not exist or does not belong to the specified dataset.

Enable or Disable Alerting

Control whether a monitored view sends alert notifications when new matches are detected. Monitoring (trend data collection) continues regardless of this setting.
POST /api/v1/dataset/{dataset_id}/views/{view_id}/alerting
Authorization: Bearer <jwt>
Content-Type: application/json

Parameters

ParameterLocationTypeRequiredDescription
dataset_idpathUUIDYesThe dataset the view belongs to.
view_idpathUUIDYesThe view to configure alerting for.
enabledbody (JSON)booleanYestrue to enable alerts, false to disable.

Request Body

{
  "request": {
    "enabled": true
  }
}
The enabled field is nested inside a request object in the JSON body.

Example

# Disable alerting
curl -X POST \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{"request": {"enabled": false}}' \
  "https://app.visual-layer.com/api/v1/dataset/<dataset_id>/views/<view_id>/alerting"

Response (200)

{
  "alerting_enabled": false
}

Python Example

import requests

VL_BASE_URL = "https://app.visual-layer.com"
JWT_TOKEN = "<your-jwt-token>"
DATASET_ID = "<your-dataset-id>"

headers = {"Authorization": f"Bearer {JWT_TOKEN}"}

# Create a view
resp = requests.post(
    f"{VL_BASE_URL}/api/v1/dataset/{DATASET_ID}/views",
    headers=headers,
    params={"entity_type": "IMAGES", "threshold": 0},
    data={"name": "Damaged windshields"},
)
resp.raise_for_status()
view = resp.json()
view_id = view["id"]
print(f"Created view: {view_id}")
print(f"  Monitoring: {view['monitoring_enabled']}")
print(f"  Alerting: {view['alerting_enabled']}")

# List views
resp = requests.get(
    f"{VL_BASE_URL}/api/v1/dataset/{DATASET_ID}/views",
    headers=headers,
)
resp.raise_for_status()
views = resp.json()["views"]
for v in views:
    print(f"  {v['name']}{v['total_results']} results, alerting={v['alerting_enabled']}")

# Get trend data
resp = requests.get(
    f"{VL_BASE_URL}/api/v1/dataset/{DATASET_ID}/views/{view_id}/trend",
    headers=headers,
)
resp.raise_for_status()
trend = resp.json()
print(f"Trend: {len(trend['points'])} data points, {trend['total_results']} total results")

# Disable alerting (keep monitoring active)
resp = requests.post(
    f"{VL_BASE_URL}/api/v1/dataset/{DATASET_ID}/views/{view_id}/alerting",
    headers=headers,
    json={"request": {"enabled": False}},
)
resp.raise_for_status()
print(f"Alerting: {resp.json()['alerting_enabled']}")

# Delete a view
resp = requests.delete(
    f"{VL_BASE_URL}/api/v1/dataset/{DATASET_ID}/views/{view_id}",
    headers=headers,
)
resp.raise_for_status()
print(f"Deleted view: {view_id}")

Response Codes

See Error Handling for the error response format and Python handling patterns.

Views Endpoints

HTTP CodeMeaningCommon Cause
200Request successful.
400Bad request.Monitoring not enabled for the view (trend/alerting endpoints).
401Unauthorized.Invalid or expired JWT token.
404Not found.Dataset or view does not exist, or the view does not belong to the specified dataset.
422Validation error.Missing required fields or malformed request body.
500Internal server error.Contact support if this persists.

Best Practices

  • Create views before adding media. Monitoring evaluates only batches that arrive after the view was created. Views created after a media addition do not retroactively evaluate older batches.
  • Use descriptive view names. View names appear in alert notifications and trend charts. Clear names like “Damaged windshields” or “Mislabeled training data” make alerts immediately actionable.
  • Disable alerting for informational views. If a view tracks long-term trends but does not require immediate attention, disable alerting to reduce notification noise while keeping trend data collection active.
  • Poll trend data for dashboards. The trend endpoint returns cumulative counts suitable for building monitoring dashboards. Poll periodically after batch additions to track data quality over time.
  • Delete unused views. Each view is evaluated on every batch addition. Removing views that are no longer needed reduces processing overhead.

Notifications API

List, read, and manage alert notifications delivered by monitored views.

Saved Views

Create and manage saved views through the Visual Layer UI.

Monitoring and Alerts

Understand how monitoring and alerting works across your datasets.

Add Media

Add media to datasets, triggering monitoring evaluation on all views.