---
title: "Ad Spy tools"
description: "Search ads and brands, read stored research, manage Ad Spy boards, saved searches and filter presets, and transcribe or analyze video ads."
url: "https://sellify.ai/docs/developers/mcp-tools/ad-spy"
---

# Ad Spy tools

> Search ads and brands, read stored research, manage Ad Spy boards, saved searches and filter presets, and transcribe or analyze video ads.

Search ads and brands, read stored research, manage Ad Spy boards, saved searches and filter presets, and transcribe or analyze video ads. This page lists 50 tools, 24 of them read-only.

- [`ad_spy_ads_search`](#ad_spy_ads_search): Search Ad Spy ads
- [`ad_spy_brand_ads_search`](#ad_spy_brand_ads_search): Search ads for a brand
- [`ad_spy_brands_search`](#ad_spy_brands_search): Search Ad Spy brands
- [`ad_spy_product_brand_recommendations_get`](#ad_spy_product_brand_recommendations_get): Get brand recommendations for a product
- [`ad_spy_saved_ads_list`](#ad_spy_saved_ads_list): List saved Ad Spy ads
- [`ad_spy_board_update`](#ad_spy_board_update): Update or move an Ad Spy board
- [`ad_spy_board_reorder`](#ad_spy_board_reorder): Reorder root Ad Spy boards
- [`ad_spy_board_delete`](#ad_spy_board_delete): Delete an Ad Spy board
- [`ad_spy_board_remove_ad`](#ad_spy_board_remove_ad): Remove a saved ad from an Ad Spy board
- [`ad_spy_board_share`](#ad_spy_board_share): Share an Ad Spy board
- [`ad_spy_board_unshare`](#ad_spy_board_unshare): Stop sharing an Ad Spy board
- [`ad_spy_board_resolve_ads`](#ad_spy_board_resolve_ads): Resolve a saved ad within an Ad Spy board
- [`ad_spy_board_resolve`](#ad_spy_board_resolve): Resolve an Ad Spy board for Agent use
- [`ad_spy_board_ensure`](#ad_spy_board_ensure): Ensure an Ad Spy board exists for Agent use
- [`ad_spy_board_save_ads`](#ad_spy_board_save_ads): Save Ad Spy ads to a board
- [`ad_spy_saved_ad_save`](#ad_spy_saved_ad_save): Save an Ad Spy ad
- [`ad_spy_saved_ad_unsave`](#ad_spy_saved_ad_unsave): Remove a saved Ad Spy ad
- [`ad_spy_brand_follow`](#ad_spy_brand_follow): Follow an Ad Spy brand
- [`ad_spy_brand_unfollow`](#ad_spy_brand_unfollow): Unfollow an Ad Spy brand
- [`ad_spy_brand_follow_batch`](#ad_spy_brand_follow_batch): Follow several Ad Spy brands
- [`ad_spy_brand_request_ads`](#ad_spy_brand_request_ads): Request Ad Spy collection for a brand
- [`ad_spy_brand_status`](#ad_spy_brand_status): Check Ad Spy brand collection and enrichment
- [`ad_spy_brand_get_overview`](#ad_spy_brand_get_overview): Get an Ad Spy brand overview
- [`ad_spy_brand_get_intelligence`](#ad_spy_brand_get_intelligence): Get stored Ad Spy brand intelligence
- [`ad_spy_brand_get_stats`](#ad_spy_brand_get_stats): Get stored stats for a followed Ad Spy brand
- [`ad_spy_brand_get_research`](#ad_spy_brand_get_research): Get Ad Spy brand research rollups
- [`ad_spy_brand_get_research_ads`](#ad_spy_brand_get_research_ads): Get ads matching a brand research row
- [`ad_spy_brand_get_landing_page_ads`](#ad_spy_brand_get_landing_page_ads): Get stored ads for a brand landing page
- [`ad_spy_ads_count`](#ad_spy_ads_count): Count stored Ad Spy ads and check freshness
- [`ad_spy_ads_aggregate`](#ad_spy_ads_aggregate): Summarize stored Ad Spy ads
- [`ad_spy_ads_top_hooks`](#ad_spy_ads_top_hooks): Rank the most used ad hooks
- [`ad_spy_ad_get_hooks`](#ad_spy_ad_get_hooks): Get the hook and angle of one ad
- [`ad_spy_advertisers_find_by_domain`](#ad_spy_advertisers_find_by_domain): Find advertisers by website domain
- [`ad_spy_filter_preset_list`](#ad_spy_filter_preset_list): List Ad Spy filter presets
- [`ad_spy_filter_preset_create`](#ad_spy_filter_preset_create): Create an Ad Spy filter preset
- [`ad_spy_filter_preset_update`](#ad_spy_filter_preset_update): Update an Ad Spy filter preset
- [`ad_spy_filter_preset_delete`](#ad_spy_filter_preset_delete): Delete an Ad Spy filter preset
- [`ad_spy_filter_preset_set_default`](#ad_spy_filter_preset_set_default): Set the default Ad Spy filter preset
- [`ad_spy_saved_search_list`](#ad_spy_saved_search_list): List saved Ad Spy searches
- [`ad_spy_saved_search_create`](#ad_spy_saved_search_create): Save an Ad Spy search
- [`ad_spy_saved_search_delete`](#ad_spy_saved_search_delete): Delete a saved Ad Spy search
- [`ad_spy_saved_search_run`](#ad_spy_saved_search_run): Run a saved Ad Spy search
- [`ad_spy_saved_ad_share`](#ad_spy_saved_ad_share): Create a public share link for a saved ad
- [`ad_spy_saved_ad_unshare`](#ad_spy_saved_ad_unshare): Revoke a saved-ad share link
- [`ad_spy_video_transcript_start`](#ad_spy_video_transcript_start): Start video ad transcription
- [`ad_spy_video_transcript_get_status`](#ad_spy_video_transcript_get_status): Get a video ad transcript status
- [`ad_spy_video_analysis_start`](#ad_spy_video_analysis_start): Start full video ad analysis
- [`ad_spy_video_analysis_get_status`](#ad_spy_video_analysis_get_status): Get a video ad analysis status
- [`ad_spy_video_similar_scripts_start`](#ad_spy_video_similar_scripts_start): Generate similar video-ad scripts
- [`ad_spy_video_similar_scripts_get_status`](#ad_spy_video_similar_scripts_get_status): Get similar-script generation status

## `ad_spy_ads_search`

**Search Ad Spy ads**

General Ad Spy search for a keyword, product, or advertiser name. Needs no brand page ID. Prefers held-brand, cache, and local archive results before any bounded live provider search.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | About 0.45 credits          |
| Safe to repeat | Yes                         |

### Input

| Field             | Type            | Required | Description                                                                                                                                                                                                                      |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string          | Yes      | The keyword, product, or advertiser name from the user request. Use this general search when no verified Ad Spy brand page ID is available. Length 1 to 200.                                                                     |
| `country`         | "ALL" or string | No       |                                                                                                                                                                                                                                  |
| `sortBy`          | enum            | No       | One of: `total_impressions`, `relevancy_monthly_grouped`.                                                                                                                                                                        |
| `status`          | enum            | No       | One of: `ALL`, `ACTIVE`.                                                                                                                                                                                                         |
| `cursor`          | string or null  | No       |                                                                                                                                                                                                                                  |
| `idempotency_key` | string          | No       | Client-chosen key identifying this call. Reuse it only when retrying the same call. Length 1 to 200.                                                                                                                             |
| `max_credits`     | number          | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                                                                                                                                                    |
| `response_format` | enum            | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field             | Type            | Description                                                                              |
| ----------------- | --------------- | ---------------------------------------------------------------------------------------- |
| `ads`             | array of object | Items up to 50.                                                                          |
| `cursor`          | string or null  |                                                                                          |
| `totalCount`      | number or null  |                                                                                          |
| `servedFrom`      | enum or null    | One of: `archive`, `provider`.                                                           |
| `failedBrands`    | array of object |                                                                                          |
| `credits_charged` | number          | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null  | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_ads_search",
    "arguments": {
      "query": "example",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_brand_ads_search`

**Search ads for a brand**

Searches ads for one verified Ad Spy brand, identified by its page ID and name from an Ad Spy brand search. Prefers cached and archived results before a bounded live provider search.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | About 2.4 credits           |
| Safe to repeat | Yes                         |

### Input

| Field             | Type            | Required | Description                                                                                                                                                                                                                      |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string          | Yes      | A verified Ad Spy brand page ID returned by an Ad Spy brand search. Never infer or invent this value. Length 1 to 64.                                                                                                            |
| `pageName`        | string          | Yes      | The exact brand name returned with the verified page ID. Length 1 to 200.                                                                                                                                                        |
| `country`         | "ALL" or string | No       |                                                                                                                                                                                                                                  |
| `sortBy`          | enum            | No       | One of: `total_impressions`, `relevancy_monthly_grouped`.                                                                                                                                                                        |
| `status`          | enum            | No       | One of: `ALL`, `ACTIVE`, `INACTIVE`.                                                                                                                                                                                             |
| `timeWindow`      | enum            | No       | One of: `3m`, `6m`, `12m`, `all`. Defaults to `"all"`.                                                                                                                                                                           |
| `cursor`          | string or null  | No       |                                                                                                                                                                                                                                  |
| `idempotency_key` | string          | No       | Client-chosen key identifying this call. Reuse it only when retrying the same call. Length 1 to 200.                                                                                                                             |
| `max_credits`     | number          | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                                                                                                                                                    |
| `response_format` | enum            | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field             | Type            | Description                                                                              |
| ----------------- | --------------- | ---------------------------------------------------------------------------------------- |
| `ads`             | array of object | Items up to 50.                                                                          |
| `cursor`          | string or null  |                                                                                          |
| `totalCount`      | number or null  |                                                                                          |
| `servedFrom`      | enum or null    | One of: `archive`, `provider`.                                                           |
| `failedBrands`    | array of object |                                                                                          |
| `credits_charged` | number          | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null  | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_ads_search",
    "arguments": {
      "pageId": "example",
      "pageName": "example",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_brands_search`

**Search Ad Spy brands**

Resolves an advertiser name to verified Ad Spy brand records and page IDs. Returns brands, not ads.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | About 0.15 credits          |
| Safe to repeat | Yes                         |

### Input

| Field             | Type   | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string | Yes      | The advertiser name to resolve to an Ad Spy brand page ID before a brand-specific ad search. Length 1 to 200.                                                                                                                    |
| `idempotency_key` | string | No       | Client-chosen key identifying this call. Reuse it only when retrying the same call. Length 1 to 200.                                                                                                                             |
| `max_credits`     | number | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                                                                                                                                                    |
| `response_format` | enum   | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field             | Type            | Description                                                                              |
| ----------------- | --------------- | ---------------------------------------------------------------------------------------- |
| `brands`          | array of object | Items up to 50.                                                                          |
| `credits_charged` | number          | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null  | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brands_search",
    "arguments": {
      "query": "example",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_product_brand_recommendations_get`

**Get brand recommendations for a product**

Returns stored Ad Spy brand recommendations for one workspace product. Queues a bounded backfill when none exist yet, and retries a failed match with no brands once a few minutes have passed since it failed.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Writes data                 |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field       | Type          | Required | Description |
| ----------- | ------------- | -------- | ----------- |
| `productId` | string (uuid) | Yes      |             |

### Output

| Field            | Type            | Description                           |
| ---------------- | --------------- | ------------------------------------- |
| `productId`      | string (uuid)   |                                       |
| `productName`    | string          |                                       |
| `status`         | enum            | One of: `pending`, `ready`, `failed`. |
| `errorMessage`   | string or null  |                                       |
| `computedAt`     | string or null  |                                       |
| `requestedAt`    | string          |                                       |
| `pendingTooLong` | boolean         |                                       |
| `brands`         | array of object |                                       |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_product_brand_recommendations_get",
    "arguments": {
      "productId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_saved_ads_list`

**List saved Ad Spy ads**

Returns a bounded tenant-scoped list and deterministic resolution status for saved Ad Spy ads. Use an exact saved-ad ID, advertiser, or headline query to resolve the source ad.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type    | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string  | No       | Length 1 to 120.                                                                                                                                                                                                                 |
| `limit`           | integer | No       | Between 1 and 10. Defaults to `5`.                                                                                                                                                                                               |
| `response_format` | enum    | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field        | Type            | Description     |
| ------------ | --------------- | --------------- |
| `savedAds`   | array of object | Items up to 10. |
| `resolution` | object          |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_ads_list",
    "arguments": {}
  }
}
```

## `ad_spy_board_update`

**Update or move an Ad Spy board**

Renames, recolors, or moves an Ad Spy board while preserving a maximum nesting depth of one. Agent callers pass the exact current board name as expectedName so a stale id/name pairing is refused.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type                  | Required | Description                                                   |
| -------------- | --------------------- | -------- | ------------------------------------------------------------- |
| `boardId`      | string (uuid)         | Yes      |                                                               |
| `name`         | string                | No       |                                                               |
| `color`        | enum                  | No       | One of: `blue`, `green`, `yellow`, `red`, `purple`, `orange`. |
| `parentId`     | string (uuid) or null | No       |                                                               |
| `expectedName` | string                | Yes      |                                                               |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_update",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "expectedName": "example"
    }
  }
}
```

## `ad_spy_board_reorder`

**Reorder root Ad Spy boards**

Reorders all active root Ad Spy boards using an exact current permutation.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field             | Type                   | Required | Description     |
| ----------------- | ---------------------- | -------- | --------------- |
| `orderedBoardIds` | array of string (uuid) | Yes      | Items 1 to 200. |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_reorder",
    "arguments": {
      "orderedBoardIds": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    }
  }
}
```

## `ad_spy_board_delete`

**Delete an Ad Spy board**

Soft-deletes an Ad Spy board, its direct sub-boards, and their memberships. Agent callers pass the exact current board name as expectedName so a stale id/name pairing is refused.

When the user asks for this, call it directly: Sellify asks the user to confirm before anything is deleted. If it returns mcp\_confirmation\_required, show the user its question and retry with confirmation\_token only after they say yes.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field                | Type          | Required | Description                                                                                                              |
| -------------------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| `boardId`            | string (uuid) | Yes      |                                                                                                                          |
| `expectedName`       | string        | Yes      |                                                                                                                          |
| `confirmation_token` | string        | No       | Only for retrying a call that returned mcp\_confirmation\_required: the exact token from that result. Never make one up. |

### Output

| Field             | Type                   | Description |
| ----------------- | ---------------------- | ----------- |
| `success`         | true                   |             |
| `deletedBoardIds` | array of string (uuid) |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_delete",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "expectedName": "example"
    }
  }
}
```

## `ad_spy_board_remove_ad`

**Remove a saved ad from an Ad Spy board**

Removes a saved-ad membership from an Ad Spy board.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type          | Required | Description |
| -------------- | ------------- | -------- | ----------- |
| `boardId`      | string (uuid) | Yes      |             |
| `savedSpyAdId` | string (uuid) | Yes      |             |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_remove_ad",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "savedSpyAdId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_board_share`

**Share an Ad Spy board**

Turns on public sharing for an Ad Spy board and returns its share link. Anyone with the link can view the saved ads on the board without signing in. If the board is already shared, the existing link is returned unchanged. Agent callers pass the exact current board name as expectedName so a stale id/name pairing is refused.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type          | Required | Description |
| -------------- | ------------- | -------- | ----------- |
| `boardId`      | string (uuid) | Yes      |             |
| `expectedName` | string        | Yes      |             |

### Output

| Field       | Type   | Description |
| ----------- | ------ | ----------- |
| `shareSlug` | string |             |
| `shareUrl`  | string |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_share",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "expectedName": "example"
    }
  }
}
```

## `ad_spy_board_unshare`

**Stop sharing an Ad Spy board**

Turns off public sharing for an Ad Spy board so its existing share link stops working. Agent callers pass the exact current board name as expectedName so a stale id/name pairing is refused.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type          | Required | Description |
| -------------- | ------------- | -------- | ----------- |
| `boardId`      | string (uuid) | Yes      |             |
| `expectedName` | string        | Yes      |             |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_unshare",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "expectedName": "example"
    }
  }
}
```

## `ad_spy_board_resolve_ads`

**Resolve a saved ad within an Ad Spy board**

Returns a bounded, tenant-scoped list of ads from one exact Ad Spy board and deterministic resolution status. Use the exact board id from listAdSpyBoards.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type          | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `boardId`         | string (uuid) | Yes      | The exact id returned by listBoards or createBoard. Never use an Ecom generated-ad board id.                                                                                                                                     |
| `query`           | string        | No       | Length 1 to 120.                                                                                                                                                                                                                 |
| `limit`           | integer       | No       | Between 1 and 10. Defaults to `5`.                                                                                                                                                                                               |
| `response_format` | enum          | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field        | Type            | Description     |
| ------------ | --------------- | --------------- |
| `board`      | object          |                 |
| `savedAds`   | array of object | Items up to 10. |
| `resolution` | object          |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_resolve_ads",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_board_resolve`

**Resolve an Ad Spy board for Agent use**

Lists Ad Spy saved-ad boards in the current workspace. Use query to resolve a user-named Ad Spy board before creating one. These are distinct from Ecom generated-ad library folders.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type    | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string  | No       | The exact board name from the user when resolving a named board. Include it instead of listing every board. Length 1 to 80.                                                                                                      |
| `limit`           | integer | No       | Between 1 and 50. Defaults to `25`.                                                                                                                                                                                              |
| `response_format` | enum    | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field        | Type            | Description     |
| ------------ | --------------- | --------------- |
| `boards`     | array of object | Items up to 50. |
| `resolution` | object          |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_resolve",
    "arguments": {}
  }
}
```

## `ad_spy_board_ensure`

**Ensure an Ad Spy board exists for Agent use**

Creates a saved-ad board in Ad Spy. If an active board with the same name already exists, returns it as a successful no-op with created false. Never use this for generated Ecom ads.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field   | Type   | Required | Description                                                   |
| ------- | ------ | -------- | ------------------------------------------------------------- |
| `name`  | string | Yes      | Length 1 to 80.                                               |
| `color` | enum   | No       | One of: `blue`, `green`, `yellow`, `red`, `purple`, `orange`. |

### Output

| Field       | Type          | Description                                                   |
| ----------- | ------------- | ------------------------------------------------------------- |
| `id`        | string (uuid) |                                                               |
| `name`      | string        | Length up to 80.                                              |
| `color`     | enum          | One of: `blue`, `green`, `yellow`, `red`, `purple`, `orange`. |
| `sortOrder` | integer       |                                                               |
| `createdAt` | string        |                                                               |
| `updatedAt` | string        |                                                               |
| `created`   | boolean       |                                                               |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_ensure",
    "arguments": {
      "name": "example"
    }
  }
}
```

## `ad_spy_board_save_ads`

**Save Ad Spy ads to a board**

Saves exact ads returned by Ad Spy research into the selected Ad Spy board. Pass exact adArchiveIds from search results and the exact board id from listBoards or createBoard. Existing saved ads and memberships are successful no-ops.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type            | Required | Description                                                                                  |
| -------------- | --------------- | -------- | -------------------------------------------------------------------------------------------- |
| `boardId`      | string (uuid)   | Yes      | The exact id returned by listBoards or createBoard. Never use an Ecom generated-ad board id. |
| `adArchiveIds` | array of string | Yes      | Items 1 to 10.                                                                               |

### Output

| Field                 | Type            | Description       |
| --------------------- | --------------- | ----------------- |
| `board`               | object          |                   |
| `requestedCount`      | integer         | Between 1 and 10. |
| `addedToBoardCount`   | integer         |                   |
| `alreadyInBoardCount` | integer         |                   |
| `failedCount`         | integer         |                   |
| `results`             | array of object | Items up to 10.   |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_board_save_ads",
    "arguments": {
      "boardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "adArchiveIds": [
        "example"
      ]
    }
  }
}
```

## `ad_spy_saved_ad_save`

**Save an Ad Spy ad**

Saves an ad returned by an Ad Spy search into the current organization. Pass the exact adArchiveId from the search result. Repeating the action returns the existing saved ad.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field         | Type    | Required | Description                                                                                                     |
| ------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| `adArchiveId` | string  | Yes      | The exact adArchiveId of an Ad Spy search result or saved ad. Never infer or invent this value. Length 1 to 64. |
| `imageIndex`  | integer | No       | Between 0 and 49.                                                                                               |

### Output

| Field                | Type          | Description |
| -------------------- | ------------- | ----------- |
| `savedSpyAdId`       | string (uuid) |             |
| `alreadySaved`       | boolean       |             |
| `recreateImageIndex` | integer       |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_ad_save",
    "arguments": {
      "adArchiveId": "example"
    }
  }
}
```

## `ad_spy_saved_ad_unsave`

**Remove a saved Ad Spy ad**

Removes an ad from the current organization by its exact adArchiveId. Repeating the action is safe and reports removed false.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field         | Type   | Required | Description                                                                                                     |
| ------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------- |
| `adArchiveId` | string | Yes      | The exact adArchiveId of an Ad Spy search result or saved ad. Never infer or invent this value. Length 1 to 64. |

### Output

| Field     | Type    | Description |
| --------- | ------- | ----------- |
| `removed` | boolean |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_ad_unsave",
    "arguments": {
      "adArchiveId": "example"
    }
  }
}
```

## `ad_spy_brand_follow`

**Follow an Ad Spy brand**

Follows one exact brand from an Ad Spy result in this tool's bound workspace. If the user names another workspace, do not call this tool. Repeating the action returns the existing followed brand.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field           | Type           | Required | Description                                                                                              |
| --------------- | -------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `pageId`        | string         | Yes      | The exact page ID returned with an Ad Spy ad or brand. Never infer or invent this value. Length 1 to 64. |
| `pageName`      | string         | Yes      | Length 1 to 200.                                                                                         |
| `profilePicUrl` | string or null | No       |                                                                                                          |

### Output

| Field             | Type          | Description |
| ----------------- | ------------- | ----------- |
| `followedBrandId` | string (uuid) |             |
| `alreadyFollowed` | boolean       |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_follow",
    "arguments": {
      "pageId": "example",
      "pageName": "example"
    }
  }
}
```

## `ad_spy_brand_unfollow`

**Unfollow an Ad Spy brand**

Stops following the exact brand in the current organization. Repeating the action is safe.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field    | Type   | Required | Description                                                                                              |
| -------- | ------ | -------- | -------------------------------------------------------------------------------------------------------- |
| `pageId` | string | Yes      | The exact page ID returned with an Ad Spy ad or brand. Never infer or invent this value. Length 1 to 64. |

### Output

| Field     | Type    | Description |
| --------- | ------- | ----------- |
| `removed` | boolean |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_unfollow",
    "arguments": {
      "pageId": "example"
    }
  }
}
```

## `ad_spy_brand_follow_batch`

**Follow several Ad Spy brands**

Follows up to 100 exact brands returned by Ad Spy. Existing follows are left unchanged and reported separately.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field    | Type            | Required | Description     |
| -------- | --------------- | -------- | --------------- |
| `brands` | array of object | Yes      | Items 1 to 100. |

### Output

| Field                  | Type    | Description |
| ---------------------- | ------- | ----------- |
| `followedCount`        | integer |             |
| `alreadyFollowedCount` | integer |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_follow_batch",
    "arguments": {
      "brands": [
        {
          "pageId": "example",
          "pageName": "example"
        }
      ]
    }
  }
}
```

## `ad_spy_brand_request_ads`

**Request Ad Spy collection for a brand**

Queues collection for an exact Meta brand. The request runs asynchronously; alreadyCollecting means an existing collection is still in progress.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |

### Input

| Field      | Type   | Required | Description                                                                                      |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------------------ |
| `pageId`   | string | Yes      | The exact Meta page ID of a brand from an Ad Spy brand search. Never infer or invent this value. |
| `pageName` | string | Yes      | Length 1 to 200.                                                                                 |

### Output

| Field               | Type    | Description |
| ------------------- | ------- | ----------- |
| `enqueued`          | boolean |             |
| `alreadyCollecting` | boolean |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_request_ads",
    "arguments": {
      "pageId": "example",
      "pageName": "example"
    }
  }
}
```

## `ad_spy_brand_status`

**Check Ad Spy brand collection and enrichment**

Reports, for each exact brand page ID, whether this workspace follows it, the state of its latest ads collection request (collecting or collected, collected with no ads, failed, or not requested), whether Ad Spy already has archived ads for it, and whether its brand stats are ready. Use it to report the outcome of a brand ads request or a batch follow.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type            | Required | Description                                                                                                                                                                                                                      |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageIds`         | array of string | Yes      | Items 1 to 100.                                                                                                                                                                                                                  |
| `response_format` | enum            | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field    | Type            | Description      |
| -------- | --------------- | ---------------- |
| `brands` | array of object | Items up to 100. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_status",
    "arguments": {
      "pageIds": [
        "example"
      ]
    }
  }
}
```

## `ad_spy_brand_get_overview`

**Get an Ad Spy brand overview**

Reads the stored overview for one verified Ad Spy brand, including ad volume, media mix, landing pages, social counts and partnership signals. Pass a returned normalizedUrl verbatim to adSpy.brand.getLandingPageAds. This is an archive/cache read and does not run a live ad-provider search.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type   | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                    |
| `timeWindow`      | enum   | No       | One of: `3m`, `6m`, `12m`, `all`. Defaults to `"all"`.                                                                                                                                                                           |
| `response_format` | enum   | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field                      | Type            | Description                  |
| -------------------------- | --------------- | ---------------------------- |
| `source`                   | enum            | One of: `archive`, `legacy`. |
| `coverageCount`            | integer or null |                              |
| `distinctLandingPageCount` | integer or null |                              |
| `duplicateCreativeCount`   | integer or null |                              |
| `hasError`                 | boolean         |                              |
| `landingPageCoverageCount` | integer         |                              |
| `landingPages`             | array of object | Items up to 10.              |
| `mediaMix`                 | object or null  |                              |
| `monthlyActive`            | array of object | Items up to 24.              |
| `newAdsLast30d`            | integer or null |                              |
| `newAdsPrev30d`            | integer or null |                              |
| `niche`                    | array of string | Items up to 10.              |
| `partnership`              | object or null  |                              |
| `pending`                  | boolean         |                              |
| `social`                   | object          |                              |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_overview",
    "arguments": {
      "pageId": "example"
    }
  }
}
```

## `ad_spy_brand_get_intelligence`

**Get stored Ad Spy brand intelligence**

Reads the stored top landing pages and popular hooks for one verified Ad Spy brand. pending reports whether background enrichment is still running; this action does not make a live provider call.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type   | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                    |
| `response_format` | enum   | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field          | Type            | Description     |
| -------------- | --------------- | --------------- |
| `landingPages` | array of object | Items up to 10. |
| `popularHooks` | array of object | Items up to 10. |
| `scannedCount` | integer         |                 |
| `pending`      | boolean         |                 |
| `hasError`     | boolean         |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_intelligence",
    "arguments": {
      "pageId": "example"
    }
  }
}
```

## `ad_spy_brand_get_stats`

**Get stored stats for a followed Ad Spy brand**

Reads stored aggregate stats for one brand followed by this workspace, including active ads, trend, media mix and landing-page counts. If enrichment is pending, retry later; this action does not make a live provider call.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type   | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                    |
| `response_format` | enum   | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field                      | Type            | Description     |
| -------------------------- | --------------- | --------------- |
| `activeAdsCount`           | integer or null |                 |
| `activeSince`              | integer or null |                 |
| `changeFromPrevMonthPct`   | number or null  |                 |
| `distinctLandingPageCount` | integer or null |                 |
| `duplicateCreativeCount`   | integer or null |                 |
| `mediaMix`                 | object or null  |                 |
| `monthlyActive`            | array of object | Items up to 24. |
| `newAdsLast30d`            | integer or null |                 |
| `newAdsPrev30d`            | integer or null |                 |
| `niche`                    | array of string | Items up to 10. |
| `pageLikeCount`            | integer or null |                 |
| `pageProfileUrl`           | string or null  |                 |
| `pending`                  | boolean         |                 |
| `profilePicUrl`            | string or null  |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_stats",
    "arguments": {
      "pageId": "example"
    }
  }
}
```

## `ad_spy_brand_get_research`

**Get Ad Spy brand research rollups**

Reads bounded research rollups for a verified brand: hooks, copy, headlines, landing pages, personas, angles, USPs, desires, emotions and themes. Pass a returned section and row key verbatim to adSpy.brand.getResearchAds. Rows can be ranked by ad count or longest-running-days, the available durability proxy. representativeAdId is a sample for the row and is not necessarily its longest-running ad.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type    | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string  | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                    |
| `window`          | enum    | No       | One of: `30d`, `3m`, `6m`, `12m`, `all`. Defaults to `"30d"`.                                                                                                                                                                    |
| `section`         | enum    | No       | One of: `hook`, `copy`, `headline`, `landing`, `persona`, `adAngle`, `usp`, `desire`, `emotion`, `theme`.                                                                                                                        |
| `sortBy`          | enum    | No       | One of: `ad_count`, `longest_running`. Defaults to `"ad_count"`.                                                                                                                                                                 |
| `limit`           | integer | No       | Maximum rows returned per research section. Between 1 and 10. Defaults to `10`.                                                                                                                                                  |
| `response_format` | enum    | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field              | Type                     | Description                                           |
| ------------------ | ------------------------ | ----------------------------------------------------- |
| `totalAds`         | integer                  |                                                       |
| `taggedAds`        | integer                  |                                                       |
| `groupingVersion`  | string                   | Length up to 100.                                     |
| `groupingPending`  | boolean                  |                                                       |
| `taggingPending`   | boolean                  |                                                       |
| `tagsCapped`       | boolean                  |                                                       |
| `sortedBy`         | enum                     | One of: `ad_count_desc`, `longest_running_days_desc`. |
| `performanceProxy` | "longest\_running\_days" |                                                       |
| `sections`         | array of object          | Items up to 10.                                       |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_research",
    "arguments": {
      "pageId": "example"
    }
  }
}
```

## `ad_spy_brand_get_research_ads`

**Get ads matching a brand research row**

Reads a bounded page of stored ads matching an exact research section and row key returned by adSpy.brand.getResearch. The response contains compact ad summaries rather than raw provider payloads and does not run a live provider search.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type           | Required | Description                                                                                                                                                                                                                      |
| ----------------- | -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string         | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                    |
| `window`          | enum           | No       | One of: `30d`, `3m`, `6m`, `12m`, `all`. Defaults to `"30d"`.                                                                                                                                                                    |
| `section`         | enum           | Yes      | One of: `hook`, `copy`, `headline`, `landing`, `persona`, `adAngle`, `usp`, `desire`, `emotion`, `theme`.                                                                                                                        |
| `rowKey`          | string         | Yes      | The exact row key returned by adSpy.brand.getResearch. Length 1 to 2048.                                                                                                                                                         |
| `cursor`          | string or null | No       | Opaque pagination cursor. Omit it for the first page; for the next page, pass the previous response nextCursor verbatim. Never invent, decode, or transform it. Defaults to `null`.                                              |
| `limit`           | integer        | No       | Between 1 and 25. Defaults to `10`.                                                                                                                                                                                              |
| `response_format` | enum           | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field        | Type            | Description                                                                                                       |
| ------------ | --------------- | ----------------------------------------------------------------------------------------------------------------- |
| `ads`        | array of object | The current page of stored ad summaries in stable order. Items up to 25.                                          |
| `nextCursor` | string or null  | Opaque cursor for the next page. Pass it verbatim as cursor on the next call; null means there are no more pages. |
| `totalCount` | integer or null | Exact matching-ad count on the first page; null on every page requested with a cursor.                            |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_research_ads",
    "arguments": {
      "pageId": "example",
      "section": "hook",
      "rowKey": "example"
    }
  }
}
```

## `ad_spy_brand_get_landing_page_ads`

**Get stored ads for a brand landing page**

Reads a bounded page of active stored ads that send traffic to an exact landing-page normalizedUrl supplied by the user, returned by adSpy.brand.getOverview, or returned as row\.key by the landing section of adSpy.brand.getResearch. Prefer the normalizedUrl or research row\.key; the action also normalizes a research row\.url display URL before lookup. Use this action instead of adSpy.brand.getResearchAds for exact landing-page URL requests. The response contains compact ad summaries and does not run a live provider search.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type           | Required | Description                                                                                                                                                                                                                                                                                               |
| ----------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageId`          | string         | Yes      | The exact page ID returned by an Ad Spy brand or ad search. Never infer or invent this value. Length 1 to 64.                                                                                                                                                                                             |
| `normalizedUrl`   | string         | Yes      | The landing-page normalizedUrl supplied by the user, returned by adSpy.brand.getOverview, or returned as row\.key by the landing section of adSpy.brand.getResearch. Prefer that exact normalized value. A research row\.url display URL is also accepted and normalized before lookup. Length 1 to 2048. |
| `timeWindow`      | enum           | No       | One of: `3m`, `6m`, `12m`, `all`. Defaults to `"all"`.                                                                                                                                                                                                                                                    |
| `cursor`          | string or null | No       | Opaque pagination cursor. Omit it for the first page; for the next page, pass the previous response nextCursor verbatim. Never invent, decode, or transform it. Defaults to `null`.                                                                                                                       |
| `limit`           | integer        | No       | Between 1 and 25. Defaults to `10`.                                                                                                                                                                                                                                                                       |
| `response_format` | enum           | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`.                                                                          |

### Output

| Field        | Type            | Description                                                                                                       |
| ------------ | --------------- | ----------------------------------------------------------------------------------------------------------------- |
| `ads`        | array of object | The current page of stored ad summaries in stable order. Items up to 25.                                          |
| `nextCursor` | string or null  | Opaque cursor for the next page. Pass it verbatim as cursor on the next call; null means there are no more pages. |
| `totalCount` | integer or null | Exact matching-ad count on the first page; null on every page requested with a cursor.                            |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_brand_get_landing_page_ads",
    "arguments": {
      "pageId": "example",
      "normalizedUrl": "example"
    }
  }
}
```

## `ad_spy_ads_count`

**Count stored Ad Spy ads and check freshness**

Counts the ads Sellify already holds for a keyword or one brand, without searching Meta. Returns how many there are, how many are still running, when the newest one was last seen, and when the keyword was last refreshed. Costs no credits.

Free. Call this before a paid Ad Spy search when the user asks how many ads exist, how fresh the data is, or whether a search is worth running. Report adCount and newestAdSeenAt as the real numbers. When searchLikelyFree is true, the Ad Spy search for the same keyword will most likely be answered from stored ads without spending credits. adCount 0 means Sellify holds nothing yet; a paid search may still find ads.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field     | Type   | Required | Description                                                                                                                              |
| --------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `query`   | string | No       | A keyword, product or niche from the user request. Pass this or pageId, not both. Length 1 to 200.                                       |
| `pageId`  | string | No       | The exact page ID of one brand, returned by an Ad Spy brand or ad search. Pass this or query, not both. Never invent it. Length 1 to 64. |
| `country` | string | No       | Two-letter country code. Omit for all countries. Length 2 to 2.                                                                          |
| `status`  | enum   | No       | ACTIVE counts only ads still running. Defaults to ACTIVE. One of: `ALL`, `ACTIVE`.                                                       |

### Output

| Field              | Type           | Description |
| ------------------ | -------------- | ----------- |
| `adCount`          | integer        |             |
| `activeAdCount`    | integer        |             |
| `newestAdSeenAt`   | string or null |             |
| `lastRefreshedAt`  | string or null |             |
| `searchLikelyFree` | boolean        |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_ads_count",
    "arguments": {}
  }
}
```

## `ad_spy_ads_aggregate`

**Summarize stored Ad Spy ads**

Summarizes the ads Sellify holds for a keyword or one brand: counts by ad format, by call-to-action button, by how long each ad has run, and by launch month for the last 12 months. Ad variations count once. Costs no credits.

Free. Use this when the user wants the shape of a market or a brand rather than individual ads: which formats dominate, which buttons advertisers use, how many ads run past 30 or 90 days (a sign they work), and whether launches are rising. Long-running ads are the strongest signal of a winning ad.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type   | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string | No       | A keyword, product or niche from the user request. Pass this or pageId, not both. Length 1 to 200.                                                                                                                               |
| `pageId`          | string | No       | The exact page ID of one brand, returned by an Ad Spy brand or ad search. Pass this or query, not both. Never invent it. Length 1 to 64.                                                                                         |
| `country`         | string | No       | Two-letter country code. Omit for all countries. Length 2 to 2.                                                                                                                                                                  |
| `status`          | enum   | No       | ACTIVE counts only ads still running. Defaults to ACTIVE. One of: `ALL`, `ACTIVE`.                                                                                                                                               |
| `response_format` | enum   | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field             | Type            | Description     |
| ----------------- | --------------- | --------------- |
| `adCount`         | integer         |                 |
| `activeAdCount`   | integer         |                 |
| `formats`         | array of object | Items up to 10. |
| `ctaTypes`        | array of object | Items up to 10. |
| `runLength`       | object          |                 |
| `launchesByMonth` | array of object | Items up to 12. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_ads_aggregate",
    "arguments": {}
  }
}
```

## `ad_spy_ads_top_hooks`

**Rank the most used ad hooks**

Ranks the opening hooks most reused across the ads Sellify holds for a keyword or one brand. Each hook shows how many ads used it, how many brands, its longest run in days, and one example ad. Costs no credits.

Free. Use this when the user asks which hooks, opening lines or angles work in a niche or for a brand. A hook reused across many ads, or one that has run for a long time, is a proven hook. Only ads Sellify has already analyzed have a hook, so report adsWithHookCount out of matchedAdCount. Pass sampleAdArchiveId to the per-ad hook tool for the full breakdown of an example.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type    | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string  | No       | A keyword, product or niche from the user request. Pass this or pageId, not both. Length 1 to 200.                                                                                                                               |
| `pageId`          | string  | No       | The exact page ID of one brand, returned by an Ad Spy brand or ad search. Pass this or query, not both. Never invent it. Length 1 to 64.                                                                                         |
| `country`         | string  | No       | Two-letter country code. Omit for all countries. Length 2 to 2.                                                                                                                                                                  |
| `status`          | enum    | No       | ACTIVE counts only ads still running. Defaults to ACTIVE. One of: `ALL`, `ACTIVE`.                                                                                                                                               |
| `limit`           | integer | No       | How many hooks to return. Defaults to 10. Between 1 and 25.                                                                                                                                                                      |
| `response_format` | enum    | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field              | Type            | Description     |
| ------------------ | --------------- | --------------- |
| `matchedAdCount`   | integer         |                 |
| `adsWithHookCount` | integer         |                 |
| `hooks`            | array of object | Items up to 25. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_ads_top_hooks",
    "arguments": {}
  }
}
```

## `ad_spy_ad_get_hooks`

**Get the hook and angle of one ad**

Returns what Sellify has already worked out about one ad: its hook, headline, angle, target persona, desire, emotion and selling point, plus the opening spoken words and on-screen text when available. Costs no credits.

Free. Use this when the user asks what hook or angle a specific ad uses. When analyzed is false, Sellify has not broken this ad down yet; for a video ad, offer to transcribe or analyze it instead, which costs credits.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field         | Type   | Required | Description                                                                                             |
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------- |
| `adArchiveId` | string | Yes      | The ad archive ID from an Ad Spy search, saved ad or top hooks result. Never invent it. Length 1 to 64. |

### Output

| Field           | Type            | Description      |
| --------------- | --------------- | ---------------- |
| `adArchiveId`   | string          | Length up to 64. |
| `analyzed`      | boolean         |                  |
| `hook`          | string or null  |                  |
| `headline`      | string or null  |                  |
| `angle`         | string or null  |                  |
| `persona`       | string or null  |                  |
| `desire`        | string or null  |                  |
| `emotion`       | string or null  |                  |
| `sellingPoint`  | string or null  |                  |
| `spokenOpening` | string or null  |                  |
| `onScreenText`  | array of string | Items up to 3.   |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_ad_get_hooks",
    "arguments": {
      "adArchiveId": "example"
    }
  }
}
```

## `ad_spy_advertisers_find_by_domain`

**Find advertisers by website domain**

Finds the brand pages whose stored ads send people to a website domain or store URL, including its subdomains. Returns each brand page ID, name and ad counts. Costs no credits.

Free. Use this when the user gives a website or store URL instead of a brand name, or asks who advertises a site. Pass the pageId from a result to the brand tools for that brand. An empty list means Sellify holds no ads pointing at that domain yet; then search Ad Spy brands by name.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type    | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain`          | string  | Yes      | A website domain or store URL from the user request, such as gymshark.com or `https://www.gymshark.com/collections/new`. Length 3 to 2048.                                                                                       |
| `limit`           | integer | No       | How many advertisers to return. Defaults to 10. Between 1 and 25.                                                                                                                                                                |
| `response_format` | enum    | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field         | Type            | Description       |
| ------------- | --------------- | ----------------- |
| `domain`      | string          | Length up to 253. |
| `advertisers` | array of object | Items up to 25.   |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_advertisers_find_by_domain",
    "arguments": {
      "domain": "example"
    }
  }
}
```

## `ad_spy_filter_preset_list`

**List Ad Spy filter presets**

Lists the saved Ad Spy filter presets in this workspace in one call, newest 50 first, and sets truncated when there are more; pass pageType only to narrow to one page type. Each preset has the exact id needed to update, delete or make it the default. canEdit says whether the current user may update or delete it; any member can make a preset the default.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ---- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageType`        | enum | No       | One of: `discovery`, `following`.                                                                                                                                                                                                |
| `response_format` | enum | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field       | Type            | Description     |
| ----------- | --------------- | --------------- |
| `presets`   | array of object | Items up to 50. |
| `truncated` | boolean         |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_filter_preset_list",
    "arguments": {}
  }
}
```

## `ad_spy_filter_preset_create`

**Create an Ad Spy filter preset**

Creates a named filter preset for discovery or followed-brand ads. Names must be unique within the page type.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |

### Input

| Field       | Type    | Required | Description                       |
| ----------- | ------- | -------- | --------------------------------- |
| `name`      | string  | Yes      | Length 1 to 100.                  |
| `pageType`  | enum    | Yes      | One of: `discovery`, `following`. |
| `config`    | object  | Yes      |                                   |
| `isDefault` | boolean | No       | Defaults to `false`.              |

### Output

| Field       | Type          | Description                       |
| ----------- | ------------- | --------------------------------- |
| `id`        | string (uuid) |                                   |
| `name`      | string        |                                   |
| `pageType`  | enum          | One of: `discovery`, `following`. |
| `config`    | object        |                                   |
| `isDefault` | boolean       |                                   |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_filter_preset_create",
    "arguments": {
      "name": "example",
      "pageType": "discovery",
      "config": {
        "country": "example",
        "activeOnly": true,
        "hideAiGenerated": true,
        "minVariations": 1,
        "minBrandFollowers": 1,
        "minCopyLength": 1,
        "startedAfter": "example",
        "limitPerBrand": 1,
        "adFormats": [
          "IMAGE"
        ],
        "channels": [
          "example"
        ],
        "ctaTypes": [
          "example"
        ]
      }
    }
  }
}
```

## `ad_spy_filter_preset_update`

**Update an Ad Spy filter preset**

Updates a preset created by the current user. Only provided fields change.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field       | Type          | Required | Description      |
| ----------- | ------------- | -------- | ---------------- |
| `id`        | string (uuid) | Yes      |                  |
| `name`      | string        | No       | Length 1 to 100. |
| `config`    | object        | No       |                  |
| `isDefault` | boolean       | No       |                  |

### Output

| Field       | Type          | Description                       |
| ----------- | ------------- | --------------------------------- |
| `id`        | string (uuid) |                                   |
| `name`      | string        |                                   |
| `pageType`  | enum          | One of: `discovery`, `following`. |
| `config`    | object        |                                   |
| `isDefault` | boolean       |                                   |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_filter_preset_update",
    "arguments": {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_filter_preset_delete`

**Delete an Ad Spy filter preset**

Deletes a preset created by the current user.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field | Type          | Required | Description |
| ----- | ------------- | -------- | ----------- |
| `id`  | string (uuid) | Yes      |             |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_filter_preset_delete",
    "arguments": {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_filter_preset_set_default`

**Set the default Ad Spy filter preset**

Sets one preset as the default for a page type, or clears the default when id is null.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field      | Type                  | Required | Description                       |
| ---------- | --------------------- | -------- | --------------------------------- |
| `id`       | string (uuid) or null | Yes      |                                   |
| `pageType` | enum                  | Yes      | One of: `discovery`, `following`. |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_filter_preset_set_default",
    "arguments": {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "pageType": "discovery"
    }
  }
}
```

## `ad_spy_saved_search_list`

**List saved Ad Spy searches**

Lists the saved Ad Spy searches in this workspace, newest 50 first, with the exact id needed to run or delete one and the keyword or brand each one searches. canDelete says whether the current user may delete it. Costs no credits.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field             | Type | Required | Description                                                                                                                                                                                                                      |
| ----------------- | ---- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `response_format` | enum | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field           | Type            | Description     |
| --------------- | --------------- | --------------- |
| `savedSearches` | array of object | Items up to 50. |
| `truncated`     | boolean         |                 |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_search_list",
    "arguments": {}
  }
}
```

## `ad_spy_saved_search_create`

**Save an Ad Spy search**

Saves a named Ad Spy search, a keyword or one brand page ID plus country, status and sort, so it can be run again later. Saving does not run the search and costs no credits. A saved search is not a filter preset: presets hold filters for the Ad Spy page and have no search term.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |

### Input

| Field        | Type            | Required | Description                                                                                                                                                                  |
| ------------ | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`       | string          | Yes      | A short name the user will recognize, such as "Cold plunge US". Length 1 to 100.                                                                                             |
| `query`      | string          | No       | For a keyword search: the keyword, product or advertiser name itself, without words like "ads", for example "cold plunge". Pass this or pageId, never both. Length 1 to 200. |
| `pageId`     | string          | No       | Only for a search of one brand: its verified page ID from an Ad Spy brand search. Leave it out of a keyword search. Never invent it. Length 1 to 64.                         |
| `pageName`   | string          | No       | Only with pageId: the brand name returned with it. Leave it out of a keyword search. Length 1 to 200.                                                                        |
| `country`    | "ALL" or string | No       | Two-letter country code, or ALL. Omit to use the search default.                                                                                                             |
| `status`     | enum            | No       | ACTIVE for ads still running, ALL for every ad. INACTIVE works only with pageId. Omit to use the search default. One of: `ALL`, `ACTIVE`, `INACTIVE`.                        |
| `sortBy`     | enum            | No       | Omit unless the user asks for a sort order. One of: `total_impressions`, `relevancy_monthly_grouped`.                                                                        |
| `timeWindow` | enum            | No       | Only with pageId: how far back to look. Leave it out of a keyword search, and omit it for all time. One of: `3m`, `6m`, `12m`, `all`.                                        |

### Output

| Field        | Type           | Description                                               |
| ------------ | -------------- | --------------------------------------------------------- |
| `id`         | string (uuid)  |                                                           |
| `name`       | string         |                                                           |
| `query`      | string or null |                                                           |
| `pageId`     | string or null |                                                           |
| `pageName`   | string or null |                                                           |
| `country`    | string or null |                                                           |
| `status`     | enum or null   | One of: `ALL`, `ACTIVE`, `INACTIVE`.                      |
| `sortBy`     | enum or null   | One of: `total_impressions`, `relevancy_monthly_grouped`. |
| `timeWindow` | enum or null   | One of: `3m`, `6m`, `12m`, `all`.                         |
| `createdAt`  | string         |                                                           |
| `canDelete`  | boolean        |                                                           |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_search_create",
    "arguments": {
      "name": "example"
    }
  }
}
```

## `ad_spy_saved_search_delete`

**Delete a saved Ad Spy search**

Deletes a saved Ad Spy search created by the current user. The ads it found are not affected.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field | Type          | Required | Description                                                                              |
| ----- | ------------- | -------- | ---------------------------------------------------------------------------------------- |
| `id`  | string (uuid) | Yes      | The exact saved search id returned when the search was listed or saved. Never invent it. |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_search_delete",
    "arguments": {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_saved_search_run`

**Run a saved Ad Spy search**

Runs a saved Ad Spy search by its id and returns the same ads a fresh search with its keyword or brand would return. It is charged exactly like that search: often nothing when Sellify already holds fresh ads, otherwise a few credits per results page.

Use this when the user asks to run, rerun or check a search they saved, passing the id from the saved search list. max\_credits is the most the run may spend, not what it will cost.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | About 2.4 credits           |
| Safe to repeat | Yes                         |

### Input

| Field             | Type           | Required | Description                                                                                                                                                                                                                      |
| ----------------- | -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string (uuid)  | Yes      | The exact saved search id returned when the search was listed or saved. Never invent it.                                                                                                                                         |
| `cursor`          | string or null | No       | The cursor from the previous run of this saved search, to get the next page. Omit for the first page.                                                                                                                            |
| `idempotency_key` | string         | No       | Client-chosen key identifying this call. Reuse it only when retrying the same call. Length 1 to 200.                                                                                                                             |
| `max_credits`     | number         | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                                                                                                                                                    |
| `response_format` | enum           | No       | "concise" (the default) shortens long text and leaves out nested details in each result. Pass "detailed" only when you need the full text or nested details of a result. One of: `concise`, `detailed`. Defaults to `"concise"`. |

### Output

| Field             | Type            | Description                                                                              |
| ----------------- | --------------- | ---------------------------------------------------------------------------------------- |
| `ads`             | array of object | Items up to 50.                                                                          |
| `cursor`          | string or null  |                                                                                          |
| `totalCount`      | number or null  |                                                                                          |
| `servedFrom`      | enum or null    | One of: `archive`, `provider`.                                                           |
| `failedBrands`    | array of object |                                                                                          |
| `savedSearch`     | object          |                                                                                          |
| `credits_charged` | number          | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null  | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_search_run",
    "arguments": {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_saved_ad_share`

**Create a public share link for a saved ad**

Enables public sharing for the selected saved ad. Anyone with the returned link can view it. Repeating the action returns the existing link. Refused while impersonating a user.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type          | Required | Description                                                                                              |
| -------------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `savedSpyAdId` | string (uuid) | Yes      | The id of a saved ad in this workspace, as listed among its saved ads. Never infer or invent this value. |

### Output

| Field       | Type         | Description |
| ----------- | ------------ | ----------- |
| `shareSlug` | string       |             |
| `shareUrl`  | string (uri) |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_ad_share",
    "arguments": {
      "savedSpyAdId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_saved_ad_unshare`

**Revoke a saved-ad share link**

Disables public sharing for the selected saved ad. Repeating the action is safe.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Changes or deletes data       |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | Free                          |
| Who can call it | Workspace owners and admins   |
| Safe to repeat  | Yes                           |

### Input

| Field          | Type          | Required | Description                                                                                              |
| -------------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `savedSpyAdId` | string (uuid) | Yes      | The id of a saved ad in this workspace, as listed among its saved ads. Never infer or invent this value. |

### Output

| Field     | Type | Description |
| --------- | ---- | ----------- |
| `success` | true |             |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_saved_ad_unshare",
    "arguments": {
      "savedSpyAdId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## `ad_spy_video_transcript_start`

**Start video ad transcription**

Starts transcription for a video ad. If the result is pending, poll the transcript status action until it is ready or failed.

Use this when the user wants the words spoken in a video ad. Take adArchiveId from an Ad Spy search or saved ad result; never invent one. Transcription runs in the background. This returns pending or ready, never the transcript itself: poll the video transcript status tool with the same adArchiveId until it is ready or failed, and read the transcript from that result.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | About 0.25 credits            |
| Who can call it | Workspace owners and admins   |

### Input

| Field             | Type   | Required | Description                                                                                           |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `adArchiveId`     | string | Yes      | Length 1 to 64.                                                                                       |
| `idempotency_key` | string | No       | Client-chosen key identifying this write. Reuse it only when retrying the same call. Length 1 to 200. |
| `max_credits`     | number | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                         |

### Output

| Field             | Type           | Description                                                                              |
| ----------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `status`          | enum           | One of: `pending`, `ready`.                                                              |
| `credits_charged` | number         | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_transcript_start",
    "arguments": {
      "adArchiveId": "example",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_video_transcript_get_status`

**Get a video ad transcript status**

Checks whether a video ad transcript is missing, pending, failed, or ready and returns the transcript when ready. Poll this after starting transcription.

Pass the adArchiveId whose transcription was started. While the status is pending, wait a few seconds and call this again. When it is ready, read the words from transcript. Missing means transcription was never started for this ad.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field         | Type   | Required | Description     |
| ------------- | ------ | -------- | --------------- |
| `adArchiveId` | string | Yes      | Length 1 to 64. |

### Output

The result is text for the model to read.

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_transcript_get_status",
    "arguments": {
      "adArchiveId": "example"
    }
  }
}
```

## `ad_spy_video_analysis_start`

**Start full video ad analysis**

Starts structured full-video analysis for an ad. If the result is pending, poll the video analysis status action until it is ready or failed.

Use this when the user wants a video ad broken down scene by scene, such as its hook, visuals and pacing. When they only want the spoken words, transcribe the video instead, which costs less. Take adArchiveId from an Ad Spy search or saved ad result; never invent one. Analysis runs in the background. This returns pending or ready, never the analysis itself: poll the video analysis status tool with the same adArchiveId until it is ready or failed, and read the analysis from that result.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | About 3 credits               |
| Who can call it | Workspace owners and admins   |

### Input

| Field             | Type           | Required | Description                                                                                           |
| ----------------- | -------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `adArchiveId`     | string         | Yes      | Length 1 to 64.                                                                                       |
| `brandName`       | string or null | No       |                                                                                                       |
| `idempotency_key` | string         | No       | Client-chosen key identifying this write. Reuse it only when retrying the same call. Length 1 to 200. |
| `max_credits`     | number         | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                         |

### Output

| Field             | Type           | Description                                                                              |
| ----------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `status`          | enum           | One of: `pending`, `ready`.                                                              |
| `credits_charged` | number         | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_analysis_start",
    "arguments": {
      "adArchiveId": "example",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_video_analysis_get_status`

**Get a video ad analysis status**

Checks whether full video analysis is missing, pending, failed, or ready and returns the structured scene analysis when ready. Poll this after starting analysis.

Pass the adArchiveId whose analysis was started. While the status is pending, wait a few seconds and call this again. When it is ready, read the scene-by-scene breakdown from the result.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field         | Type   | Required | Description     |
| ------------- | ------ | -------- | --------------- |
| `adArchiveId` | string | Yes      | Length 1 to 64. |

### Output

The result is text for the model to read.

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_analysis_get_status",
    "arguments": {
      "adArchiveId": "example"
    }
  }
}
```

## `ad_spy_video_similar_scripts_start`

**Generate similar video-ad scripts**

Queues three product-specific scripts from a snapshotted video transcript and returns a submission id to poll.

Use this when the user wants new video ad scripts modeled on an Ad Spy video ad for one of their saved products. Take adArchiveId from an Ad Spy search or saved ad result and productId from the product list; never invent either. The ad must be transcribed first: if it has no transcript, transcribe it and wait until its transcript is ready. Each call writes three scripts. Then poll the similar-scripts status tool with the returned submissionId until it is ready or failed, and read the scripts from that result.

| Property        | Value                         |
| --------------- | ----------------------------- |
| Access          | Writes data                   |
| Scope           | Ad Spy: write (`adspy:write`) |
| Credits         | About 1 credit                |
| Who can call it | Workspace owners and admins   |

### Input

| Field             | Type          | Required | Description                                                                                           |
| ----------------- | ------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `adArchiveId`     | string        | Yes      | Length 1 to 64.                                                                                       |
| `productId`       | string (uuid) | Yes      |                                                                                                       |
| `idempotency_key` | string        | No       | Client-chosen key identifying this write. Reuse it only when retrying the same call. Length 1 to 200. |
| `max_credits`     | number        | Yes      | The most credits this call may spend, with at most two decimals. Up to 10000.                         |

### Output

| Field             | Type           | Description                                                                              |
| ----------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `submissionId`    | string (uuid)  |                                                                                          |
| `credits_charged` | number         | Workspace credits charged by this call.                                                  |
| `credits_left`    | number or null | Workspace credits remaining after this call, or null when the balance could not be read. |

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_similar_scripts_start",
    "arguments": {
      "adArchiveId": "example",
      "productId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "max_credits": 1
    }
  }
}
```

## `ad_spy_video_similar_scripts_get_status`

**Get similar-script generation status**

Poll after starting similar-script generation. Returns bounded scripts only when ready.

Pass the submissionId returned when similar-script generation started. While the status is pending or processing, wait a few seconds and call this again. When it is ready, read the scripts from the result.

| Property       | Value                       |
| -------------- | --------------------------- |
| Access         | Read-only                   |
| Scope          | Ad Spy: read (`adspy:read`) |
| Credits        | Free                        |
| Safe to repeat | Yes                         |

### Input

| Field          | Type          | Required | Description |
| -------------- | ------------- | -------- | ----------- |
| `submissionId` | string (uuid) | Yes      |             |

### Output

The result is text for the model to read.

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ad_spy_video_similar_scripts_get_status",
    "arguments": {
      "submissionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  }
}
```

## Related

[Tool reference overview](https://sellify.ai/docs/developers/mcp-tools) · [Authentication](https://sellify.ai/docs/developers/authentication) · [Credits and limits](https://sellify.ai/docs/developers/credits-and-limits)
