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

# Changelog

> Updates to the Searchable REST API and MCP server

<Update label="August 2026" description="Bot-category and named-bot crawl breakdowns" tags={["API", "MCP"]}>
  ## Follow each page from training crawl to assistant fetch

  The existing AI Traffic reports now expose the bot identity Searchable already resolves internally.
  Pass `groupBy=botCategory` or `groupBy=botName` on REST
  `/traffic/overview`, `/traffic/bots`, or `/traffic/correlation`, or use the same `groupBy` argument on
  the consolidated `get_ai_traffic` MCP tool. No new MCP tool was added, and omitting `groupBy` keeps
  existing response shapes unchanged.

  The public categories are `ai_training`, `ai_search`, `ai_assistant`, `ai_agent`, and
  `search_engine`. In particular, `ai_assistant` distinguishes user-triggered fetches such as
  ChatGPT-User, Claude-User, and Perplexity-User from training and retrieval crawlers. Correlation also
  supports `groupBy=platform`. Every correlation grouping describes crawl requests; it does not
  attribute an AI-referred session to a crawler.
</Update>

<Update label="August 2026" description="Charts render only when you ask for them" tags={["MCP"]}>
  ## `render` — decide per call whether a chart is drawn

  Nine MCP tools ship an interactive card (`get_visibility`, `get_share_of_voice`, `get_competitors`,
  `get_sentiment`, `get_topic_analysis`, `get_source_trends`, `get_shopping_visibility`,
  `get_site_health`, `list_prompts`). Until now a host drew that card beside **every** answer those
  tools gave, including the many calls that only fetch numbers to summarise or feed into another
  request.

  Those nine tools now take an optional `render` boolean:

  ```
  get_visibility(projectId, render: true)    // draws the chart card
  get_visibility(projectId, render: false)   // data only, no card
  get_visibility(projectId)                  // draws the card, as before
  ```

  `true` when the result is meant to be looked at; `false` when you only need the numbers. State it on
  every call — but **omitting it is safe and always draws the card**, so nothing that worked before
  this release behaves differently.

  <Note>
    Backwards compatible by design. Clients that pin a tool schema — the ChatGPT plugin directory
    publishes a snapshot taken at scan time — keep calling without `render` and keep getting their
    cards, unchanged. No REST endpoint is affected; this applies to MCP tool calls only.
  </Note>
</Update>

<Update label="August 2026" description="investigate — one call that answers a whole diagnostic question" tags={["API", "MCP"]}>
  ## Ask a question, not five queries

  `investigate` runs a whole diagnostic chain **server-side and in parallel**, returning the
  measurements together instead of requiring five or six requests you then have to join. Available as
  an MCP tool and as `GET /api/mcp/projects/{projectId}/investigate`.

  | `question`                  | What it returns                                                                                                                                                  |
  | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `visibility_drop` (default) | Score trend with the largest single-day fall, per-platform movement vs the previous window, share-of-voice shift with the competitors who gained, weakest topics |
  | `competitive_position`      | Your share and rank with period movement, the competitor table, and the topics where a rival currently leads                                                     |
  | `citation_gap`              | Your citation trend, the domains AI answers actually cite in your space, and per-engine citation share                                                           |

  It takes the same narrowing arguments as the individual reads — `days` or `from`/`to`, `platform`,
  `topicId`, `unbranded` / `branded`, `country` / `locationId`.

  **It reports measurements, never a cause.** It will tell you ChatGPT fell 38 points while Gemini
  held; it will not tell you why, because the reason is usually outside the data — a rebrand, a
  campaign ending, a competitor launch. Every response carries an `interpretation` list naming what
  the numbers cannot settle, and a signal whose upstream failed appears in `unavailable` with a
  reason rather than as a zero, so missing data is never mistaken for a finding.

  **Recipes.** Each question has a companion guide covering how to read the result, the interpretation
  rules, and what the data cannot tell you: [why did our AI visibility
  drop](/recipes/visibility-drop), [where do we stand against
  competitors](/recipes/competitive-position), [why aren't we being cited](/recipes/citation-gap).
  Load one in-chat with `read_doc("recipes/visibility-drop")`.

  **Slash commands.** The same three playbooks are also exposed as MCP **prompts** — the first prompts
  this server offers — so clients that render them (Claude Desktop and similar) get
  `visibility-drop`, `competitive-position`, and `citation-gap` as user-invocable commands.
</Update>

<Update label="August 2026" description="Absolute date ranges, five new traffic reports, and new views on the existing families" tags={["API", "MCP"]}>
  Everything here is **additive** — no existing call changes shape, and every capability lands on
  both the MCP tools and the matching REST endpoints, which share one implementation.

  **Absolute date ranges (`from` / `to`).** Previously only Search Console accepted explicit dates;
  everything else spoke in relative `days`, so "compare March against June" or "the week of the
  launch" could not be expressed. Every windowed read now takes `from` and `to` (inclusive, UTC,
  `YYYY-MM-DD` or full ISO): `get_visibility` (all views), `get_share_of_voice`, `get_sentiment`,
  `get_topic_analysis`, `get_ai_traffic`, and their REST twins. Both bounds are required together and
  are mutually exclusive with `days` — sending both returns `400 invalid_argument` rather than
  silently picking one. An over-long `days` is still clamped; an over-long explicit range is
  **rejected**, because narrowing a range you spelled out would answer a different question.

  **Five new AI Traffic reports** on `get_ai_traffic` (and as REST endpoints under
  `/traffic/*`):

  | Report             | Answers                                                                          |
  | ------------------ | -------------------------------------------------------------------------------- |
  | `sitemap_coverage` | Per bot: sitemap fetch cadence, pages discovered, publish-to-crawl lag           |
  | `human`            | Human sessions that arrived from an AI assistant, split by platform              |
  | `correlation`      | Per page, crawls versus the AI-referred sessions that followed                   |
  | `attribution`      | Traffic by UTM tuple, referrer, and bot category                                 |
  | `logs`             | The raw request feed — filter by path, status, bots-only, host; cursor-paginated |

  `logs` is row-capped (25 default, 100 max) and **never returns `ip_address` or `user_agent`**: the
  IP is personal data with no analytical value once `country` is present, and the user-agent is
  superseded by the resolved bot identity. A new `host` parameter narrows any traffic report to
  specific hostnames on multi-domain projects.

  **New views on the existing families.**

  * `get_share_of_voice` gains `group_by="date"` — the daily brand-versus-competitor share series, for "is our share growing".
  * `get_topic_analysis` gains `view="prompts"` (per-prompt rank inside one topic, with the competitors outranking you — requires `topicId`) and `view="heatmap"` (average brand position per topic x AI platform). Both are also REST endpoints: `/topics/prompt-rankings` and `/topics/heatmap`.
  * `get_visibility` gains `include="industry_ranking"` — the competitive leaderboard attached to the summary.
  * Date-series views gain `include="annotations"`: the dated markers (campaign launches, migrations) overlapping the window, so a spike arrives with its explanation.

  **Filters.** `list_prompts` (and `GET /prompts`) accept `search` for a case-insensitive substring
  match on prompt text — `%` and `_` match literally rather than as wildcards. `topicId` accepts a
  comma-separated list on the surfaces whose queries take several (`get_visibility`,
  `get_share_of_voice`, `get_sentiment`, `get_topic_analysis`, `get_competitors`,
  `get_shopping_visibility`); single-topic surfaces (`list_prompts`, `get_query_fanout`, `get_ads`)
  document and accept one id rather than advertising a list they would reject. `list_projects` returns
  `dataAvailableFrom` per project — the earliest date with a **completed, scored** visibility report —
  so a client can size its windows instead of discovering the horizon through empty results.

  **Reading the new reports honestly.** Three contracts are worth knowing before you parse them:

  * `report="human"` carries a `summarySource`. Site-wide totals come from the first-party tracker
    while the AI figures fall back to GA4 when no tracker is installed; in that split state every
    `summary` field and `percentOfTotal` are `null` rather than `0`, and a failed GA4 read arrives as
    `aiReferral.sourceError` instead of as zeroes.
  * `report="correlation"` joins crawls and AI-referred sessions over the **same window** by path.
    That is co-occurrence, not attribution — nothing establishes that a session followed a crawl. Its
    `pagesConsidered` is a floor on the page count, with `populationTruncated` flagging when the
    upstream per-set cap means pages are missing.
  * `include="industry_ranking"` returns the top 25 entities, not the whole field: `hasMore` flags a
    longer leaderboard, `brandRankStatus` separates "ranks below the cutoff" from "unranked", and
    `totalEntities` is `null` when truncated.

  Arguments a view cannot apply are now `invalid_argument` errors rather than silent no-ops — an
  `include` on a view that attaches no blocks, `topicId` on the all-topics view, `platform` on the
  topic x platform heatmap, an explicit range longer than `group_by=prompt`'s 180-day ceiling, and
  half a log cursor. Impossible calendar dates (`2026-02-30`) are rejected instead of rolling into the
  next month, and markdown headings name an explicit range instead of relabelling it "last N days".
  `logs`, `sitemap_coverage`, and `attribution` require a crawler-log source and return
  `traffic_not_connected` for analytics-only projects, rather than an empty `200` that reads as "no
  crawler traffic".
</Update>

<Update label="August 2026" description="MCP family-grid consolidation — fewer tools, same answers" tags={["MCP"]}>
  **Four reads folded into their family's primary tool.** The visibility trend, the two sentiment side-views, and domain authority are now selector parameters instead of standalone tools:

  | Old tool                    | New call                                            |
  | --------------------------- | --------------------------------------------------- |
  | `get_visibility_history`    | `get_visibility` (`group_by: "date"`)               |
  | `get_sentiment_history`     | `get_sentiment` (`view: "history"`)                 |
  | `get_sentiment_competitors` | `get_sentiment` (`view: "competitors"`)             |
  | `get_domain_authority`      | `get_brand_profile` (`include: "domain_authority"`) |

  **The old names still work.** All four stay registered as deprecated stubs with byte-identical payloads, so existing scripts and scheduled jobs are unaffected today. They are scheduled for removal **after 2026-10-15** — the same \~60-day window the removed aliases got. An unsupported combination on the new views (for example `compare` on `view=history`, or a `platform` filter on `group_by=date`) returns `invalid_argument` instead of being silently ignored.

  **REST is untouched.** `GET /visibility/history`, `GET /sentiment/history`, `GET /sentiment/competitors`, and `GET /domain-authority` are not deprecated and follow the standard [12-month policy](/changelog#deprecation-policy) as before.

  **Leaner tool descriptions.** Tool descriptions across the server were tightened (\~18% smaller) with no behavioral facts removed — every MCP client loads the full tool list into model context each conversation, so this directly cuts per-conversation overhead.
</Update>

<Update label="August 2026" description="Period comparison, CSV export, per-URL rollup, MCP utility & docs tools" tags={["API", "MCP"]}>
  **Period comparison in one call.** `GET /visibility`, `GET /visibility/topics`, `GET /share-of-voice`, and `GET /sentiment` (and the matching MCP tools `get_visibility`, `get_share_of_voice`, `get_sentiment`) accept `compare=previous_period` or `compare=previous_year`. The response gains an additive `comparison` block — the previous window's metrics plus current-minus-previous deltas — so "how did we do vs last month?" no longer needs two calls and client-side math. On `/visibility/topics`, per-topic deltas ride inline on each topic row. On `/share-of-voice`, every competitor row gains `previousSov`/`sovDelta`.

  **Per-URL metrics rollup.** New `GET /projects/{projectId}/pages/metrics?url=…` (and the `get_page_metrics` MCP tool): one page's three AI series joined in a single call — citations of the URL in AI answers, AI-referral sessions landing on it (by platform), and AI-crawler hits fetching it (by bot), each as daily buckets. Traffic series degrade to `available: false` when the LLM Analytics integration isn't connected; citations always answer.

  **CSV export + bigger pages.** The five biggest list endpoints — cited domains, cited URLs, prompts, issues, opportunities — accept `?format=csv` (RFC 4180, BOM-prefixed, spreadsheet-formula-hardened). Page-size caps rose for bulk pulls: cited domains/URLs and prompts to **1,000** rows per page, opportunities to 1,000; values above a cap clamp instead of erroring.

  **Consistent pagination everywhere.** `GET /issues`, `GET /opportunities`, and `GET /competitors` now return the full standard offset block (`hasMore` + `nextOffset` included) — the derive-it-yourself caveats are gone from the docs because they're gone from the API.

  **New MCP orientation tools.** `get_current_date` (UTC anchor + pre-computed 7/30/90/365-day window starts, so assistants never do date arithmetic), `whoami` (who this connection is, its read/write scopes, and its visible project roster), and `search_docs` / `read_doc` (full-text search + retrieval over this documentation, served from the app's embedded corpus — assistants can answer "how is the visibility score calculated?" in-chat). Plus two MCP **resources**: `searchable://glossary` and `searchable://glossary/full` — metric and concept definitions with the tools that read each one.
</Update>

<Update label="July 2026" description="New: responseMentionRate — one mention metric across endpoints" tags={["API"]}>
  **`responseMentionRate` is the mention metric to use.** It is the percentage (0-100) of AI responses that mention your brand, and it means **the same thing on every endpoint** — added to both `GET /visibility` (`summary.responseMentionRate`) and `GET /visibility/history` (per data point). `GET /visibility/history` data points also now return `responsesWithBrand`, so the rate is auditable from the payload alone.

  **Why:** `mentionRate` does not mean the same thing on both endpoints, and never has.

  * On `GET /visibility` it is a **share** of responses — bounded 0-100.
  * On `GET /visibility/history` it is a **density**: brand mentions ÷ responses × 100. Because one response can mention a brand several times, this routinely reads **above 100%** (a real project reads 393%). That is the value it has always returned, not a recent regression.

  `mentionRate` and `overallMentionRate` are therefore **deprecated but unchanged** on `GET /visibility`, `GET /visibility/history`, and `GET /visibility/prompts`. They keep returning exactly what they always have — we do not silently recalculate a shipped field. There is **no removal date**; per the policy below you would get at least 12 months' notice, and this entry starts no clock. If you want the density, it stays derivable as `brandMentions / totalResponses * 100`.

  **Migrating:** replace `mentionRate` with `responseMentionRate` on `/visibility` and `/visibility/history`. On `/visibility/prompts`, `mentionRate` / `overallMentionRate` are exact aliases of `visibilityScore` / `overallVisibilityScore` — same value, so switching is a rename with no data change.

  **Also new: `GET /visibility/platforms`** — per-AI-platform visibility (the platform counterpart to `/visibility/topics` and `/visibility/locations`). `platform` is comma-separated and accepts display names, aliases, and raw model ids.
</Update>

<Update label="July 2026" description="Client MCP & API revamp" tags={["API", "MCP"]}>
  **MCP: sign in instead of pasting a key.** The MCP server now supports an OAuth 2.1 login flow (PKCE + Dynamic Client Registration) — connect Claude, Cursor, or another MCP client by signing in and approving access, scoped to exactly the projects and read/write permissions you choose. The `sea_` API-key bearer path still works unchanged for scripts and headless clients. See [MCP integration](/integrations/mcp).

  **New data coverage**, in REST and as MCP tools:

  * **Share of Voice & Competitors** — brand vs. competitor mention-share ranking, its daily trend, and the full tracked-competitor roster
  * **AI Traffic** — first-party AI-crawler visits and AI-referral sessions, sourced from the tracker/CDN pipeline
  * **Shopping visibility** — AI shopping/product-carousel appearances
  * **Prompt Answers** — raw, per-response AI-answer data (text, mentions, citations) for a single prompt
  * **`GET /reports`** — list previously generated shareable reports for a project

  **Write actions over MCP** — `generate_report`, `trigger_audit`, and `refresh_sitemap` are now callable as MCP tools (in addition to their existing REST POST endpoints), each gated on the `write` scope and an explicit confirmation.

  **Hardened REST responses.** Every response now carries an `X-Request-Id` and standard rate-limit headers (600 requests/minute per API key); errors are RFC 9457 `application/problem+json` with a stable `code` field you can branch on. See the new **[error reference](/api/errors)**. The `POST /reports`, `POST /audits`, and `POST /sitemap/refresh` endpoints additionally accept an `Idempotency-Key` header, so a retry after a timeout or dropped connection never triggers the action twice.

  **Clearer "not connected" errors.** Google Search Console, Google Analytics 4, and AI Traffic endpoints now return an actionable `409` with a direct link to the right settings page when the integration isn't connected yet, instead of a generic failure.

  **This page, and the interactive [API reference](/api-reference/introduction)** — a full OpenAPI 3.1 spec with a live playground for every endpoint, generated straight from the shipped route contracts.
</Update>

## Deprecation policy

* **12 months' notice.** We give at least 12 months' notice before removing or changing the behavior of any documented endpoint, parameter, or response field. Adding a new endpoint or an additive response field is not a breaking change and isn't subject to this notice.
* **`Deprecation` / `Sunset` headers.** Once an endpoint is scheduled for removal, its responses carry a `Deprecation` header (the date it was deprecated) and, once a removal date is fixed, a `Sunset` header (the date it stops working), per the [IETF Sunset header convention](https://www.rfc-editor.org/rfc/rfc8594). Nothing on this API is scheduled for removal today, so no `Sunset` header is in play. The `mentionRate` / `overallMentionRate` response fields are marked deprecated in the API reference (see the July 2026 entry above) — they remain fully supported with no removal date, and are superseded by `responseMentionRate`.
* **Versioning posture.** `/api/mcp/*` — despite the name — is the frozen v1 REST contract: stable, versionless-by-default. New capabilities land as new endpoints or new additive fields, never as a breaking change to an existing one. `/api/v1/*` is reserved for surfaces that need independent versioning from that contract (currently just `/api/v1/projects/{projectId}/audits`, which mirrors `GET /api/mcp/projects/{projectId}/audits` exactly).
* A breaking change, if one is ever required, ships as a new endpoint or a new version prefix, announced here first, with the prior version supported through the full notice window.

Questions about an upcoming change? **[support@searchable.com](mailto:support@searchable.com)**.
