> ## Documentation Index
> Fetch the complete documentation index at: https://octolens.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Keywords

> Manage the terms you monitor, and review the AI's keyword-tuning suggestions.

Flags and arguments below are the contract as the binary states it. The global flags (`--json`, `--timeout`, …) apply here too and are documented on [Global flags](/docs/cli/contract/global-flags). Error codes are a workspace-global contract, not a per-command one — the taxonomy, and how to read a code that is not in it, is on [The error envelope](/docs/cli/contract/error-envelope).

## `octolens keywords add`

Start monitoring a new keyword (interactive on a TTY)

**Arguments**

| Argument | Type     | Required | Description                                |
| -------- | -------- | -------- | ------------------------------------------ |
| `TERM`   | `string` | optional | The phrase to track (equivalent to --term) |

**Flags**

| Flag                 | Type      | Required (headless) | Description                                                                                                                                      |
| -------------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--additional-terms` | `string`  | no                  | Comma-separated terms required alongside the main keyword                                                                                        |
| `--allow-duplicate`  | `boolean` | no                  | Create the keyword even if the exact term is already tracked (default: adding an already-tracked term is a no-op returning the existing keyword) |
| `--context`          | `string`  | no                  | Short sentence disambiguating the keyword for AI relevance scoring                                                                               |
| `--exclude-words`    | `string`  | no                  | Comma-separated words that disqualify a post if present                                                                                          |
| `--source`           | `string`  | no                  | Platform to monitor (repeatable; defaults to every plan-allowed source)                                                                          |
| `--tag`              | `string`  | no                  | Classification: own\_brand, competitor, industry\_term                                                                                           |
| `--term`             | `string`  | yes (headless)      | The phrase to track (alternative to the positional TERM)                                                                                         |

**Examples**

```bash theme={null}
octolens keywords add 'acme corp'
octolens keywords add 'acme corp' --source reddit --source twitter
octolens keywords add --term 'acme corp' --context 'cloud storage company' --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/keywords`.

| Field                  | Type                                                       | Description                                                                                                                        |
| ---------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `id`                   | integer                                                    | Stable numeric keyword id — what `keywords update/pause/resume/rm` accept.                                                         |
| `keyword`              | string                                                     | The phrase being tracked.                                                                                                          |
| `context`              | string \| null                                             | Disambiguation sentence used by AI relevance scoring. Auto-generated from the company profile when omitted at creation.            |
| `additionalTerms`      | string \| null                                             | Comma-separated terms required alongside the main keyword. `null` when none.                                                       |
| `additionalTermsAndOr` | boolean                                                    | How `additionalTerms` combine: `true` = OR (any one), `false` = AND (all).                                                         |
| `caseSensitive`        | boolean                                                    | Whether matching is case-sensitive.                                                                                                |
| `symbolSensitive`      | boolean                                                    | Exact-match mode: `true` requires multi-word keywords to appear together.                                                          |
| `platforms`            | string\[]                                                  | Platform slugs this keyword is monitored on (`reddit`, `twitter`, …).                                                              |
| `excludeWords`         | string \| null                                             | Comma-separated exact-match exclusions. `null` when none.                                                                          |
| `wildcardExcludeWords` | string \| null                                             | Comma-separated wildcard exclusion patterns (`*` supported). `null` when none.                                                     |
| `excludeAuthors`       | string \| null                                             | Comma-separated author handles whose posts are filtered out. `null` when none.                                                     |
| `tag`                  | enum: `own_brand`, `competitor`, `industry_term` — or null | Keyword classification. `null` for legacy keywords without a tag.                                                                  |
| `paused`               | boolean                                                    | When `true`, data collection is paused for this keyword.                                                                           |
| `isSubReddit`          | boolean \| null                                            | `true` when the keyword is a subreddit to monitor rather than a phrase. `null` for non-Reddit keywords.                            |
| `alreadyExisted`       | boolean                                                    | `true` when the term was already tracked (case-insensitive) and the existing keyword was returned instead of creating a duplicate. |

Without `--json`: A terminal prints a confirmation line and the keyword's full definition.

<Accordion title="Example output">
  ```json theme={null}
  {
    "id": 42,
    "keyword": "acme corp",
    "context": "Acme is a cloud storage company, not the cartoon.",
    "additionalTerms": null,
    "additionalTermsAndOr": true,
    "caseSensitive": false,
    "symbolSensitive": true,
    "platforms": [
      "reddit",
      "twitter",
      "hackernews"
    ],
    "excludeWords": "jobs,hiring",
    "wildcardExcludeWords": null,
    "excludeAuthors": null,
    "tag": "own_brand",
    "paused": false,
    "isSubReddit": null,
    "alreadyExisted": false
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE · `8` CANCELLED. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens keywords list`

List your tracked keywords with status and mention volume

**Flags**

| Flag       | Type      | Required (headless) | Description                                                                                                                                  |
| ---------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `--all`    | `boolean` | no                  | Show the full collection (the default for this bounded list)                                                                                 |
| `--limit`  | `integer` | no                  | Show only the first N items (mutually exclusive with --all)                                                                                  |
| `--volume` | `boolean` | no                  | Include each keyword's recent mention volume (default). --no-volume skips the analytics aggregation for a much faster list (default: `true`) |

**Examples**

```bash theme={null}
octolens keywords list
octolens keywords list --json
octolens keywords list --no-volume
octolens keywords list --limit 5
octolens keywords list --all --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `GET /api/v2/keywords`.

| Field                         | Type                                                       | Description                                                                                                                                       |
| ----------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`                        | object\[]                                                  | Every tracked keyword, sorted by name (case-insensitive, id tie-break).                                                                           |
| `data[].id`                   | integer                                                    | Stable numeric keyword id — what `keywords update/pause/resume/rm` accept.                                                                        |
| `data[].keyword`              | string                                                     | The phrase being tracked.                                                                                                                         |
| `data[].context`              | string \| null                                             | Disambiguation sentence used by AI relevance scoring. Auto-generated from the company profile when omitted at creation.                           |
| `data[].additionalTerms`      | string \| null                                             | Comma-separated terms required alongside the main keyword. `null` when none.                                                                      |
| `data[].additionalTermsAndOr` | boolean                                                    | How `additionalTerms` combine: `true` = OR (any one), `false` = AND (all).                                                                        |
| `data[].caseSensitive`        | boolean                                                    | Whether matching is case-sensitive.                                                                                                               |
| `data[].symbolSensitive`      | boolean                                                    | Exact-match mode: `true` requires multi-word keywords to appear together.                                                                         |
| `data[].platforms`            | string\[]                                                  | Platform slugs this keyword is monitored on (`reddit`, `twitter`, …).                                                                             |
| `data[].excludeWords`         | string \| null                                             | Comma-separated exact-match exclusions. `null` when none.                                                                                         |
| `data[].wildcardExcludeWords` | string \| null                                             | Comma-separated wildcard exclusion patterns (`*` supported). `null` when none.                                                                    |
| `data[].excludeAuthors`       | string \| null                                             | Comma-separated author handles whose posts are filtered out. `null` when none.                                                                    |
| `data[].tag`                  | enum: `own_brand`, `competitor`, `industry_term` — or null | Keyword classification. `null` for legacy keywords without a tag.                                                                                 |
| `data[].paused`               | boolean                                                    | When `true`, data collection is paused for this keyword.                                                                                          |
| `data[].isSubReddit`          | boolean \| null                                            | `true` when the keyword is a subreddit to monitor rather than a phrase. `null` for non-Reddit keywords.                                           |
| `data[].volume`               | integer \| null                                            | Recent mention volume from the analytics breakdown. `0` = tracked but quiet; `null` strictly means unavailable (lookup failed, or `--no-volume`). |
| `pagination.nextCursor`       | null                                                       | Always `null`: keywords are a bounded collection (`--limit`/`--all` clip client-side).                                                            |

When the volume aggregation itself fails, the payload additionally carries a `warning` string naming the failure (every `volume` is then `null`); the keyword list itself is still complete.

Without `--json`: A terminal renders an aligned keyword table with status and volume; piped stdout emits one tab-delimited record per keyword.

<Accordion title="Example output">
  ```json theme={null}
  {
    "data": [
      {
        "id": 42,
        "keyword": "acme corp",
        "context": "Acme is a cloud storage company, not the cartoon.",
        "additionalTerms": null,
        "additionalTermsAndOr": true,
        "caseSensitive": false,
        "symbolSensitive": true,
        "platforms": [
          "reddit",
          "twitter",
          "hackernews"
        ],
        "excludeWords": "jobs,hiring",
        "wildcardExcludeWords": null,
        "excludeAuthors": null,
        "tag": "own_brand",
        "paused": false,
        "isSubReddit": null,
        "volume": 312
      }
    ],
    "pagination": {
      "nextCursor": null
    }
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens keywords pause`

Pause data collection for a keyword (idempotent)

**Arguments**

| Argument  | Type     | Required | Description                 |
| --------- | -------- | -------- | --------------------------- |
| `KEYWORD` | `string` | required | Keyword id or name to pause |

**Examples**

```bash theme={null}
octolens keywords pause 42
octolens keywords pause 'acme corp' --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/keywords/{id}/pause`.

| Field     | Type    | Description                                                                                             |
| --------- | ------- | ------------------------------------------------------------------------------------------------------- |
| `id`      | integer | Keyword id.                                                                                             |
| `keyword` | string  | Keyword text.                                                                                           |
| `paused`  | boolean | The committed state after this write (always `true` here).                                              |
| `changed` | boolean | `true` when THIS request moved the row; `false` when the keyword was already paused (idempotent no-op). |

Without `--json`: A terminal prints one confirmation line naming the committed state.

Example output:

```json theme={null}
{
  "id": 42,
  "keyword": "acme corp",
  "paused": true,
  "changed": true
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens keywords resume`

Resume data collection for a keyword (idempotent)

**Arguments**

| Argument  | Type     | Required | Description                  |
| --------- | -------- | -------- | ---------------------------- |
| `KEYWORD` | `string` | required | Keyword id or name to resume |

**Examples**

```bash theme={null}
octolens keywords resume 42
octolens keywords resume 'acme corp' --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/keywords/{id}/pause`.

| Field     | Type    | Description                                                                                             |
| --------- | ------- | ------------------------------------------------------------------------------------------------------- |
| `id`      | integer | Keyword id.                                                                                             |
| `keyword` | string  | Keyword text.                                                                                           |
| `paused`  | boolean | The committed state after this write (always `false` here).                                             |
| `changed` | boolean | `true` when THIS request moved the row; `false` when the keyword was already active (idempotent no-op). |

Without `--json`: A terminal prints one confirmation line naming the committed state.

Example output:

```json theme={null}
{
  "id": 42,
  "keyword": "acme corp",
  "paused": false,
  "changed": true
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens keywords rm`

Delete a keyword (confirms on a TTY; --yes headless)

**Arguments**

| Argument  | Type     | Required | Description                  |
| --------- | -------- | -------- | ---------------------------- |
| `KEYWORD` | `string` | required | Keyword id or name to delete |

**Flags**

| Flag    | Type      | Required (headless) | Description                  |
| ------- | --------- | ------------------- | ---------------------------- |
| `--yes` | `boolean` | yes (headless)      | Skip the confirmation prompt |

**Examples**

```bash theme={null}
octolens keywords rm 42 --yes
octolens keywords rm 'acme corp' --yes
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `DELETE /api/v2/keywords/{id}`.

| Field                                     | Type      | Description                                                                                                            |
| ----------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------- |
| `ok`                                      | boolean   | Always `true` — a refused deletion answers the error envelope instead.                                                 |
| `id`                                      | integer   | Id of the deleted keyword.                                                                                             |
| `keyword`                                 | string    | Term of the deleted keyword.                                                                                           |
| `deletedFeeds`                            | object\[] | Feeds destroyed with the keyword because their filters referenced only it. Always present; `[]` when nothing cascaded. |
| `deletedFeeds[].id`                       | integer   | Deleted feed id.                                                                                                       |
| `deletedFeeds[].name`                     | string    | Deleted feed name.                                                                                                     |
| `deletedNotifications`                    | object\[] | Notifications destroyed with those feeds. Always present; `[]` when nothing cascaded.                                  |
| `deletedNotifications[].id`               | integer   | Deleted notification id.                                                                                               |
| `deletedNotifications[].name`             | string    | Deleted notification name.                                                                                             |
| `deletedNotifications[].feedId`           | integer   | The feed the notification was attached to.                                                                             |
| `deletedNotifications[].destinationCount` | integer   | How many delivery destinations the notification had.                                                                   |

Without `--json`: A terminal confirms the deletion and names every cascaded feed and notification.

<Accordion title="Example output">
  ```json theme={null}
  {
    "ok": true,
    "id": 42,
    "keyword": "acme corp",
    "deletedFeeds": [
      {
        "id": 25248,
        "name": "Acme mentions"
      }
    ],
    "deletedNotifications": [
      {
        "id": 19,
        "name": "Acme alert",
        "feedId": 25248,
        "destinationCount": 1
      }
    ]
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE · `8` CANCELLED. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens keywords update`

Update a keyword's matching config (by id or name)

**Arguments**

| Argument  | Type     | Required | Description                  |
| --------- | -------- | -------- | ---------------------------- |
| `KEYWORD` | `string` | required | Keyword id or name to update |

**Flags**

| Flag                       | Type      | Required (headless) | Description                                                       |
| -------------------------- | --------- | ------------------- | ----------------------------------------------------------------- |
| `--additional-terms`       | `string`  | no                  | Replace comma-separated additional terms (empty string clears)    |
| `--additional-terms-or`    | `boolean` | no                  | Combine additional terms with OR (default) instead of AND         |
| `--case-sensitive`         | `boolean` | no                  | Toggle case-sensitive matching                                    |
| `--context`                | `string`  | no                  | Replace the relevance-context sentence                            |
| `--exact-match`            | `boolean` | no                  | Toggle "exact match" (symbol-sensitive) mode                      |
| `--exclude-authors`        | `string`  | no                  | Replace comma-separated excluded authors (empty string clears)    |
| `--exclude-words`          | `string`  | no                  | Replace comma-separated exclude words (empty string clears)       |
| `--source`                 | `string`  | no                  | Replace the monitored platforms (repeatable)                      |
| `--tag`                    | `string`  | no                  | Set classification: own\_brand, competitor, industry\_term        |
| `--wildcard-exclude-words` | `string`  | no                  | Replace comma-separated wildcard exclusions (empty string clears) |

**Examples**

```bash theme={null}
octolens keywords update 42 --exclude-words 'jobs, hiring'
octolens keywords update 'acme corp' --source reddit --source twitter
octolens keywords update 42 --exact-match --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `PATCH /api/v2/keywords/{id}`.

| Field                  | Type                                                       | Description                                                                                                             |
| ---------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `id`                   | integer                                                    | Stable numeric keyword id — what `keywords update/pause/resume/rm` accept.                                              |
| `keyword`              | string                                                     | The phrase being tracked.                                                                                               |
| `context`              | string \| null                                             | Disambiguation sentence used by AI relevance scoring. Auto-generated from the company profile when omitted at creation. |
| `additionalTerms`      | string \| null                                             | Comma-separated terms required alongside the main keyword. `null` when none.                                            |
| `additionalTermsAndOr` | boolean                                                    | How `additionalTerms` combine: `true` = OR (any one), `false` = AND (all).                                              |
| `caseSensitive`        | boolean                                                    | Whether matching is case-sensitive.                                                                                     |
| `symbolSensitive`      | boolean                                                    | Exact-match mode: `true` requires multi-word keywords to appear together.                                               |
| `platforms`            | string\[]                                                  | Platform slugs this keyword is monitored on (`reddit`, `twitter`, …).                                                   |
| `excludeWords`         | string \| null                                             | Comma-separated exact-match exclusions. `null` when none.                                                               |
| `wildcardExcludeWords` | string \| null                                             | Comma-separated wildcard exclusion patterns (`*` supported). `null` when none.                                          |
| `excludeAuthors`       | string \| null                                             | Comma-separated author handles whose posts are filtered out. `null` when none.                                          |
| `tag`                  | enum: `own_brand`, `competitor`, `industry_term` — or null | Keyword classification. `null` for legacy keywords without a tag.                                                       |
| `paused`               | boolean                                                    | When `true`, data collection is paused for this keyword.                                                                |
| `isSubReddit`          | boolean \| null                                            | `true` when the keyword is a subreddit to monitor rather than a phrase. `null` for non-Reddit keywords.                 |

Without `--json`: A terminal prints a confirmation line and the keyword's definition after the update.

<Accordion title="Example output">
  ```json theme={null}
  {
    "id": 42,
    "keyword": "acme corp",
    "context": "Acme is a cloud storage company, not the cartoon.",
    "additionalTerms": null,
    "additionalTermsAndOr": true,
    "caseSensitive": false,
    "symbolSensitive": true,
    "platforms": [
      "reddit",
      "twitter",
      "hackernews"
    ],
    "excludeWords": "jobs,hiring",
    "wildcardExcludeWords": null,
    "excludeAuthors": null,
    "tag": "own_brand",
    "paused": false,
    "isSubReddit": null
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens suggestions accept`

Accept a keyword suggestion (applies it to the keyword)

**Arguments**

| Argument | Type      | Required | Description                             |
| -------- | --------- | -------- | --------------------------------------- |
| `ID`     | `integer` | required | Suggestion id (from `suggestions list`) |

**Flags**

| Flag      | Type     | Required (headless) | Description                                     |
| --------- | -------- | ------------------- | ----------------------------------------------- |
| `--value` | `string` | no                  | Override the suggested value before applying it |

**Examples**

```bash theme={null}
octolens suggestions accept 123
octolens suggestions accept 123 --value 'jobs, hiring' --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/keywords/suggestions`.

| Field            | Type    | Description                                                                                                                            |
| ---------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `ok`             | boolean | Always `true` — a failed accept answers the error envelope instead.                                                                    |
| `suggestionId`   | integer | The accepted suggestion.                                                                                                               |
| `success`        | boolean | Always `true` (the v2 response's own success flag).                                                                                    |
| `appliedChanges` | object  | Map of keyword fields that changed to their new values (e.g. `{"excludeWords": "spam,scam"}`). Shape depends on the suggestion `type`. |

Without `--json`: A terminal prints one confirmation line naming the applied changes.

Example output:

```json theme={null}
{
  "ok": true,
  "suggestionId": 7,
  "success": true,
  "appliedChanges": {
    "excludeWords": "jobs,hiring,acme jobs"
  }
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens suggestions list`

List AI keyword-tuning suggestions (org-wide or per keyword)

**Flags**

| Flag        | Type      | Required (headless) | Description                                        |
| ----------- | --------- | ------------------- | -------------------------------------------------- |
| `--all`     | `boolean` | no                  | Drain every page (mutually exclusive with --limit) |
| `--keyword` | `string`  | no                  | Narrow to one keyword (id or name)                 |
| `--limit`   | `integer` | no                  | Return the first N suggestions (across pages)      |

**Examples**

```bash theme={null}
octolens suggestions list
octolens suggestions list --keyword 'acme corp'
octolens suggestions list --all --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `GET /api/v2/keywords/suggestions`.

| Field                                         | Type                                                                                                                                           | Description                                                                                                       |
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `data`                                        | object\[]                                                                                                                                      | Pending AI keyword-tuning suggestions, highest impact first.                                                      |
| `data[].id`                                   | integer                                                                                                                                        | Suggestion id — what `suggestions accept/reject` take.                                                            |
| `data[].keywordId`                            | integer                                                                                                                                        | Keyword the suggestion targets.                                                                                   |
| `data[].keyword`                              | string                                                                                                                                         | Keyword text.                                                                                                     |
| `data[].keywordVolume`                        | integer                                                                                                                                        | Mention volume on this keyword over the recent window.                                                            |
| `data[].type`                                 | enum: `add_exclude_words`, `add_exclude_authors`, `add_additional_terms`, `change_additional_terms_logic`, `set_exact_match`, `disable_source` | What kind of keyword-config change the AI proposes.                                                               |
| `data[].value`                                | string                                                                                                                                         | The proposed value; shape depends on `type` (comma-separated terms, a platform slug, `true`/`false`, `and`/`or`). |
| `data[].reason`                               | string \| null                                                                                                                                 | AI-written justification shown to the user.                                                                       |
| `data[].impact`                               | string \| null                                                                                                                                 | AI-written estimated impact, free-form prose.                                                                     |
| `data[].impactScore`                          | number                                                                                                                                         | Numeric impact score (0–1) used to sort suggestions.                                                              |
| `data[].keywordSettings`                      | object                                                                                                                                         | Snapshot of the keyword's current config, for a diff preview.                                                     |
| `data[].keywordSettings.excludeWords`         | string \| null                                                                                                                                 | Current comma-separated exclude words on the keyword.                                                             |
| `data[].keywordSettings.excludeAuthors`       | string \| null                                                                                                                                 | Current comma-separated excluded authors.                                                                         |
| `data[].keywordSettings.additionalTerms`      | string \| null                                                                                                                                 | Current comma-separated additional terms.                                                                         |
| `data[].keywordSettings.additionalTermsAndOr` | boolean                                                                                                                                        | Current AND/OR combinator for additional terms.                                                                   |
| `data[].keywordSettings.platforms`            | string \| null                                                                                                                                 | Current comma-separated platforms list.                                                                           |
| `data[].keywordSettings.symbolSensitive`      | boolean                                                                                                                                        | Current "exact match" mode.                                                                                       |
| `pagination.nextCursor`                       | string \| null                                                                                                                                 | Opaque resume cursor. `null` when the listing is complete.                                                        |
| `totalSuggestionCount`                        | integer                                                                                                                                        | Total pending suggestions across all keywords (the full snapshot, not just this page).                            |

Without `--json`: A terminal renders each suggestion with its reason and impact; piped stdout emits one tab-delimited record per suggestion.

<Accordion title="Example output">
  ```json theme={null}
  {
    "data": [
      {
        "id": 7,
        "keywordId": 42,
        "keyword": "acme corp",
        "keywordVolume": 312,
        "type": "add_exclude_words",
        "value": "acme jobs,acme hiring",
        "reason": "31% of recent matches are job postings, not product mentions.",
        "impact": "Reduces noise by ~15%.",
        "impactScore": 0.82,
        "keywordSettings": {
          "excludeWords": "jobs,hiring",
          "excludeAuthors": null,
          "additionalTerms": null,
          "additionalTermsAndOr": true,
          "platforms": "reddit,twitter,hackernews",
          "symbolSensitive": true
        }
      }
    ],
    "pagination": {
      "nextCursor": null
    },
    "totalSuggestionCount": 1
  }
  ```
</Accordion>

With `--keyword`, stdout carries a keyword-scoped document instead — the resolved keyword's pending suggestions without the org-wide enrichment (no `keyword` text, `keywordVolume`, `impactScore` or per-row `keywordSettings`) and no `totalSuggestionCount`.

| Field                          | Type                                                                                                                                           | Description                                                                                                       |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `data`                         | object\[]                                                                                                                                      | The keyword's pending suggestions, newest first.                                                                  |
| `data[].id`                    | integer                                                                                                                                        | Suggestion id — what `suggestions accept/reject` take.                                                            |
| `data[].keywordId`             | integer                                                                                                                                        | Keyword the suggestion targets (the one `--keyword` resolved to).                                                 |
| `data[].organizationId`        | string                                                                                                                                         | Owning organization id.                                                                                           |
| `data[].type`                  | enum: `add_exclude_words`, `add_exclude_authors`, `add_additional_terms`, `change_additional_terms_logic`, `set_exact_match`, `disable_source` | What kind of keyword-config change the AI proposes.                                                               |
| `data[].value`                 | string                                                                                                                                         | The proposed value; shape depends on `type` (comma-separated terms, a platform slug, `true`/`false`, `and`/`or`). |
| `data[].reason`                | string \| null                                                                                                                                 | AI-written justification shown to the user.                                                                       |
| `data[].impact`                | string \| null                                                                                                                                 | AI-written estimated impact, free-form prose.                                                                     |
| `data[].status`                | enum: `pending`                                                                                                                                | Always `pending` — the listing carries only actionable suggestions.                                               |
| `data[].createdAt`             | string                                                                                                                                         | ISO 8601 datetime the suggestion was generated.                                                                   |
| `data[].respondedAt`           | string \| null                                                                                                                                 | Always `null` while `status` is `pending`.                                                                        |
| `pagination.nextCursor`        | null                                                                                                                                           | Always `null` — the bundle is returned whole; `--limit` heads it client-side.                                     |
| `keyword`                      | object                                                                                                                                         | Snapshot of the keyword's current settings, for a diff preview.                                                   |
| `keyword.excludeWords`         | string \| null                                                                                                                                 | Current comma-separated exclude words on the keyword.                                                             |
| `keyword.excludeAuthors`       | string \| null                                                                                                                                 | Current comma-separated excluded authors.                                                                         |
| `keyword.additionalTerms`      | string \| null                                                                                                                                 | Current comma-separated additional terms.                                                                         |
| `keyword.additionalTermsAndOr` | boolean                                                                                                                                        | Current AND/OR combinator for additional terms.                                                                   |
| `keyword.platforms`            | string \| null                                                                                                                                 | Current comma-separated platforms list.                                                                           |
| `keyword.symbolSensitive`      | boolean                                                                                                                                        | Current "exact match" mode.                                                                                       |
| `suggestions`                  | object\[]                                                                                                                                      | DEPRECATED alias of `data` (kept for one release) — same rows, same order. Prefer `data`.                         |

<Accordion title="Example output">
  ```json theme={null}
  {
    "data": [
      {
        "id": 7,
        "keywordId": 42,
        "organizationId": "org_2abcDEFGHijkLMNopQRstuVWxyz",
        "type": "add_exclude_words",
        "value": "acme jobs,acme hiring",
        "reason": "31% of recent matches are job postings, not product mentions.",
        "impact": "Reduces noise by ~15%.",
        "status": "pending",
        "createdAt": "2026-07-30T09:15:00.000Z",
        "respondedAt": null
      }
    ],
    "pagination": {
      "nextCursor": null
    },
    "keyword": {
      "excludeWords": "jobs,hiring",
      "excludeAuthors": null,
      "additionalTerms": null,
      "additionalTermsAndOr": true,
      "platforms": "reddit,twitter,hackernews",
      "symbolSensitive": true
    },
    "suggestions": [
      {
        "id": 7,
        "keywordId": 42,
        "organizationId": "org_2abcDEFGHijkLMNopQRstuVWxyz",
        "type": "add_exclude_words",
        "value": "acme jobs,acme hiring",
        "reason": "31% of recent matches are job postings, not product mentions.",
        "impact": "Reduces noise by ~15%.",
        "status": "pending",
        "createdAt": "2026-07-30T09:15:00.000Z",
        "respondedAt": null
      }
    ]
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens suggestions reject`

Reject a suggestion by id, or all for a keyword (--keyword)

**Arguments**

| Argument | Type      | Required | Description                                       |
| -------- | --------- | -------- | ------------------------------------------------- |
| `ID`     | `integer` | optional | Suggestion id to reject (from `suggestions list`) |

**Flags**

| Flag        | Type     | Required (headless) | Description                                                  |
| ----------- | -------- | ------------------- | ------------------------------------------------------------ |
| `--keyword` | `string` | no                  | Reject ALL pending suggestions for this keyword (id or name) |

**Examples**

```bash theme={null}
octolens suggestions reject 123
octolens suggestions reject --keyword 'acme corp' --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `DELETE /api/v2/keywords/suggestions`.

| Field                   | Type       | Description                                                                                            |
| ----------------------- | ---------- | ------------------------------------------------------------------------------------------------------ |
| `ok`                    | boolean    | Always `true` — a failed reject answers the error envelope instead.                                    |
| `suggestionId`          | integer    | The rejected suggestion (single-suggestion form).                                                      |
| `rejectedCount`         | integer    | How many suggestions moved from `pending` to `rejected`. `0` is the affirmative 'nothing was pending'. |
| `rejectedSuggestionIds` | integer\[] | Ids of the suggestions dismissed, ascending. Always present; `[]` when nothing was pending.            |

Rejecting ALL of a keyword's suggestions (`--all --keyword`) reports `keywordId` instead of `suggestionId`; `rejectedCount`/`rejectedSuggestionIds` then name every dismissed row.

Without `--json`: A terminal prints one confirmation line naming what was dismissed.

Example output:

```json theme={null}
{
  "ok": true,
  "suggestionId": 7,
  "rejectedCount": 1,
  "rejectedSuggestionIds": [
    7
  ]
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).
