# Competitors actions

> Competitors: 4 Xholic actions (1 read, 3 change), each with its MCP tool, REST endpoint and CLI command.

Source: https://docs.xholic.ai/actions/competitors/

4 actions. Every field marked *Required* must be sent; `account`, `dryRun`, `idempotencyKey`, `confirmCredits` and `quoteId` are the [control fields](/api/responses/#control-fields) every surface adds.

## Product competitors

`competitors.list` · read

A product's competitors, optionally discovering new ones.

- **MCP tool:** `competitors_list`. Catalog: reach it with `find_actions` and `run_read_action`, or turn on the full toolset.
- **REST:** `GET /v1/competitors/list`
- **CLI:** `xholic competitors list`
- **Scope:** `read`
- **Plan:** Pro plan or higher
- **Cost:** Free.
- **Rate limit bucket:** `read`

**Input**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string (uuid) | Yes |  |
| `discover` | boolean | No | Search for competitors when the product has none yet. Default: `false`. |
| `account` | string ≤ 64 chars | No | X account to act on, as @handle. Leave it out to use the connection's default account. |

## Add a competitor

`competitors.add` · write

Add a competitor to a product. Call it only when the user asked for this in the conversation; never on your own initiative.

- **MCP tool:** `competitors_add`. Catalog: reach it with `find_actions` and `run_write_action`, or turn on the full toolset.
- **REST:** `POST /v1/competitors/add`
- **CLI:** `xholic competitors add`
- **Scope:** `write`
- **Plan:** Pro plan or higher
- **Cost:** Free.
- **Rate limit bucket:** `write`

**Input**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string (uuid) | Yes |  |
| `entry` | string ≤ 200 chars | Yes | An @handle, an x.com profile link or a company name. |
| `account` | string ≤ 64 chars | No | X account to act on, as @handle. Leave it out to use the connection's default account. |
| `dryRun` | boolean | No | Return exactly what would happen without doing it. |
| `idempotencyKey` | string ≤ 200 chars | No | A unique key for this write. Repeating a call with the same key returns the first result instead of acting twice. |

## Discover competitors

`competitors.discover` · write

Find a product's competitors and add them as suggestions to accept or dismiss. Works once per product per cooldown. Call it only when the user asked for this in the conversation; never on your own initiative.

- **MCP tool:** `competitors_discover`. Catalog: reach it with `find_actions` and `run_write_action`, or turn on the full toolset.
- **REST:** `POST /v1/competitors/discover`
- **CLI:** `xholic competitors discover`
- **Scope:** `write`
- **Plan:** Pro plan or higher
- **Cost:** Free.
- **Rate limit bucket:** `write`

**Input**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string (uuid) | Yes | Product id from signals.products. |
| `account` | string ≤ 64 chars | No | X account to act on, as @handle. Leave it out to use the connection's default account. |
| `dryRun` | boolean | No | Return exactly what would happen without doing it. |
| `idempotencyKey` | string ≤ 200 chars | No | A unique key for this write. Repeating a call with the same key returns the first result instead of acting twice. |

## Accept or remove a competitor

`competitors.set_status` · write

ACCEPTED keeps a suggested competitor; DISMISSED removes any competitor. Call it only when the user asked for this in the conversation; never on your own initiative.

- **MCP tool:** `competitors_set_status`. Catalog: reach it with `find_actions` and `run_write_action`, or turn on the full toolset.
- **REST:** `POST /v1/competitors/set-status`
- **CLI:** `xholic competitors set-status`
- **Scope:** `write`
- **Plan:** Pro plan or higher
- **Cost:** Free.
- **Rate limit bucket:** `write`

**Input**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string (uuid) | Yes | Product id from signals.products. |
| `competitorId` | string (uuid) | Yes | Competitor id from competitors.list. |
| `status` | "ACCEPTED" \\| "DISMISSED" | Yes |  |
| `account` | string ≤ 64 chars | No | X account to act on, as @handle. Leave it out to use the connection's default account. |
| `dryRun` | boolean | No | Return exactly what would happen without doing it. |
| `idempotencyKey` | string ≤ 200 chars | No | A unique key for this write. Repeating a call with the same key returns the first result instead of acting twice. |
