> ## 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.

# List source classification rule changes

> The project's rule change log, newest first: who changed which rule, through which door (`channel`: `app`, `rest`, `mcp`, or `system` for automatic removals), from what to what, and the counts its preview showed. `rootDomain` narrows it to one domain's rules. A `limit` outside 1 to 200 returns 400 `invalid_argument`. Needs only the `read` scope.



## OpenAPI

````yaml /api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/rules/history
openapi: 3.1.0
info:
  title: Searchable REST API
  version: 1.0.0
  summary: >-
    Query AI visibility, sources, sentiment, traffic, and content data, and
    trigger audits/reports/sitemap syncs.
  description: >-
    The Searchable REST API (`/api/mcp/*` and
    `/api/v1/projects/{projectId}/audits`) exposes the same data and actions
    available in the Searchable dashboard and MCP server, over plain HTTP with a
    bearer API key. It is a **read-mostly** surface — 75 of its 91 operations
    are GET. The mutating ones are capability-gated (a bare `write` scope does
    not satisfy a capability such as `prompt:draft`), and those listed under
    [Idempotency](/api-reference/introduction#idempotency) support
    `Idempotency-Key` replay.


    See **[Getting started](/api-reference/introduction)** for auth, rate
    limits, idempotency, and pagination conventions, and the **[error
    reference](/api/errors)** for every error `code` this API returns.


    `/api/mcp/*` is a frozen v1 contract — see the [changelog](/changelog) for
    the deprecation policy.
  contact:
    name: Searchable Support
    email: support@searchable.com
    url: https://docs.searchable.com/api-reference/introduction
servers:
  - url: https://app.searchable.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Projects
    description: List and inspect the projects an API key can reach.
  - name: Visibility
    description: >-
      AI visibility score, platform/topic/prompt/location breakdowns, and
      historical trend.
  - name: Share of Voice
    description: Brand vs. competitor mention-share ranking and its daily trend.
  - name: Competitors
    description: >-
      The project's tracked competitor roster — share of voice, sentiment, and
      mention/citation counts.
  - name: Sources
    description: >-
      Domains and URLs cited by AI answers — citation share, trend, and cached
      page content.
  - name: Sentiment
    description: Brand sentiment summary, trend, and head-to-head competitor comparison.
  - name: Query Fanout
    description: The sub-queries AI models generate when answering tracked prompts.
  - name: Traffic
    description: >-
      First-party AI-crawler and AI-referral traffic sourced from the
      tracker/CDN pipeline.
  - name: Shopping
    description: AI shopping/product-carousel visibility.
  - name: Ads
    description: >-
      Sponsored ads surfaced in AI answers — advertisers, individual creatives,
      ad-heavy prompts, and the frequency trend.
  - name: Answers
    description: Raw, per-response AI-answer data for a single prompt.
  - name: GSC
    description: Live Google Search Console performance data for the project's linked site.
  - name: GA4
    description: Live Google Analytics 4 traffic and AI-referral data.
  - name: Audits & Issues
    description: >-
      Page audits (technical + AEO), site issues, monitored pages, and sitemap
      sync.
  - name: Reports
    description: Generate and list shareable visibility/sentiment reports.
  - name: Articles
    description: Content pieces (articles) created in Searchable.
  - name: Opportunities
    description: >-
      Actionable, prioritized suggestions Searchable has surfaced for the
      project.
  - name: Brand
    description: Brand profile (knowledge base + AI-observed facts) and domain authority.
  - name: Prompts
    description: >-
      The project's prompt catalog (tracked, untracked, and AI-suggested
      prompts).
paths:
  /api/mcp/projects/{projectId}/sources/rules/history:
    get:
      tags:
        - Sources
      summary: List source classification rule changes
      description: >-
        The project's rule change log, newest first: who changed which rule,
        through which door (`channel`: `app`, `rest`, `mcp`, or `system` for
        automatic removals), from what to what, and the counts its preview
        showed. `rootDomain` narrows it to one domain's rules. A `limit` outside
        1 to 200 returns 400 `invalid_argument`. Needs only the `read` scope.
      operationId: listSourceClassificationRuleChanges
      parameters:
        - $ref: '#/components/parameters/projectId'
        - $ref: '#/components/parameters/ruleRootDomain'
        - $ref: '#/components/parameters/ruleChangesLimit'
      responses:
        '200':
          description: The change log.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SourceClassificationRuleHistoryResponse'
        '400':
          $ref: '#/components/responses/defaultError'
        '401':
          $ref: '#/components/responses/defaultError'
        '403':
          $ref: '#/components/responses/defaultError'
        '404':
          $ref: '#/components/responses/defaultError'
        '429':
          $ref: '#/components/responses/rateLimited'
        '504':
          $ref: '#/components/responses/defaultError'
components:
  parameters:
    projectId:
      name: projectId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The project id.
    ruleRootDomain:
      name: rootDomain
      in: query
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 253
      description: Only the changes to this domain's rules (e.g. `linkedin.com`).
    ruleChangesLimit:
      name: limit
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 200
        default: 50
      description: How many changes to return, newest first.
  headers:
    XRequestId:
      description: This request's id. Include it when contacting support.
      schema:
        type: string
        format: uuid
    RateLimit:
      description: >-
        IETF draft rate-limit header:
        `"default";r=<remaining>;t=<seconds-until-reset>`. Omitted on responses
        where the limiter did not run (e.g. a pre-auth validation error, or a
        degraded limiter failing open).
      schema:
        type: string
    RateLimitPolicy:
      description: >-
        IETF draft rate-limit policy: `"default";q=<quota>;w=<window-seconds>`.
        Currently `q=600;w=60`.
      schema:
        type: string
    XRateLimitLimit:
      description: Requests allowed per window (600/minute per key).
      schema:
        type: integer
    XRateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
    XRateLimitReset:
      description: Absolute Unix-epoch second the current window resets.
      schema:
        type: integer
    RetryAfter:
      description: >-
        Seconds to wait before retrying. Set on 429s issued by Searchable's own
        rate limiter and on `409 idempotency_in_flight`; may be absent when an
        upstream provider (e.g. Google) rate-limits.
      schema:
        type: integer
  schemas:
    SourceClassificationRuleHistoryResponse:
      type: object
      properties:
        changes:
          type: array
          items:
            $ref: '#/components/schemas/SourceClassificationRuleChangeView'
        success:
          type: boolean
          description: >-
            Always `true` — injected on every success response by this endpoint
            family's response wrapper.
      required:
        - changes
        - success
    SourceClassificationRuleChangeView:
      type: object
      properties:
        id:
          type: string
        ruleId:
          type:
            - string
            - 'null'
        action:
          type: string
          enum:
            - create
            - update
            - delete
        before:
          anyOf:
            - $ref: '#/components/schemas/SourceClassificationRuleSnapshot'
            - type: 'null'
        after:
          anyOf:
            - $ref: '#/components/schemas/SourceClassificationRuleSnapshot'
            - type: 'null'
        channel:
          type: string
          enum:
            - app
            - rest
            - mcp
            - system
        actor:
          anyOf:
            - $ref: '#/components/schemas/SourceClassificationPerson'
            - type: 'null'
        impact:
          anyOf:
            - $ref: '#/components/schemas/SourceClassificationImpact'
            - type: 'null'
          description: >-
            The counts the preview showed; null for a remove-all's rows and
            automatic changes.
        reason:
          anyOf:
            - type: string
              enum:
                - deleted
                - demoted
                - converted_to_brand
            - type: 'null'
          description: Why a competitor's rule was removed automatically; null otherwise.
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - ruleId
        - action
        - before
        - after
        - channel
        - actor
        - impact
        - reason
        - createdAt
    Problem:
      type: object
      description: >-
        RFC 9457 `application/problem+json` error body. `error` is retained
        verbatim as a legacy compat key equal to `message`. Some codes carry
        additional fields beyond the base shape (documented per-code in the
        [error reference](/api/errors)) — always additive, never replacing
        these.
      properties:
        type:
          type: string
          format: uri
          description: >-
            A URL identifying the error kind — the error reference page,
            anchored to `code`.
        title:
          type: string
          description: Human-readable summary of `code`.
        status:
          type: integer
          description: The HTTP status code (matches the response status).
        code:
          type: string
          description: >-
            Machine-readable, stable error code — safe to branch on. See the
            [error reference](/api/errors) for the full catalog.
          enum:
            - unauthorized
            - forbidden
            - missing_scope
            - plan_upgrade_required
            - security_policy_denied
            - not_found
            - invalid_argument
            - invalid_country
            - no_domain
            - no_workspace
            - no_pages
            - bulk_limit_exceeded
            - quota_exceeded
            - project_not_runnable
            - pitch_not_supported
            - rate_limited
            - idempotency_in_flight
            - idempotency_conflict
            - query_timeout
            - gsc_not_connected
            - gsc_site_not_linked
            - gsc_access_denied
            - ga4_not_connected
            - traffic_not_connected
            - invalid_scope
            - host_outside_domain
            - invalid_citation_type
            - missing_competitor
            - unknown_competitor
            - duplicate_scope
            - rule_limit
            - internal_error
        error:
          type: string
          description: Legacy compat key. Always equal to `message`.
        message:
          type: string
          description: Human-readable error message (identical to `error`).
        howToFix:
          type: string
          description: Present on actionable errors — a concrete next step.
        requestId:
          type: string
          format: uuid
          description: This request's id. Include it when contacting support.
        requiresUpgrade:
          type: boolean
          description: Present on `plan_upgrade_required` (403).
        retryable:
          type: boolean
          description: >-
            Present on `rate_limited`, `idempotency_in_flight`, and
            `query_timeout`.
        timeout:
          type: boolean
          description: Present on `query_timeout` (504).
        quotaExceeded:
          type: boolean
          description: Present on `quota_exceeded` (403).
        current:
          type: integer
          description: Present on `quota_exceeded` — current usage.
        limit:
          type: integer
          description: Present on `quota_exceeded` — the plan's limit.
        bulkLimitExceeded:
          type: boolean
          description: Present on `bulk_limit_exceeded` (400, `POST /audits`).
        requested:
          type: integer
          description: >-
            Present on `bulk_limit_exceeded` / `quota_exceeded` — the count
            requested.
        maxAllowed:
          type: integer
          description: Present on `bulk_limit_exceeded` — the plan's per-request cap.
        details:
          description: >-
            Present on some `invalid_argument` (400) responses — a Zod
            `.flatten()` validation breakdown.
          type: object
          properties:
            formErrors:
              type: array
              items:
                type: string
            fieldErrors:
              type: object
              additionalProperties:
                type: array
                items:
                  type: string
      required:
        - type
        - title
        - status
        - code
        - error
        - message
    SourceClassificationRuleSnapshot:
      type: object
      description: >-
        A rule as one change log row recorded it, with its competitor's current
        name.
      properties:
        id:
          type: string
        scope:
          type: string
          description: The rule's scope as people read it, like `linkedin.com/help`.
        rootDomain:
          type: string
        host:
          type:
            - string
            - 'null'
          description: >-
            The subdomain the rule covers; null for every host under
            `rootDomain`.
        pathPrefix:
          type:
            - string
            - 'null'
          description: The path the rule covers; null for every path.
        citationType:
          $ref: '#/components/schemas/SourceClassificationType'
        competitorId:
          type:
            - string
            - 'null'
        competitorName:
          type:
            - string
            - 'null'
      required:
        - id
        - scope
        - rootDomain
        - host
        - pathPrefix
        - citationType
        - competitorId
        - competitorName
    SourceClassificationPerson:
      type: object
      description: A person named in the rules or their log.
      properties:
        id:
          type: string
        name:
          type:
            - string
            - 'null'
      required:
        - id
        - name
    SourceClassificationImpact:
      type: object
      description: What a rule change does to the citations already stored.
      properties:
        rowsChanged:
          type: integer
          description: Stored citations whose Source Type (or competitor) would change.
        answersChanged:
          type: integer
          description: AI answers those citations belong to.
        transitions:
          type: array
          description: The moves from type to type, most citations first.
          items:
            type: object
            properties:
              from:
                $ref: '#/components/schemas/SourceClassificationType'
              to:
                $ref: '#/components/schemas/SourceClassificationType'
              rows:
                type: integer
            required:
              - from
              - to
              - rows
      required:
        - rowsChanged
        - answersChanged
        - transitions
    SourceClassificationType:
      type: string
      enum:
        - brand
        - competitor
        - editorial
        - social
        - forum
        - review
        - institutional
        - third_party
        - other
      description: A Source Type. `brand` is the app's Owned.
  responses:
    defaultError:
      description: >-
        Error response. `code` is the machine-readable reason — see the [error
        reference](/api/errors) for the full catalog and remediation per code.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    rateLimited:
      description: >-
        Rate limited. Usually the per-API-key REST limit (600 requests/minute);
        on Google-backed endpoints it can also relay an upstream Google rate
        limit. `Retry-After` (seconds) is present when the limit was applied by
        Searchable's own rate limiter; it may be absent when an upstream
        provider rate-limits.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: sea_xxxxx
      description: >-
        A Searchable API key, created under **Manage Account → Integrations →
        API Keys**. Send as `Authorization: Bearer sea_xxxxx`. Every key carries
        one or more scopes (`read`, `write`, `admin`) and may optionally be
        bound to a single project — see [Getting
        started](/api-reference/introduction#authentication).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.