> For the complete documentation index, see [llms.txt](https://developer.eagle.cool/web-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.eagle.cool/web-api/api/item.md).

# Item

## Endpoints Overview

| Method | Endpoint                          | Description                    |
| ------ | --------------------------------- | ------------------------------ |
| GET    | `/api/v2/item/get`                | List items with filters        |
| POST   | `/api/v2/item/get`                | List items with filters (body) |
| POST   | `/api/v2/item/query`              | Full-text search               |
| GET    | `/api/v2/item/countAll`           | Count all items                |
| POST   | `/api/v2/item/add`                | Add a new item                 |
| POST   | `/api/v2/item/update`             | Update an item                 |
| POST   | `/api/v2/item/setCustomThumbnail` | Set a custom thumbnail         |
| POST   | `/api/v2/item/refreshThumbnail`   | Refresh item thumbnail         |

***

## GET /api/v2/item/get <a href="#list" id="list"></a>

List items with optional filtering. Returns paginated results.

### Query Parameters

* `id` string (optional) — Return a single item by ID
* `ids` string (optional) — Comma-separated item IDs
* `isSelected` boolean (optional) — Return currently selected items
* `isUntagged` boolean (optional) — Return items without tags
* `isUnfiled` boolean (optional) — Return items not in any folder
* `keywords` string (optional) — Filter by keywords (comma-separated)
* `tags` string (optional) — Filter by tags (comma-separated)
* `folders` string (optional) — Filter by folder IDs (comma-separated)
* `ext` string (optional) — Filter by file extension (e.g., `jpg`, `png`)
* `annotation` string (optional) — Filter by annotation text
* `rating` integer (optional) — Filter by rating (`0`–`5`)
* `url` string (optional) — Filter by source URL
* `shape` string (optional) — Filter by shape: `square`, `portrait`, `panoramic-portrait`, `landscape`, `panoramic-landscape`
* `fields` string (optional) — Comma-separated list of fields to return (improves performance)
* `offset` integer (optional) — Pagination offset, default `0`
* `limit` integer (optional) — Pagination limit, default `50`, max `1000`

### Response

```json
{
    "status": "success",
    "data": {
        "data": [
            {
                "id": "M3QSGJNQTC2DG",
                "name": "sunset-photo",
                "ext": "jpg",
                "width": 1920,
                "height": 1080,
                "url": "https://example.com/photo.jpg",
                "tags": ["nature", "sunset"],
                "folders": ["FOLDER_ID_1"],
                "star": 4,
                "annotation": "Beautiful sunset at the beach",
                "modificationTime": 1700000000000
            }
        ],
        "total": 1250,
        "offset": 0,
        "limit": 50
    }
}
```

### Examples

```javascript
// List first 50 items (default)
await fetch("http://localhost:41595/api/v2/item/get").then(r => r.json());

// Get a single item by ID
await fetch("http://localhost:41595/api/v2/item/get?id=M3QSGJNQTC2DG").then(r => r.json());

// Filter by extension with pagination
await fetch("http://localhost:41595/api/v2/item/get?ext=png&offset=0&limit=100").then(r => r.json());

// Return only specific fields for better performance
await fetch("http://localhost:41595/api/v2/item/get?fields=id,name,tags").then(r => r.json());
```

***

## POST /api/v2/item/get <a href="#list-post" id="list-post"></a>

Same as GET, but accepts filter parameters in the JSON body. Useful for complex queries with arrays.

### Request Body

* `id` string (optional) — Item ID
* `ids` string\[] (optional) — Array of item IDs
* `isSelected` boolean (optional) — Currently selected items
* `isUntagged` boolean (optional) — Items without tags
* `isUnfiled` boolean (optional) — Items not in any folder
* `keywords` string\[] (optional) — Keywords to match
* `tags` string\[] (optional) — Tags to match
* `folders` string\[] (optional) — Folder IDs to match
* `smartFolders` string\[] (optional) — Filter by smart folder IDs (OR logic, matches any)
* `ext` string (optional) — File extension
* `annotation` string (optional) — Annotation text
* `rating` integer (optional) — Rating (`0`–`5`)
* `url` string (optional) — Source URL
* `shape` string (optional) — Image shape
* `fields` string\[] (optional) — Fields to return
* `offset` integer (optional) — Pagination offset, default `0`
* `limit` integer (optional) — Pagination limit, default `50`, max `1000`

### Examples

```javascript
// Filter by tags
await fetch("http://localhost:41595/api/v2/item/get", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        tags: ["design", "inspiration"],
        limit: 20
    })
}).then(r => r.json());

// Get items by multiple IDs
await fetch("http://localhost:41595/api/v2/item/get", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        ids: ["ITEM_ID_1", "ITEM_ID_2", "ITEM_ID_3"]
    })
}).then(r => r.json());

// Filter JPG files in a specific folder, return only id and name
await fetch("http://localhost:41595/api/v2/item/get", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        ext: "jpg",
        folders: ["FOLDER_ID"],
        fields: ["id", "name", "tags"],
        offset: 0,
        limit: 100
    })
}).then(r => r.json());
```

```javascript
// Filter with smart folders
await fetch("http://localhost:41595/api/v2/item/get", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        smartFolders: ["SMART_FOLDER_ID"],
        tags: ["cat"],
        limit: 20
    })
}).then(r => r.json());
```

{% hint style="info" %}
**Performance Tip:** Use the `fields` parameter to return only the data you need. This significantly improves response time when working with large libraries.
{% endhint %}

***

## POST /api/v2/item/query <a href="#query" id="query"></a>

Full-text search across item names, tags, annotations, URLs, folder names, and more. Supports advanced query syntax. Returns paginated results.

### Request Body

* `query` string — Search query string
* `offset` integer (optional) — Pagination offset, default `0`
* `limit` integer (optional) — Pagination limit, default `50`, max `1000`

### Query Syntax

| Syntax       | Description             | Example             |
| ------------ | ----------------------- | ------------------- |
| `word`       | Must contain word       | `cat`               |
| `a b`        | Must contain both (AND) | `cat dog`           |
| `a OR b`     | Contains either (OR)    | `cat OR dog`        |
| `a \|\| b`   | Contains either (OR)    | `cat \|\| dog`      |
| `-word`      | Must NOT contain        | `cat -dog`          |
| `"phrase"`   | Exact phrase match      | `"orange cat"`      |
| `(a OR b) c` | Grouping                | `(cat OR dog) cute` |

### Examples

```javascript
// Simple search
await fetch("http://localhost:41595/api/v2/item/query", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: "sunset" })
}).then(r => r.json());

// Advanced search: items with "cat" or "dog" but not "cartoon"
await fetch("http://localhost:41595/api/v2/item/query", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        query: "(cat OR dog) -cartoon",
        limit: 20
    })
}).then(r => r.json());

// Paginate through search results
await fetch("http://localhost:41595/api/v2/item/query", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: "design", offset: 50, limit: 50 })
}).then(r => r.json());
```

***

## GET /api/v2/item/countAll <a href="#count" id="count"></a>

Returns the total number of items in the library.

### Response

```json
{
    "status": "success",
    "data": 12500
}
```

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/countAll").then(r => r.json());
```

***

## POST /api/v2/item/add <a href="#add" id="add"></a>

Add a new item to Eagle. Supports adding from URL, Base64 data, local file path, or bookmark.

### Request Body

* `id` string (optional) — Custom item ID
* `name` string (optional) — Item name
* `tags` string\[] (optional) — Tags to assign
* `folders` string\[] (optional) — Folder IDs to add the item to
* `annotation` string (optional) — Item annotation
* `website` string (optional) — Source website URL

**Plus one of the following:**

* `url` string — Image URL to download
* `base64` string — Base64 encoded image data
* `path` string — Local file path to import
* `bookmarkURL` string — URL to add as a bookmark

### Examples

```javascript
// Add from URL
await fetch("http://localhost:41595/api/v2/item/add", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        url: "https://example.com/photo.jpg",
        name: "Example Photo",
        tags: ["downloaded", "example"],
        folders: ["FOLDER_ID"]
    })
}).then(r => r.json());

// Add from local file path
await fetch("http://localhost:41595/api/v2/item/add", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        path: "C:\\Users\\User\\Downloads\\design.png",
        name: "My Design",
        tags: ["design"]
    })
}).then(r => r.json());

// Add a bookmark
await fetch("http://localhost:41595/api/v2/item/add", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        bookmarkURL: "https://www.example.com",
        name: "Example Site",
        tags: ["bookmark"]
    })
}).then(r => r.json());

// Batch add multiple items (up to 1000)
await fetch("http://localhost:41595/api/v2/item/add", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        items: [
            { url: "https://example.com/photo1.jpg", name: "Photo 1" },
            { path: "C:\\Users\\User\\Downloads\\design.png", name: "Design" },
            { bookmarkURL: "https://www.example.com", name: "Bookmark" }
        ]
    })
}).then(r => r.json());
```

### Batch Mode

Pass an `items` array to add multiple items at once (up to 1000). Each object in the array follows the same format as single mode, and you can mix `path`, `url`, `bookmarkURL`, and `base64`.

### Response

Single mode returns the new item's ID:

```json
{
    "status": "success",
    "data": { "id": "M3QSGJNQTC2DG" }
}
```

Batch mode returns all new item IDs:

```json
{
    "status": "success",
    "data": { "ids": ["ITEM_ID_1", "ITEM_ID_2", "ITEM_ID_3"] }
}
```

***

## POST /api/v2/item/update <a href="#update" id="update"></a>

Update an existing item's metadata. Only the fields you include will be modified.

### Request Body

* `id` string (required) — The item ID to update

**Modifiable fields:**

* `name` string (optional) — New name
* `tags` string\[] (optional) — Replace tags
* `folders` string\[] (optional) — Replace folder assignments
* `annotation` string (optional) — New annotation
* `url` string (optional) — New source URL
* `star` integer (optional) — Rating, `0`–`5`
* `modificationTime` integer (optional) — Modification timestamp
* `noThumbnail` boolean (optional) — Mark as having no thumbnail
* `noPreview` boolean (optional) — Mark as not previewable
* `isDeleted` boolean (optional) — Move to / restore from trash

### Response

Returns the updated item object.

### Examples

```javascript
// Update item name and tags
await fetch("http://localhost:41595/api/v2/item/update", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "M3QSGJNQTC2DG",
        name: "Updated Name",
        tags: ["tag1", "tag2"],
        star: 5
    })
}).then(r => r.json());

// Move item to trash
await fetch("http://localhost:41595/api/v2/item/update", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "M3QSGJNQTC2DG",
        isDeleted: true
    })
}).then(r => r.json());
```

***

## POST /api/v2/item/setCustomThumbnail <a href="#set-thumbnail" id="set-thumbnail"></a>

Set a custom thumbnail for an item from a local image file.

### Request Body

* `itemId` string (required) — The item ID
* `filePath` string (required) — Path to the thumbnail image

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/setCustomThumbnail", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        itemId: "M3QSGJNQTC2DG",
        filePath: "C:\\Users\\User\\thumbnails\\custom.png"
    })
}).then(r => r.json());
```

{% hint style="info" %}
This operation is asynchronous. The API waits up to 10 seconds for the thumbnail to be generated before responding.
{% endhint %}

***

## POST /api/v2/item/refreshThumbnail <a href="#refresh-thumbnail" id="refresh-thumbnail"></a>

Regenerate the thumbnail for an item, updating file size, dimensions, and color palette.

### Request Body

* `itemId` string (required) — The item ID

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/refreshThumbnail", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ itemId: "M3QSGJNQTC2DG" })
}).then(r => r.json());
```

***

## GET /api/v2/item/getComments <a href="#get-comments" id="get-comments"></a>

Get all comments (annotations) for an item. Returns image rect comments or video timestamp comments.

{% hint style="info" %}
**Version Requirement:** This endpoint requires **Eagle 4.0 Build 22** or later.
{% endhint %}

### Query Parameters

* `id` string (required) — The item ID

### Response

```json
{
    "status": "success",
    "data": [
        {
            "id": "MN3DZC0R7XYSZ",
            "x": 324,
            "y": 810,
            "width": 194,
            "height": 208,
            "annotation": "Face area",
            "lastModified": 1774282485915
        }
    ]
}
```

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/getComments?id=M3QSGJNQTC2DG")
    .then(r => r.json());
```

***

## POST /api/v2/item/addComment <a href="#add-comment" id="add-comment"></a>

Add a comment to an item. Supports two types:

* **Image rect comment** — provide `x`, `y`, `width`, `height` to mark a region on the image
* **Video timestamp comment** — provide `duration` to mark a point on the video timeline

The server automatically generates `id` and `lastModified` fields.

{% hint style="info" %}
**Version Requirement:** This endpoint requires **Eagle 4.0 Build 22** or later.
{% endhint %}

### Request Body

* `id` string (required) — The item ID
* `annotation` string (optional) — Comment text
* `x` number (optional) — Rect X position (image comment)
* `y` number (optional) — Rect Y position (image comment)
* `width` number (optional) — Rect width, must > 0 (image comment)
* `height` number (optional) — Rect height, must > 0 (image comment)
* `duration` number (optional) — Video timestamp in seconds, must >= 0 (video comment)

{% hint style="warning" %}
You must provide either `duration` (video) or all of `x`/`y`/`width`/`height` (image). Providing both or neither will return an error.
{% endhint %}

### Example

```javascript
// Add an image rect comment
await fetch("http://localhost:41595/api/v2/item/addComment", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "M3QSGJNQTC2DG",
        x: 350, y: 480, width: 380, height: 400,
        annotation: "White fluffy toy face"
    })
}).then(r => r.json());

// Add a video timestamp comment
await fetch("http://localhost:41595/api/v2/item/addComment", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "VIDEO_ITEM_ID",
        duration: 65.5,
        annotation: "Important scene"
    })
}).then(r => r.json());
```

***

## POST /api/v2/item/updateComment <a href="#update-comment" id="update-comment"></a>

Update an existing comment. Only the provided fields are updated; `lastModified` is refreshed automatically.

{% hint style="info" %}
**Version Requirement:** This endpoint requires **Eagle 4.0 Build 22** or later.
{% endhint %}

### Request Body

* `id` string (required) — The item ID
* `commentId` string (required) — The comment ID to update
* `annotation` string (optional) — New comment text
* `x` number (optional) — New X position (image comment only)
* `y` number (optional) — New Y position (image comment only)
* `width` number (optional) — New width, must > 0 (image comment only)
* `height` number (optional) — New height, must > 0 (image comment only)
* `duration` number (optional) — New timestamp, must >= 0 (video comment only)

{% hint style="warning" %}
Image comments can only update `x`/`y`/`width`/`height`. Video comments can only update `duration`. Cross-type updates will return an error.
{% endhint %}

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/updateComment", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "M3QSGJNQTC2DG",
        commentId: "MN3DZC0R7XYSZ",
        annotation: "Updated annotation text"
    })
}).then(r => r.json());
```

***

## POST /api/v2/item/removeComment <a href="#remove-comment" id="remove-comment"></a>

Remove a comment from an item.

{% hint style="info" %}
**Version Requirement:** This endpoint requires **Eagle 4.0 Build 22** or later.
{% endhint %}

### Request Body

* `id` string (required) — The item ID
* `commentId` string (required) — The comment ID to remove

### Example

```javascript
await fetch("http://localhost:41595/api/v2/item/removeComment", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        id: "M3QSGJNQTC2DG",
        commentId: "MN3DZC0R7XYSZ"
    })
}).then(r => r.json());
```

***

## Item Properties <a href="#properties" id="properties"></a>

Items returned by the API contain the following properties:

| Property           | Type      | Description                              |
| ------------------ | --------- | ---------------------------------------- |
| `id`               | string    | Unique item ID                           |
| `name`             | string    | Item name                                |
| `ext`              | string    | File extension                           |
| `width`            | integer   | Image width in pixels                    |
| `height`           | integer   | Image height in pixels                   |
| `url`              | string    | Source URL                               |
| `isDeleted`        | boolean   | Whether the item is in trash             |
| `annotation`       | string    | Item annotation/notes                    |
| `tags`             | string\[] | Array of tag names                       |
| `folders`          | string\[] | Array of folder IDs                      |
| `palettes`         | Object\[] | Color palette information                |
| `size`             | integer   | File size in bytes                       |
| `star`             | integer   | Rating (0–5)                             |
| `modificationTime` | integer   | Last modification timestamp              |
| `noThumbnail`      | boolean   | Whether the file has no thumbnail        |
| `noPreview`        | boolean   | Whether double-click preview is disabled |
