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

# Tracked competitors over time

> Daily or weekly series for the brand and each tracked competitor: visibility, share of voice, mentions, position, sentiment, win rate and citations of their own website, over the brand's tracked prompts. Read from precomputed daily rows, so it is cheap at any window length. A competitor tracked recently may have `history_from` null until its backfill completes.



## OpenAPI

````yaml /openapi.json get /v1/brands/{id}/competitors/trends
openapi: 3.1.0
info:
  title: Geoptie API
  version: 1.0.0
  summary: Read and manage your AI-search visibility data.
  description: >-
    Everything the Geoptie dashboard can do, over HTTP.


    **Authentication.** Every request needs an API key as `Authorization: Bearer
    <key>`, and the workspace must have an active or trialing subscription. Keys
    are created in the dashboard and scoped to one workspace.


    **Pagination** is cursor-based. Pass `next_cursor` back as `cursor` and stop
    when `has_more` is false. The cursor is opaque; do not parse it.


    **Dates** are ISO 8601. `from` is inclusive, `to` is exclusive. Omitting
    both gives the last 30 days.


    **Limits** exist to stop runaway clients, not to meter you: there is no
    monthly request ceiling. Every response carries `X-RateLimit-*`, and
    endpoints that spend money carry `X-Endpoint-*` as well. A 429 names which
    limit was hit.


    **Errors** always carry a stable `error.code`. Match on that, never on the
    message text. A verb that an endpoint does not declare returns 405
    `method_not_allowed`.
  contact:
    name: Geoptie support
    email: support@geoptie.com
servers:
  - url: https://api.geoptie.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Brands
    description: The brands you track. A brand owns its prompts, engines and country.
  - name: Prompts
    description: >-
      The questions you track across engines, the answers they returned, and the
      brands named in those answers. Plan limits apply to how many you can
      track.
  - name: Visibility
    description: How often and how prominently a brand appears in engine answers.
  - name: Citations
    description: Which pages engines cited when answering your prompts.
  - name: Competitors
    description: >-
      Your share of voice against the other brands appearing in your prompts,
      the tracked set that share of voice is computed over, and per-competitor
      trends.
  - name: Topics
    description: Optional grouping for prompts within a brand.
  - name: Recommendations
    description: Generated actions for improving visibility, and their lifecycle.
  - name: Audit reports
    description: On-demand GEO analysis of a single URL.
  - name: Content generations
    description: >-
      New articles, written from the pages engines already cite for the prompts
      you track. Research a brief first, then write the article from it.
  - name: Content optimizations
    description: >-
      Pages you already have, scored for AI search with the specific changes
      that would raise the score.
paths:
  /v1/brands/{id}/competitors/trends:
    get:
      tags:
        - Competitors
      summary: Tracked competitors over time
      description: >-
        Daily or weekly series for the brand and each tracked competitor:
        visibility, share of voice, mentions, position, sentiment, win rate and
        citations of their own website, over the brand's tracked prompts. Read
        from precomputed daily rows, so it is cheap at any window length. A
        competitor tracked recently may have `history_from` null until its
        backfill completes.
      operationId: getCompetitorTrends
      parameters:
        - name: id
          in: path
          required: true
          description: Brand id.
          schema:
            type: string
            format: uuid
          example: b7c1e5a0-4f3d-42a8-9c6b-1e8d5a2f7043
        - name: engine
          in: query
          required: false
          description: Restrict to one engine. Omit for the all-engine rollup.
          schema:
            $ref: '#/components/schemas/Engine'
          example: chatgpt
        - name: from
          in: query
          required: false
          description: Inclusive start date. Defaults to 30 days before `to`.
          schema:
            type: string
            format: date
          example: '2026-08-01'
        - name: to
          in: query
          required: false
          description: Exclusive end date. Defaults to tomorrow.
          schema:
            type: string
            format: date
          example: '2026-09-01'
        - name: granularity
          in: query
          required: false
          description: Bucket size.
          schema:
            type: string
            enum:
              - day
              - week
            default: day
          example: day
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/CompetitorTrend'
        '400':
          $ref: '#/components/responses/E400'
        '401':
          $ref: '#/components/responses/E401'
        '402':
          $ref: '#/components/responses/E402'
        '403':
          $ref: '#/components/responses/E403'
        '404':
          $ref: '#/components/responses/E404'
        '429':
          $ref: '#/components/responses/E429'
        '500':
          $ref: '#/components/responses/E500'
components:
  schemas:
    Engine:
      type: string
      description: Stable public engine identifier. Internal model names are never exposed.
      enum:
        - chatgpt
        - claude
        - perplexity
        - gemini
        - google_ai_overviews
        - google_ai_mode
        - copilot
    CompetitorTrend:
      type: object
      properties:
        granularity:
          type: string
          enum:
            - day
            - week
        from:
          type: string
          format: date
        to:
          type: string
          format: date
        engine:
          type:
            - string
            - 'null'
        brand:
          $ref: '#/components/schemas/CompetitorTrendEntity'
        competitors:
          type: array
          items:
            $ref: '#/components/schemas/CompetitorTrendEntity'
    CompetitorTrendEntity:
      type: object
      properties:
        id:
          type:
            - string
            - 'null'
          format: uuid
          description: Tracked competitor id; null for the brand itself.
        brand_name:
          type: string
        is_your_brand:
          type: boolean
        domains:
          type: array
          items:
            type: string
        history_from:
          type:
            - string
            - 'null'
          format: date
          description: >-
            Earliest date with complete history. Null while the backfill that
            follows tracking a competitor is still running.
        totals:
          $ref: '#/components/schemas/CompetitorTrendMetrics'
        series:
          type: array
          items:
            $ref: '#/components/schemas/CompetitorTrendPoint'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable machine code. Match on this, not the message.
            message:
              type: string
    CompetitorTrendMetrics:
      type: object
      description: >-
        Derived from precomputed daily counts. The brand's answered responses
        are the denominator for visibility and detection; own plus tracked
        mentions are the denominator for share of voice.
      properties:
        responses_answered:
          type: integer
        responses_with_brand:
          type: integer
        mention_count:
          type: integer
        citation_count:
          type: integer
          description: Citations of this brand's own website in the same answers.
        detection_rate:
          type: number
          description: '0-100: share of answers that mention the brand.'
        visibility_score:
          type: number
          description: '0-100: detection weighted by position and top-3 share.'
        avg_position:
          type:
            - number
            - 'null'
        avg_sentiment:
          type:
            - number
            - 'null'
        top3_visibility:
          type:
            - number
            - 'null'
        win_rate:
          type: number
          description: '0-100: share of answers where the brand is named first.'
        share_of_voice:
          type: number
          description: 0-100, over the brand plus its tracked competitors.
    CompetitorTrendPoint:
      allOf:
        - $ref: '#/components/schemas/CompetitorTrendMetrics'
        - type: object
          properties:
            date:
              type: string
              format: date
              description: 'Bucket start: the day, or the Monday of the week.'
  responses:
    E400:
      description: >-
        Bad request. `missing_parameter`, `invalid_request`, `invalid_engine` or
        `invalid_date`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E401:
      description: '`missing_api_key` or `invalid_api_key`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E402:
      description: >-
        `subscription_required`. The workspace has no active or trialing
        subscription.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E403:
      description: '`plan_not_eligible` or `forbidden`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E404:
      description: '`not_found`. Also returned for records belonging to another workspace.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E429:
      description: >-
        `rate_limited`, `quota_exceeded`, `endpoint_rate_limited` or
        `concurrency_limited`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E500:
      description: '`internal_error`. Quote the `X-Request-Id` when reporting it.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Your API key, e.g. `Authorization: Bearer gp_live_...`.'

````

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