# Working with Snaps

This guide walks you through managing Snaps programmatically using Luxonis Hub GraphQL API. You'll learn how to list snaps,
retrieve detailed information, and delete them.

> **Creating Snaps**
> To
> **send or create**
> Snaps from your applications, you must use the DepthAI. Check out the
> [Snaps in DepthAI](https://docs.luxonis.com/software-v3/depthai/tutorials/snaps.md)
> documentation for details on how to emit Snaps from your applications.
> This guide focuses on
> **querying, filtering, and managing**
> existing Snaps via GraphQL API.

## Prerequisites

Before starting, you should be familiar with GraphQL basics. If you're new to GraphQL, check out [About
GraphQL](https://docs.luxonis.com/cloud/api/graphql.md).

You'll also need an API key to authenticate your requests.

### Step 1: Obtain API Key

To interact with Luxonis Hub API, you need an API key. API keys provide full access to your team's resources.

[Follow API Keys documentation](https://docs.luxonis.com/cloud/api/api-keys.md) to create a key in the Luxonis Hub web UI.

Once you have your API key, include it in the Authorization header:

```bash
Authorization: Bearer <your_api_key>
```

### Step 2: List Snaps

Use the snaps query to retrieve a list of all snaps in your team. This query supports cursor-based pagination for efficient
navigation through large datasets.

### Basic List Query

```graphql
query {
  team {
    snaps(first: 10) {
      nodes {
        id
        name
        createdAt
        tags
        extras
        files {
          id
          name
          classification
        }
        sourceDeviceId
        sourceAppIdentifier
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}
```

Query breakdown:

 * first: 10 - limits results to 10 snaps
 * nodes - array of snap objects
 * pageInfo - pagination metadata (cursor for next page)

Snap fields explained:

 * id: Unique snap identifier
 * name: Snap name (e.g., "car_detected", "data_collection")
 * createdAt: Timestamp when snap was created
 * tags: Array of tags for grouping (e.g., "night", "dataset_v2")
 * extras: JSON object with custom key-value pairs for searchable metadata
 * files: Array of attached files (images, videos, point clouds, etc.)
 * sourceDeviceId: Device ID that created the snap
 * sourceAppIdentifier: App that created the snap

### Pagination

To fetch the next page, use the endCursor from the previous response:

```graphql
query($after: String) {
  team {
    snaps(first: 10, after: $after) {
      nodes {
        id
        name
        createdAt
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}
```

Variables:

```json
{
  "after": "cursor_from_previous_response"
}
```

### Filtering Snaps

Filter snaps by various criteria to find specific data:

Filter by time range:

```graphql
query($from: DateTime!, $to: DateTime!) {
  team {
    snaps(
      first: 10,
      filter: {
        createdFrom: $from,
        createdTo: $to
      }
    ) {
      nodes {
        id
        name
        createdAt
      }
    }
  }
}
```

Variables:

```json
{
  "from": "2024-01-01T00:00:00Z",
  "to": "2024-02-01T00:00:00Z"
}
```

Filter by device:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { deviceId: "device-id" }
    ) {
      nodes {
        id
        name
        sourceDeviceId
      }
    }
  }
}
```

Filter by app identifier:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { deviceAppIdentifier: "my-app" }
    ) {
      nodes {
        id
        name
        sourceAppIdentifier
      }
    }
  }
}
```

Filter by name:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { name: "car_detected" }
    ) {
      nodes {
        id
        name
      }
    }
  }
}
```

Filter by tags:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { tags: ["night", "validation"] }
    ) {
      nodes {
        id
        name
        tags
      }
    }
  }
}
```

Filter by extras (custom metadata):

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { extras: { scene: "warehouse", lighting: "low" } }
    ) {
      nodes {
        id
        name
        extras
      }
    }
  }
}
```

Filter by file classification:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { withFilesClassifiedAs: [IMAGE_COLOR, VIDEO] }
    ) {
      nodes {
        id
        name
        files {
          classification
        }
      }
    }
  }
}
```

Available file classifications:

 * IMAGE_COLOR: Color images
 * IMAGE_STEREO_LEFT: Left stereo image
 * IMAGE_STEREO_RIGHT: Right stereo image
 * VIDEO: Video files
 * POINTCLOUD: Point cloud data
 * ANNOTATION: Annotation files
 * DISPARITY: Disparity maps
 * UNKNOWN_FILE: Other file types

Combine multiple filters:

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: {
        deviceId: "device-id",
        tags: ["validation"],
        createdFrom: "2024-01-01T00:00:00Z"
      }
    ) {
      nodes {
        id
        name
        tags
        createdAt
      }
    }
  }
}
```

### Step 3: Load Individual Snap

Retrieve detailed information about a specific snap using its ID, including file download URLs.

```graphql
query($snapId: ID!) {
  team {
    snap(snapId: $snapId) {
      id
      name
      createdAt
      tags
      extras
      files {
        id
        name
        hash
        mimeType
        size
        presignedUrl
        classification
      }
      sourceDeviceId
      sourceSerialNumber
      sourceAppIdentifier
    }
  }
}
```

Variables:

```json
{
  "snapId": "snap-id-from-list"
}
```

Response example:

```json
{
  "data": {
    "team": {
      "snap": {
        "id": "snap-abc123",
        "name": "car_detected",
        "createdAt": "2024-01-15T10:30:00Z",
        "tags": ["validation", "warehouse"],
        "extras": { "scene": "warehouse", "lighting": "low" },
        "files": [
          {
            "id": "file-xyz789",
            "name": "image.jpg",
            "hash": "abc123...",
            "mimeType": "image/jpeg",
            "size": 524288,
            "presignedUrl": "https://storage.example.com/snap-abc123/image.jpg?signature=...",
            "classification": "IMAGE_COLOR"
          }
        ],
        "sourceDeviceId": "device-123",
        "sourceSerialNumber": "OAK123456",
        "sourceAppIdentifier": "detection-app"
      }
    }
  }
}
```

Key fields explained:

 * presignedUrl: Direct, time-limited URL to download the file. Use this URL to download files without authentication.
 * hash: File checksum for integrity verification
 * mimeType: MIME type of the file (e.g., "image/jpeg", "video/mp4")
 * size: File size in bytes
 * sourceSerialNumber: Device serial number that created the snap
 * sourceAppIdentifier: Application identifier that emitted the snap

### Step 4: Delete Snaps

Delete snaps using either their IDs or by applying filters. Deletion happens asynchronously as a background task.

> **Asynchronous Deletion**
> Snap deletion is not immediate. The API returns a
> `bgTaskId`
> that you can use to track deletion progress.

### Method 1: Delete by IDs

Delete specific snaps using their IDs:

```graphql
mutation DeleteSnapsByIds($ids: [ID!]!) {
  team {
    deleteSnapsByIds(ids: $ids) {
      status
      bgTaskId
    }
  }
}
```

Variables:

```json
{
  "ids": ["snap-id-1", "snap-id-2", "snap-id-3"]
}
```

Response:

```json
{
  "data": {
    "team": {
      "deleteSnapsByIds": {
        "status": "SUCCESS",
        "bgTaskId": "bg-task-abc123"
      }
    }
  }
}
```

### Method 2: Delete by Filter

Delete snaps matching specific criteria:

```graphql
mutation DeleteSnapsByFilter {
  team {
    deleteSnapsByFilter(
      filter: {
        deviceId: "device-id",
        createdFrom: "2024-01-01T00:00:00Z",
        createdTo: "2024-02-01T00:00:00Z",
        tags: ["test"]
      }
    ) {
      status
      bgTaskId
    }
  }
}
```

Available deletion filters:

 * deviceId: Delete snaps from a specific device
 * deviceAppId: Delete snaps from a specific app instance
 * deviceAppIdentifier: Delete snaps from apps with this identifier
 * createdFrom: Delete snaps created after this timestamp
 * createdTo: Delete snaps created before this timestamp
 * name: Delete snaps with this name
 * tags: Delete snaps with these tags
 * extras: Delete snaps with these custom metadata
 * withFilesClassifiedAs: Delete snaps containing files of this classification

### Check Deletion Status

Track deletion progress using the bgTaskId:

```graphql
query($bgTaskId: ID!) {
  team {
    bgTask(bgTaskId: $bgTaskId) {
      id
      state {
        deletedCount
        totalCount
      }
      createdAt
      completedAt
      failedAt
    }
  }
}
```

Variables:

```json
{
  "bgTaskId": "bg-task-id-from-deletion"
}
```

Response (in progress):

```json
{
  "data": {
    "team": {
      "bgTask": {
        "id": "bg-task-abc123",
        "state": {
          "deletedCount": 150,
          "totalCount": 500
        },
        "createdAt": "2024-01-15T11:00:00Z",
        "completedAt": null,
        "failedAt": null
      }
    }
  }
}
```

Response (completed):

```json
{
  "data": {
    "team": {
      "bgTask": {
        "id": "bg-task-abc123",
        "state": {
          "deletedCount": 500,
          "totalCount": 500
        },
        "createdAt": "2024-01-15T11:00:00Z",
        "completedAt": "2024-01-15T11:05:30Z",
        "failedAt": null
      }
    }
  }
}
```

### Status Values

The status field in deletion response can be:

 * SUCCESS: Deletion task created successfully
 * IDS_NOT_FROM_TEAM: One or more snap IDs don't belong to your team
 * BG_TASK_LIMIT_REACHED: Too many background tasks running, try again later

## Summary

In this guide, you learned how to:

 * List snaps with pagination and filtering
 * Retrieve detailed information about individual snaps
 * Download snap files using presigned URLs
 * Delete snaps by IDs or using filters
 * Track deletion progress via background tasks

> **Key Takeaways**
> - Use
> **tags and extras**
> for effective snap organization and searching
> - Leverage
> **filters**
> to query specific subsets of your data
> - **Deletion is async**
> - always check
> `bgTaskId`
> for progress
> - **Presigned URLs**
> are time-limited - download files promptly

## Next Steps

 * Check out [Snaps feature documentation](https://docs.luxonis.com/cloud/features/event-storage/snaps.md) to learn about managing
   snaps via the Luxonis Hub UI
 * Learn how to [send snaps from your applications](https://docs.luxonis.com/software-v3/depthai/tutorials/snaps.md) using DepthAI
 * Explore the [full schema reference](https://docs.luxonis.com/cloud/api/reference/control-api/schema.md) for all snap-related
   types and mutations
 * Discover more [automation guides](https://docs.luxonis.com/cloud/api/guides.md) for additional API integration examples
