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

# Get Shopping Report

> Shopping-placement metrics grouped by one or more dimensions. This is the report behind the
UI Shopping screen — use it for shopping visibility, direct-link share, product rank and
per-product or per-merchant breakdowns. `/reports/performance` cannot produce these.

**Example:** "Which merchants carry purchase links for my products, by topic?"

**Dimensions** (at least 1 required): `topic`, `tag`, `market`, `model`, `query`, `date`, `website`, `branded`, `product`, `placement_type`, `merchant`
- `product` rows also carry `product_image`, `product_link`, `brand_id` / `brand_name` / `brand_url` / `brand_logo`, `brand_is_self` and `product_source_type` (owned | competitor | third_party | unconfigured); `merchant` rows carry `merchant_url`, `merchant_logo`, `merchant_is_self`
- `date` supports optional `date_aggregation_interval`: `day` (default) | `week` | `month`; buckets on the placement date
- `website` is the brand that owns the product, and auto-sets `website_type` to `SELF+COMPETITORS`; `product` / `merchant` auto-set it to `ALL`, like the dashboard's All Products / Merchants pages (default otherwise is `SELF`)
- `website_type: ALL` also returns untracked third-party brands, with a null `website_id` and an empty `website_name`

**Measures** (omit for all): `shopping_visibility`, `direct_link_share`, `share_of_shopping_voice`, `product_rank`, `answers_with_product`, `product_mentions`, `shopping_answers`, `unique_products`, `unique_merchants`, `buy_link_count`, `buy_link_share`, `avg_price`
- `shopping_visibility` = answers featuring this entity / `shopping_answers` (all answers in the group holding any shopping placement)
- `direct_link_share` = this entity's placements whose purchase link points back at the product's own brand, over its own placements
- `share_of_shopping_voice` = this brand's placements / all tracked brands' placements — placements, not answers, so a brand with three product cards in one answer counts three, as on the dashboard's Share of Voice chart
- `avg_price` also returns `avg_price_currency`

**Filters:** `topics`, `prompts`, `tags`, `markets`, `intent`, `branded`, `platform`, `website_mentioned_in_answer`, `cited_page_url`, `cited_domain`, `website_mentioned_in_citation`, `products`, `brands`, `merchants`, `placement_type`, `source_type`, `price`, `product_rank`, `has_direct_link`.
- `has_shopping_card`, `has_ads_data`, `visibility`, `rank` and `status` are accepted for compatibility with the other report endpoints and ignored here.
- `platform` matches the model that produced the answer (stricter than `/reports/performance`, which matches prompts that ever ran on a platform).

**Sort fields:** Any measure name, plus `date`, `query_name`, `topic_name`, `market_name`, `model_name`, `website_name`, `tag_name`, `product_name`, `merchant_name`, `placement_type`.

**Dates:** If no dates provided, defaults to latest run date range. Provide `start_date` and `end_date` in ISO 8601 format to specify a custom range.

**Comparison:** Provide `comparison_start_date` and `comparison_end_date` (ISO 8601, both required together) to also compute every measure over a past range — each row then gains `previous_<measure>` fields calculated with identical dimensions, measures, and filters. Rows match across periods by dimension; with the `date` dimension, each current bucket matches the comparison bucket exactly (start_date - comparison_start_date) earlier, so use equal-length ranges (and bucket-aligned ones for week/month intervals) — buckets with no counterpart simply omit previous_* values.

**Pagination:** Use `pagination` (`limit` 1-100, default 10; `offset` for paging). Use `order_by` for sorting.

**Response:** Returns `data` array with `info` metadata containing `total_rows` (before pagination) and `query` (applied metrics, dates, sorting, pagination, filters).

**Notes:** Days with no placements are omitted rather than zero-filled. Grouping by `merchant`/`advertiser` fans a placement out to one row per merchant, so column totals can exceed the ungrouped total; within a merchant row each placement still counts once (rank and price are not weighted by how many of its links point at that merchant). `AD_SHOPPING` placements count in both this report and the other one, so shopping and ad totals are not additive.



## OpenAPI

````yaml https://api.writesonic.com/v1/oauth/openapi.json?client_secret=FgwCVph3cjZy0KPsvsuU post /v2/geo/reports/shopping
openapi: 3.1.0
info:
  title: Writesonic Docs
  description: >-
    This is the documentation for Writesonic's API. To be able to test the API,
    please register an account and request an api key at
    [Writesonic](https://writesonic.com). <br/> Please check out the tutorials
    section for more information<br/>   <ul> <li> [Find your API
    key](../docs/Find%20Api%20Key) </li> <li>  [Test an
    endpoint](../docs/Test%20An%20Endpoint)</li>  </ul> <p> Writesonic API has
    been upgraded to V2(beta) version. [Click here to read V2 docs
    (beta)](../api-docs/v2.html) <br/> Note - as all APIs are
    backwards-compatible, old endpoints will not be impacted by this change.
    </p> For any queries write us to at support@writesonic.com  
  contact:
    email: support@writesonic.com
  version: '1.0'
servers:
  - url: https://api.writesonic.com
    description: Production
security: []
tags:
  - name: AI Analytics
  - name: Action Center
  - name: Brand Radar Reports
  - name: Citation Analytics
  - name: Content
  - name: Fact Check
  - name: GEO Presence
  - name: GEO Presence Sentiment
  - name: GEO Presence Shopping
  - name: Generic
  - name: Per-Prompt Analytics
  - name: Project
  - name: Project Configuration
  - name: Prompt Explorer
  - name: Prompts All
  - name: Prompts Overview
  - name: Reports
  - name: Research Page Tracker
  - name: Research Page Tracker Portfolio
  - name: Tags
paths:
  /v2/geo/reports/shopping:
    post:
      tags:
        - Reports
      summary: Get Shopping Report
      description: >-
        Shopping-placement metrics grouped by one or more dimensions. This is
        the report behind the

        UI Shopping screen — use it for shopping visibility, direct-link share,
        product rank and

        per-product or per-merchant breakdowns. `/reports/performance` cannot
        produce these.


        **Example:** "Which merchants carry purchase links for my products, by
        topic?"


        **Dimensions** (at least 1 required): `topic`, `tag`, `market`, `model`,
        `query`, `date`, `website`, `branded`, `product`, `placement_type`,
        `merchant`

        - `product` rows also carry `product_image`, `product_link`, `brand_id`
        / `brand_name` / `brand_url` / `brand_logo`, `brand_is_self` and
        `product_source_type` (owned | competitor | third_party | unconfigured);
        `merchant` rows carry `merchant_url`, `merchant_logo`,
        `merchant_is_self`

        - `date` supports optional `date_aggregation_interval`: `day` (default)
        | `week` | `month`; buckets on the placement date

        - `website` is the brand that owns the product, and auto-sets
        `website_type` to `SELF+COMPETITORS`; `product` / `merchant` auto-set it
        to `ALL`, like the dashboard's All Products / Merchants pages (default
        otherwise is `SELF`)

        - `website_type: ALL` also returns untracked third-party brands, with a
        null `website_id` and an empty `website_name`


        **Measures** (omit for all): `shopping_visibility`, `direct_link_share`,
        `share_of_shopping_voice`, `product_rank`, `answers_with_product`,
        `product_mentions`, `shopping_answers`, `unique_products`,
        `unique_merchants`, `buy_link_count`, `buy_link_share`, `avg_price`

        - `shopping_visibility` = answers featuring this entity /
        `shopping_answers` (all answers in the group holding any shopping
        placement)

        - `direct_link_share` = this entity's placements whose purchase link
        points back at the product's own brand, over its own placements

        - `share_of_shopping_voice` = this brand's placements / all tracked
        brands' placements — placements, not answers, so a brand with three
        product cards in one answer counts three, as on the dashboard's Share of
        Voice chart

        - `avg_price` also returns `avg_price_currency`


        **Filters:** `topics`, `prompts`, `tags`, `markets`, `intent`,
        `branded`, `platform`, `website_mentioned_in_answer`, `cited_page_url`,
        `cited_domain`, `website_mentioned_in_citation`, `products`, `brands`,
        `merchants`, `placement_type`, `source_type`, `price`, `product_rank`,
        `has_direct_link`.

        - `has_shopping_card`, `has_ads_data`, `visibility`, `rank` and `status`
        are accepted for compatibility with the other report endpoints and
        ignored here.

        - `platform` matches the model that produced the answer (stricter than
        `/reports/performance`, which matches prompts that ever ran on a
        platform).


        **Sort fields:** Any measure name, plus `date`, `query_name`,
        `topic_name`, `market_name`, `model_name`, `website_name`, `tag_name`,
        `product_name`, `merchant_name`, `placement_type`.


        **Dates:** If no dates provided, defaults to latest run date range.
        Provide `start_date` and `end_date` in ISO 8601 format to specify a
        custom range.


        **Comparison:** Provide `comparison_start_date` and
        `comparison_end_date` (ISO 8601, both required together) to also compute
        every measure over a past range — each row then gains
        `previous_<measure>` fields calculated with identical dimensions,
        measures, and filters. Rows match across periods by dimension; with the
        `date` dimension, each current bucket matches the comparison bucket
        exactly (start_date - comparison_start_date) earlier, so use
        equal-length ranges (and bucket-aligned ones for week/month intervals) —
        buckets with no counterpart simply omit previous_* values.


        **Pagination:** Use `pagination` (`limit` 1-100, default 10; `offset`
        for paging). Use `order_by` for sorting.


        **Response:** Returns `data` array with `info` metadata containing
        `total_rows` (before pagination) and `query` (applied metrics, dates,
        sorting, pagination, filters).


        **Notes:** Days with no placements are omitted rather than zero-filled.
        Grouping by `merchant`/`advertiser` fans a placement out to one row per
        merchant, so column totals can exceed the ungrouped total; within a
        merchant row each placement still counts once (rank and price are not
        weighted by how many of its links point at that merchant). `AD_SHOPPING`
        placements count in both this report and the other one, so shopping and
        ad totals are not additive.
      operationId: get_shopping_report
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ShoppingReportRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ShoppingReportResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
components:
  schemas:
    ShoppingReportRequest:
      properties:
        project_id:
          type: string
          minLength: 1
          title: Project Id
          description: >-
            Unique identifier of the project to query. Get valid project IDs
            from get_all_projects.
          examples:
            - 550e8400-e29b-41d4-a716-446655440000
        start_date:
          type: string
          format: date-time
          title: Start Date
          description: >-
            Start of the date range (ISO 8601). Limits results to data collected
            on or after this date. When omitted: defaults to the latest run's
            start date for metric queries, or earliest available date for list
            queries.
          examples:
            - '2026-01-01T00:00:00Z'
            - '2026-03-01T00:00:00Z'
        end_date:
          type: string
          format: date-time
          title: End Date
          description: >-
            End of the date range (ISO 8601). Limits results to data collected
            on or before this date. When omitted: defaults to today. Date-only
            strings (no 'T') are extended to end of day.
          examples:
            - '2026-01-31T23:59:59Z'
            - '2026-03-17T23:59:59Z'
        current_from:
          type: string
          format: date-time
          title: Current From
          description: Alias for start_date (analytics-tool date naming).
        current_to:
          type: string
          format: date-time
          title: Current To
          description: Alias for end_date (analytics-tool date naming).
        comparison_start_date:
          type: string
          format: date-time
          title: Comparison Start Date
          description: >-
            Start of the comparison (past) date range (ISO 8601). Provide
            together with comparison_end_date to additionally compute every
            measure over this past range — each row then includes
            previous_<measure> values calculated with identical dimensions,
            measures, and filters.
          examples:
            - '2026-07-25T00:00:00Z'
        comparison_end_date:
          type: string
          format: date-time
          title: Comparison End Date
          description: >-
            End of the comparison (past) date range (ISO 8601). Required
            together with comparison_start_date. Date-only strings (no 'T') are
            extended to end of day, same as end_date.
          examples:
            - '2026-07-31T23:59:59Z'
        previous_from:
          type: string
          format: date-time
          title: Previous From
          description: Alias for comparison_start_date (analytics-tool date naming).
        previous_to:
          type: string
          format: date-time
          title: Previous To
          description: Alias for comparison_end_date (analytics-tool date naming).
        order_by:
          items:
            $ref: '#/components/schemas/SortingOrder'
          type: array
          title: Order By
          description: >-
            Sort results by one or more fields. Each entry specifies a field
            name and direction. Results are sorted by the first entry, then ties
            broken by subsequent entries.
          examples:
            - - field: visibility_score
                order: desc
            - - field: mention_count
                order: desc
              - field: rank
                order: asc
        pagination:
          $ref: '#/components/schemas/PaginationInput'
          description: >-
            Control result pagination. Set `limit` for page size and `offset` to
            skip results. Omit to return all results (use with caution on large
            datasets).
          examples:
            - limit: 10
              offset: 0
            - limit: 25
              offset: 50
        dimensions:
          items:
            $ref: '#/components/schemas/Dimension'
          type: array
          minItems: 1
          title: Dimensions
          description: >-
            Dimensions to group shopping data by. At least one dimension is
            required.
          examples:
            - - website
            - - product
              - date
            - - topic
              - merchant
        measures:
          items:
            $ref: '#/components/schemas/ShoppingMeasure'
          type: array
          title: Measures
          description: Shopping metrics to include. If empty, all measures are returned.
          examples:
            - - shopping_visibility
              - direct_link_share
        filters:
          $ref: '#/components/schemas/ShoppingFiltersInput'
          description: >-
            Narrow results by topics, markets, products, merchants, price, etc.
            All filters combine with AND logic.
        date_aggregation_interval:
          $ref: '#/components/schemas/DateAggregationInterval'
          description: >-
            Optional. When using the 'date' dimension, controls time-series
            bucket size. Defaults to 'day'.
          examples:
            - week
            - month
        website_type:
          $ref: >-
            #/components/schemas/writesonic_backend__schemas__geo_presence__multi_dimension_reports__WebsiteType
          description: >-
            Scope results by brand ownership. 'SELF' = your brand's products
            only, 'SELF+COMPETITORS' = plus competitors, 'ALL' = including
            untracked third-party brands.
          examples:
            - SELF+COMPETITORS
      additionalProperties: false
      type: object
      required:
        - project_id
        - dimensions
      title: ShoppingReportRequest
      description: Request parameters for the Shopping Report API.
    ShoppingReportResponse:
      properties:
        info:
          $ref: '#/components/schemas/ResponseInfo'
          description: >-
            Information of the API request including total count and query
            details
        data:
          items:
            $ref: '#/components/schemas/ShoppingDataRow'
          type: array
          title: Data
          description: Array of shopping data rows grouped by the requested dimensions
      type: object
      title: ShoppingReportResponse
      description: Response containing shopping report data.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    SortingOrder:
      properties:
        field:
          type: string
          title: Field
          description: >-
            Field name to sort by. Must match a measure or dimension name from
            the response (e.g., 'visibility_score', 'mention_count',
            'topic_name').
          examples:
            - visibility_score
            - mention_count
            - rank
        order:
          $ref: '#/components/schemas/SortOrderType'
          description: 'Sort direction: ''asc'' (lowest first) or ''desc'' (highest first).'
          examples:
            - desc
      additionalProperties: false
      type: object
      required:
        - field
        - order
      title: SortingOrder
      description: >-
        Sort results by a specific field. Use with `order_by` to control result
        ordering — e.g., sort by visibility score descending to see top
        performers first.
    PaginationInput:
      properties:
        limit:
          type: integer
          maximum: 100
          minimum: 1
          title: Limit
          description: >-
            Number of items per page (1-100). Use smaller values for faster
            responses.
          default: 10
          examples:
            - 10
            - 25
            - 50
        offset:
          type: integer
          minimum: 0
          title: Offset
          description: >-
            Number of items to skip. Set to `limit * page_number` for page-based
            navigation.
          default: 0
          examples:
            - 0
            - 10
            - 50
      additionalProperties: false
      type: object
      title: PaginationInput
      description: >-
        Control how many results are returned and which page to fetch. Use
        `limit` to set page size and `offset` to skip already-seen results.
    Dimension:
      type: string
      enum:
        - topic
        - tag
        - market
        - model
        - query
        - date
        - website
        - shopping
        - ads
        - branded
        - persona
        - intent_stage
        - locality
        - search_intent
        - domain
        - page
        - source_type
        - theme
        - subtheme
        - keyword
        - product
        - merchant
        - advertiser
        - placement_type
      title: Dimension
      description: >-
        Dimensions to group report data by. Each report accepts a subset;
        unsupported dimensions are rejected with 400.


        - `topic`: Group by topic/category

        - `tag`: Group by tag

        - `market`: Group by market/region

        - `model`: Group by AI model (e.g. ChatGPT, Perplexity)

        - `query`: Group by individual query/prompt

        - `date`: Group by date (requires date_aggregation_interval)

        - `website`: Group by tracked website

        - `shopping`: Group by whether the response has a shopping card
        (true/false)

        - `ads`: Group by whether the response has sponsored/ad placements
        (true/false)

        - `branded`: Group by whether the underlying query is branded
        (true/false)

        - `persona`: Group by the persona prompt target attached to the query

        - `intent_stage`: Group by the intent-stage prompt target attached to
        the query

        - `locality`: Group by the locality prompt target attached to the query

        - `search_intent`: Group by the query's dominant search intent
        (transactional, navigational, informational, commercial)

        - `domain`: Group by cited domain (citations report only)

        - `page`: Group by cited page URL (citations report only)

        - `source_type`: Group by cited source type: owned, competitor,
        social_forums, third_party (citations report only)

        - `theme`: Group by sentiment theme (sentiments report only)

        - `subtheme`: Group by sentiment subtheme (sentiments report only)

        - `keyword`: Group by sentiment keyword (sentiments report only)

        - `product`: Group by shopping product / ad creative (shopping and ads
        reports only)

        - `merchant`: Group by the merchant offering a purchase link (shopping
        report only)

        - `advertiser`: Group by the advertiser that placed the ad (ads report
        only)

        - `placement_type`: Group by placement type (e.g. SHOPPING_CARD,
        AD_TEXT)
      x-enumDescriptions:
        ads: Group by whether the response has sponsored/ad placements (true/false)
        advertiser: Group by the advertiser that placed the ad (ads report only)
        branded: Group by whether the underlying query is branded (true/false)
        date: Group by date (requires date_aggregation_interval)
        domain: Group by cited domain (citations report only)
        intent_stage: Group by the intent-stage prompt target attached to the query
        keyword: Group by sentiment keyword (sentiments report only)
        locality: Group by the locality prompt target attached to the query
        market: Group by market/region
        merchant: Group by the merchant offering a purchase link (shopping report only)
        model: Group by AI model (e.g. ChatGPT, Perplexity)
        page: Group by cited page URL (citations report only)
        persona: Group by the persona prompt target attached to the query
        placement_type: Group by placement type (e.g. SHOPPING_CARD, AD_TEXT)
        product: >-
          Group by shopping product / ad creative (shopping and ads reports
          only)
        query: Group by individual query/prompt
        search_intent: >-
          Group by the query's dominant search intent (transactional,
          navigational, informational, commercial)
        shopping: Group by whether the response has a shopping card (true/false)
        source_type: >-
          Group by cited source type: owned, competitor, social_forums,
          third_party (citations report only)
        subtheme: Group by sentiment subtheme (sentiments report only)
        tag: Group by tag
        theme: Group by sentiment theme (sentiments report only)
        topic: Group by topic/category
        website: Group by tracked website
    ShoppingMeasure:
      type: string
      enum:
        - shopping_visibility
        - direct_link_share
        - share_of_shopping_voice
        - product_rank
        - answers_with_product
        - product_mentions
        - shopping_answers
        - unique_products
        - unique_merchants
        - buy_link_count
        - buy_link_share
        - avg_price
      title: ShoppingMeasure
      description: >-
        Shopping metrics to include in the report.


        - `shopping_visibility`: Percentage of shopping answers featuring this
        entity's product (0-100)

        - `direct_link_share`: Percentage of this entity's placements carrying a
        purchase link to its own site (0-100)

        - `share_of_shopping_voice`: This entity's placements as a percentage of
        all tracked-brand placements in the group (0-100)

        - `product_rank`: Average position of the product within the shopping
        card (lower is better)

        - `answers_with_product`: Number of distinct answers featuring this
        entity's product

        - `product_mentions`: Total number of product placements

        - `unique_products`: Number of distinct products placed

        - `unique_merchants`: Number of distinct merchants offering a purchase
        link

        - `buy_link_count`: Number of purchase links attributed to this entity

        - `buy_link_share`: Purchase links attributed to this entity as a
        percentage of the group total (0-100)

        - `shopping_answers`: Total answers in the group containing any shopping
        placement (the shopping_visibility denominator)

        - `avg_price`: Average quoted price across purchase links; also returns
        avg_price_currency
      x-enumDescriptions:
        answers_with_product: Number of distinct answers featuring this entity's product
        avg_price: >-
          Average quoted price across purchase links; also returns
          avg_price_currency
        buy_link_count: Number of purchase links attributed to this entity
        buy_link_share: >-
          Purchase links attributed to this entity as a percentage of the group
          total (0-100)
        direct_link_share: >-
          Percentage of this entity's placements carrying a purchase link to its
          own site (0-100)
        product_mentions: Total number of product placements
        product_rank: >-
          Average position of the product within the shopping card (lower is
          better)
        share_of_shopping_voice: >-
          This entity's placements as a percentage of all tracked-brand
          placements in the group (0-100)
        shopping_answers: >-
          Total answers in the group containing any shopping placement (the
          shopping_visibility denominator)
        shopping_visibility: Percentage of shopping answers featuring this entity's product (0-100)
        unique_merchants: Number of distinct merchants offering a purchase link
        unique_products: Number of distinct products placed
    ShoppingFiltersInput:
      properties:
        topics:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by topic ID or topic name.
          examples:
            - condition: OR
              items:
                - operator: is
                  value: 550e8400-e29b-41d4-a716-446655440000
                - operator: contains
                  value: SEO
        prompts:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by prompt ID or query text. Use 'contains' for partial text
            matching.
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: best AI tools
        tags:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by tag ID or tag name. 'is' checks tag association, 'is_not'
            excludes.
          examples:
            - condition: OR
              items:
                - operator: is
                  value: 550e8400-e29b-41d4-a716-446655440000
        markets:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by market ID or region name (e.g., 'United States').
          examples:
            - condition: OR
              items:
                - operator: is
                  value: United States
                - operator: is
                  value: United Kingdom
        intent:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by search intent: 'transactional', 'navigational',
            'informational', 'commercial'.
          examples:
            - condition: OR
              items:
                - operator: is
                  value: informational
                - operator: is
                  value: commercial
        branded:
          $ref: '#/components/schemas/BooleanFilterGroup'
          description: true = branded queries only, false = non-branded only.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: false
        platform:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by AI platform name (e.g., 'ChatGPT', 'Perplexity',
            'Gemini'). Use 'contains' for partial matches.
          examples:
            - condition: OR
              items:
                - operator: is
                  value: ChatGPT
                - operator: is
                  value: Perplexity
        has_shopping_card:
          $ref: '#/components/schemas/BooleanFilterGroup'
          description: true = only responses with shopping cards.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: true
        has_ads_data:
          $ref: '#/components/schemas/BooleanFilterGroup'
          description: true = only responses that include sponsored / ad placements.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: true
        visibility:
          $ref: '#/components/schemas/NumericFilterGroup'
          description: >-
            Keep only answers where your brand's mention has this visibility
            score (0-100).
          examples:
            - condition: AND
              items:
                - operator: gte
                  value: 50
        rank:
          $ref: '#/components/schemas/NumericFilterGroup'
          description: >-
            Keep only answers where your brand is mentioned at this rank
            position (1-99, lower is better).
          examples:
            - condition: AND
              items:
                - operator: lte
                  value: 3
        volume:
          $ref: '#/components/schemas/NumericFilterGroup'
          description: >-
            Filter by prompt monthly search volume. Prompts without a known
            volume never match.
          examples:
            - condition: AND
              items:
                - operator: gte
                  value: 1000
        website_mentioned_in_answer:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by a tracked website (your brand or a competitor) mentioned
            in the AI response body: website ID or domain. 'contains' matches a
            substring of the domain. A value that matches no tracked website
            selects nothing.
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: writesonic.com
        cited_page_url:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by cited page URL. Use 'contains' for partial matching.
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: /blog/
        cited_domain:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by cited domain name (e.g., 'writesonic.com').
          examples:
            - condition: AND
              items:
                - operator: is
                  value: writesonic.com
        website_mentioned_in_citation:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by a tracked website whose pages are cited: website ID or
            domain. 'contains' matches a substring of the domain. A value that
            matches no tracked website selects nothing.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: 550e8400-e29b-41d4-a716-446655440000
        advanced_filters:
          $ref: '#/components/schemas/ReportFilterTree'
          description: >-
            Arbitrary AND/OR tree across any filter fields. When set, it takes
            precedence over the flat per-field filters above and is the only way
            to express cross-field OR, e.g. (topic is SEO) OR (platform is
            Grok).
          examples:
            - conditions:
                - field: topics
                  operator: is
                  value: <topic-id>
                - field: platform
                  operator: is
                  value: Grok
              join: or
        status:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by query status (e.g. 'ACTIVE', 'PAUSED').
          examples:
            - condition: AND
              items:
                - operator: is
                  value: ACTIVE
        products:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by product / ad-creative ID or title.
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: running shoe
        brands:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by the website ID, name or URL of the brand that owns the
            product.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: Nike
        placement_type:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by placement type (e.g. 'SHOPPING_CARD', 'AD_TEXT').
          examples:
            - condition: AND
              items:
                - operator: is
                  value: SHOPPING_CARD
        source_type:
          $ref: '#/components/schemas/StringFilterGroup'
          description: >-
            Filter by brand ownership: 'owned', 'competitor', 'third_party',
            'unconfigured'.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: owned
        price:
          $ref: '#/components/schemas/NumericFilterGroup'
          description: Filter by quoted price on a purchase link.
          examples:
            - condition: AND
              items:
                - operator: lte
                  value: 100
        product_rank:
          $ref: '#/components/schemas/NumericFilterGroup'
          description: >-
            Filter by the placement's position within the answer (lower is
            better).
          examples:
            - condition: AND
              items:
                - operator: lte
                  value: 3
        merchants:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by merchant website ID, name or URL (e.g. 'amazon').
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: amazon
        has_direct_link:
          $ref: '#/components/schemas/BooleanFilterGroup'
          description: >-
            true = only placements carrying a purchase link to the product's own
            brand.
          examples:
            - condition: AND
              items:
                - operator: is
                  value: true
      additionalProperties: false
      type: object
      title: ShoppingFiltersInput
      description: >-
        Filters for the Shopping Report. All filters are optional — omit to
        include all data.


        Common filters (`topics`, `prompts`, `tags`, `markets`, `intent`,
        `branded`, `platform`,

        `website_mentioned_in_answer`, `cited_page_url`, `cited_domain`,

        `website_mentioned_in_citation`) apply as on every report, plus:

        - `products` — Filter by product ID or product title.

        - `brands` — Filter by the website ID, name or URL of the brand that
        owns the product.

        - `merchants` — Filter by merchant website ID, name or URL.

        - `placement_type` — 'SHOPPING_CARD', 'SHOPPING', 'AD_SHOPPING',
        'SERP_SHOPPING'.

        - `source_type` — 'owned', 'competitor', 'third_party', 'unconfigured'.

        - `price` — Numeric: quoted price on a purchase link.

        - `product_rank` — Numeric: the product's position within the shopping
        card.

        - `has_direct_link` — Boolean: only placements carrying a purchase link
        to the product's own brand.


        Accepted for compatibility with the other report endpoints but
        **ignored** here:

        `has_shopping_card`, `has_ads_data`, `visibility`, `rank`
        (answer-mention grain — use

        `product_rank` for placement rank), `status`.
    DateAggregationInterval:
      type: string
      enum:
        - day
        - week
        - month
      title: DateAggregationInterval
      description: |-
        Time interval for aggregating date-dimension data.

        - `day`: Daily aggregation
        - `week`: Weekly aggregation
        - `month`: Monthly aggregation
      x-enumDescriptions:
        day: Daily aggregation
        month: Monthly aggregation
        week: Weekly aggregation
    writesonic_backend__schemas__geo_presence__multi_dimension_reports__WebsiteType:
      type: string
      enum:
        - SELF
        - SELF+COMPETITORS
        - ALL
      title: WebsiteType
      description: |-
        Filter results by website ownership type.

        - `SELF`: Your brand's tracked domains only
        - `SELF+COMPETITORS`: Your brand plus competitor tracked domains
        - `ALL`: All citations with no domain filtering applied
      x-enumDescriptions:
        ALL: All citations with no domain filtering applied
        SELF: Your brand's tracked domains only
        SELF+COMPETITORS: Your brand plus competitor tracked domains
    ResponseInfo:
      properties:
        total_rows:
          type: integer
          title: Total Rows
          description: Total number of rows matching the query (before pagination)
        query:
          $ref: >-
            #/components/schemas/writesonic_backend__schemas__geo_presence__business_base__QueryInfo
          description: Details of the query that produced this response
      type: object
      required:
        - total_rows
        - query
      title: ResponseInfo
      description: Metadata about the API response.
    ShoppingDataRow:
      properties:
        topic_id:
          type: string
          title: Topic Id
          description: Unique identifier of the topic
        topic_name:
          type: string
          title: Topic Name
          description: Display name of the topic
        tag_id:
          type: string
          title: Tag Id
          description: Unique identifier of the tag
        tag_name:
          type: string
          title: Tag Name
          description: Display name of the tag
        market_id:
          type: string
          title: Market Id
          description: Unique identifier of the market/region
        market_name:
          type: string
          title: Market Name
          description: Display name of the market
        model_id:
          type: string
          title: Model Id
          description: Unique identifier of the AI model
        model_name:
          type: string
          title: Model Name
          description: Display name of the AI model
        query_id:
          type: string
          title: Query Id
          description: Unique identifier of the query/prompt
        query_name:
          type: string
          title: Query Name
          description: The actual query text
        date:
          type: string
          title: Date
          description: Date bucket for time-series data (ISO format)
        website_id:
          type: string
          title: Website Id
          description: >-
            Unique identifier of the brand that owns the product; null for
            untracked third-party brands
        website_name:
          type: string
          title: Website Name
          description: >-
            Display name of the owning brand; empty string for untracked
            third-party brands
        branded:
          type: boolean
          title: Branded
          description: >-
            When grouping by `branded`: true = branded queries, false =
            non-branded
        product_id:
          type: string
          title: Product Id
          description: Unique identifier of the product / ad creative
        product_name:
          type: string
          title: Product Name
          description: Title of the product / ad creative
        product_image:
          type: string
          title: Product Image
          description: Primary product image URL (when grouping by `product`)
        product_link:
          type: string
          title: Product Link
          description: Product page URL (when grouping by `product`)
        brand_id:
          type: string
          title: Brand Id
          description: Website id the product belongs to (when grouping by `product`)
        brand_name:
          type: string
          title: Brand Name
          description: Brand website name
        brand_url:
          type: string
          title: Brand Url
          description: Brand website URL
        brand_logo:
          type: string
          title: Brand Logo
          description: Brand website logo URL
        brand_is_self:
          type: boolean
          title: Brand Is Self
          description: True when the product belongs to your own brand
        product_source_type:
          type: string
          title: Product Source Type
          description: >-
            owned | competitor | third_party | unconfigured, by the product's
            brand website
        placement_type:
          type: string
          title: Placement Type
          description: Placement type (e.g. 'SHOPPING_CARD', 'AD_TEXT', 'AD_SHOPPING')
        merchant_id:
          type: string
          title: Merchant Id
          description: Unique identifier of the merchant
        merchant_name:
          type: string
          title: Merchant Name
          description: Display name of the merchant
        merchant_url:
          type: string
          title: Merchant Url
          description: Merchant website URL
        merchant_logo:
          type: string
          title: Merchant Logo
          description: Merchant logo URL
        merchant_is_self:
          type: boolean
          title: Merchant Is Self
          description: True when the merchant is your own website
        shopping_visibility:
          type: number
          title: Shopping Visibility
          description: >-
            Percentage of shopping answers featuring this entity's product
            (0-100)
        direct_link_share:
          type: number
          title: Direct Link Share
          description: >-
            Percentage of this entity's placements carrying a purchase link to
            its own site (0-100)
        share_of_shopping_voice:
          type: number
          title: Share Of Shopping Voice
          description: >-
            This entity's placements as a percentage of all tracked-brand
            placements in the group (0-100)
        product_rank:
          type: number
          title: Product Rank
          description: >-
            Average position of the product within the shopping card (lower is
            better)
        answers_with_product:
          type: integer
          title: Answers With Product
          description: Number of distinct answers featuring this entity's product
        product_mentions:
          type: integer
          title: Product Mentions
          description: Total number of product placements
        shopping_answers:
          type: integer
          title: Shopping Answers
          description: Total answers in the group containing any shopping placement
        unique_products:
          type: integer
          title: Unique Products
          description: Number of distinct products placed
        unique_merchants:
          type: integer
          title: Unique Merchants
          description: Number of distinct merchants offering a purchase link
        buy_link_count:
          type: integer
          title: Buy Link Count
          description: Number of purchase links attributed to this entity
        buy_link_share:
          type: number
          title: Buy Link Share
          description: >-
            Purchase links attributed to this entity as a percentage of the
            group total (0-100)
        avg_price:
          type: number
          title: Avg Price
          description: Average quoted price across purchase links
        avg_price_currency:
          type: string
          title: Avg Price Currency
          description: Currency of avg_price (e.g. 'USD')
        previous_shopping_visibility:
          type: number
          title: Previous Shopping Visibility
          description: >-
            shopping_visibility over the comparison date range (present only
            when a comparison range was requested)
        previous_direct_link_share:
          type: number
          title: Previous Direct Link Share
          description: direct_link_share over the comparison date range
        previous_share_of_shopping_voice:
          type: number
          title: Previous Share Of Shopping Voice
          description: share_of_shopping_voice over the comparison date range
        previous_product_rank:
          type: number
          title: Previous Product Rank
          description: product_rank over the comparison date range
        previous_answers_with_product:
          type: integer
          title: Previous Answers With Product
          description: answers_with_product over the comparison date range
        previous_product_mentions:
          type: integer
          title: Previous Product Mentions
          description: product_mentions over the comparison date range
        previous_shopping_answers:
          type: integer
          title: Previous Shopping Answers
          description: shopping_answers over the comparison date range
        previous_unique_products:
          type: integer
          title: Previous Unique Products
          description: unique_products over the comparison date range
        previous_unique_merchants:
          type: integer
          title: Previous Unique Merchants
          description: unique_merchants over the comparison date range
        previous_buy_link_count:
          type: integer
          title: Previous Buy Link Count
          description: buy_link_count over the comparison date range
        previous_buy_link_share:
          type: number
          title: Previous Buy Link Share
          description: buy_link_share over the comparison date range
        previous_avg_price:
          type: number
          title: Previous Avg Price
          description: avg_price over the comparison date range
      type: object
      title: ShoppingDataRow
      description: A single row of shopping report data.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    SortOrderType:
      type: string
      enum:
        - asc
        - desc
      title: SortOrderType
      description: |-
        Sort direction for ordering results.

        - `asc`: Ascending order (lowest first, A-Z, oldest first)
        - `desc`: Descending order (highest first, Z-A, newest first)
      x-enumDescriptions:
        asc: Ascending order (lowest first, A-Z, oldest first)
        desc: Descending order (highest first, Z-A, newest first)
    StringFilterGroup:
      properties:
        condition:
          $ref: '#/components/schemas/FilterConditionType'
          description: >-
            'AND' (all conditions must match, default) or 'OR' (any condition
            can match).
          default: AND
          examples:
            - OR
        items:
          items:
            $ref: '#/components/schemas/StringFilterCondition'
          type: array
          title: Items
          description: List of filter conditions to apply.
          examples:
            - - operator: is
                value: 550e8400-e29b-41d4-a716-446655440000
              - operator: contains
                value: SEO
      additionalProperties: false
      type: object
      title: StringFilterGroup
      description: >-
        A group of text filter conditions. Use `condition` to control how
        multiple items combine:

        AND (default) = all must match, OR = any can match. Each item uses
        operators like 'is', 'contains', etc.
    BooleanFilterGroup:
      properties:
        condition:
          $ref: '#/components/schemas/FilterConditionType'
          description: >-
            'AND' (all conditions must match, default) or 'OR' (any condition
            can match).
          default: AND
          examples:
            - AND
        items:
          items:
            $ref: '#/components/schemas/BooleanFilterCondition'
          type: array
          title: Items
          description: List of boolean filter conditions to apply.
          examples:
            - - operator: is
                value: true
      additionalProperties: false
      type: object
      title: BooleanFilterGroup
      description: >-
        A group of boolean (true/false) filter conditions. Use `condition` to
        control how

        multiple items combine: AND (default) = all must match, OR = any can
        match.
    NumericFilterGroup:
      properties:
        condition:
          $ref: '#/components/schemas/FilterConditionType'
          description: >-
            'AND' (all conditions must match, default) or 'OR' (any condition
            can match).
          default: AND
          examples:
            - AND
        items:
          items:
            $ref: '#/components/schemas/NumericFilterCondition'
          type: array
          title: Items
          description: List of numeric filter conditions to apply.
          examples:
            - - operator: gte
                value: 50
      additionalProperties: false
      type: object
      title: NumericFilterGroup
      description: >-
        A group of numeric filter conditions for range-based filtering (e.g.,
        visibility >= 50).

        Use `condition` to control how multiple items combine: AND (default) =
        all must match, OR = any can match.
    ReportFilterTree:
      properties:
        join:
          type: string
          enum:
            - and
            - or
          title: Join
          description: '''and'' = all children must match, ''or'' = any child.'
          default: and
        conditions:
          items:
            oneOf:
              - $ref: '#/components/schemas/ReportFilterTree'
              - $ref: '#/components/schemas/ReportFilterLeaf'
          type: array
          title: Conditions
          description: >-
            Child nodes: nested trees or leaf conditions. Empty = no advanced
            filter.
      additionalProperties: false
      type: object
      title: ReportFilterTree
      description: |-
        Recursive AND/OR tree combining any report filter fields.

        Unlike the flat per-field filters (which are always AND-joined across
        fields), this expresses arbitrary boolean logic, e.g.
        `(topic is SEO) OR (platform is Grok)`.
    writesonic_backend__schemas__geo_presence__business_base__QueryInfo:
      properties:
        metrics:
          items:
            type: string
          type: array
          title: Metrics
          description: Metrics that were requested
        start_date:
          type: string
          format: date-time
          title: Start Date
          description: Start date used in the query
        end_date:
          type: string
          format: date-time
          title: End Date
          description: End date used in the query
        comparison_start_date:
          type: string
          format: date-time
          title: Comparison Start Date
          description: Start date of the comparison range, if requested
        comparison_end_date:
          type: string
          format: date-time
          title: Comparison End Date
          description: End date of the comparison range, if requested
        order_by:
          additionalProperties:
            type: string
          type: object
          title: Order By
          description: Sorting applied to the results
        pagination:
          additionalProperties:
            type: integer
          type: object
          title: Pagination
          description: Pagination parameters used
        filters:
          additionalProperties: false
          type: object
          title: Filters
          description: Filters that were applied
      type: object
      required:
        - metrics
        - start_date
        - end_date
        - order_by
        - pagination
        - filters
      title: QueryInfo
      description: Information about the query that produced the response.
    FilterConditionType:
      type: string
      enum:
        - AND
        - OR
      title: FilterConditionType
      description: >-
        Logical operator for combining multiple filter conditions within a
        group.


        - `AND`: All conditions must match (intersection)

        - `OR`: Any condition can match (union)
      x-enumDescriptions:
        AND: All conditions must match (intersection)
        OR: Any condition can match (union)
    StringFilterCondition:
      properties:
        operator:
          $ref: '#/components/schemas/StringOperator'
          description: >-
            'is' (exact match), 'is_not' (exclude), 'contains' (partial,
            case-insensitive), 'not_contains' (exclude partial)
          examples:
            - is
            - contains
        value:
          title: Value
          description: >-
            An entity ID for exact matching, or text for name/content matching.
            Partial matching with 'contains' is case-insensitive.
          examples:
            - 550e8400-e29b-41d4-a716-446655440000
            - AI Tools
      additionalProperties: false
      type: object
      required:
        - operator
      title: StringFilterCondition
      description: |-
        A single text filter condition.

        Operators:
        - `is` — Exact match by ID or name.
        - `is_not` — Exclude exact match.
        - `contains` — Partial text match (case-insensitive).
        - `not_contains` — Exclude partial text match.

        Example: {"operator": "is", "value": "<topic-id>"}
        Example: {"operator": "contains", "value": "AI Tools"}
    BooleanFilterCondition:
      properties:
        operator:
          $ref: '#/components/schemas/BooleanOperator'
          description: '''is'' (match value) or ''is_not'' (exclude value)'
          examples:
            - is
        value:
          title: Value
          description: 'Boolean value: true or false.'
          examples:
            - true
            - false
      additionalProperties: false
      type: object
      required:
        - operator
      title: BooleanFilterCondition
      description: |-
        A single boolean filter condition.

        Operators:
        - `is` — Match value. Example: {"operator": "is", "value": true}
        - `is_not` — Exclude value.
    NumericFilterCondition:
      properties:
        operator:
          $ref: '#/components/schemas/NumericOperator'
          description: '''eq'' (=), ''neq'' (!=), ''gt'' (>), ''gte'' (>=), ''lt'' (<), ''lte'' (<=)'
          examples:
            - gte
            - lte
            - eq
        value:
          title: Value
          description: Numeric value to compare against (integer or float).
          examples:
            - 50
            - 3
            - 0.75
      additionalProperties: false
      type: object
      required:
        - operator
      title: NumericFilterCondition
      description: >-
        A single numeric filter condition for range-based filtering.


        Operators:

        - `eq` (=), `neq` (not equal), `gt` (>), `gte` (>=), `lt` (<), `lte`
        (<=)


        Example: {"operator": "gte", "value": 50}
    ReportFilterLeaf:
      properties:
        field:
          $ref: '#/components/schemas/ReportFilterField'
        operator:
          type: string
          title: Operator
          description: >-
            'is' | 'is_not' | 'contains' | 'not_contains' for text/id fields;
            'is' | 'is_not' for booleans; 'eq' | 'neq' | 'gt' | 'gte' | 'lt' |
            'lte' for numeric fields (volume, sentiment).
        value:
          title: Value
          description: The value to match against (required).
      additionalProperties: false
      type: object
      required:
        - field
        - operator
        - value
      title: ReportFilterLeaf
      description: >-
        A single condition inside an `advanced_filters` tree.


        The operator must fit the field: text/id fields take `is`, `is_not`,

        `contains`, `not_contains`; boolean fields (`branded`,
        `has_shopping_card`)

        take `is`, `is_not` with true/false; numeric fields (`volume`,
        `sentiment`)

        take `eq`, `neq`, `gt`, `gte`, `lt`, `lte` with a number. Anything else
        is

        rejected with 422 instead of being silently ignored.
    StringOperator:
      type: string
      enum:
        - is
        - is_not
        - contains
        - not_contains
      title: StringOperator
      description: >-
        Operator for string filter conditions. Accepts UUID or text values.


        - `is`: Exact match. If value is a UUID, matches by ID; otherwise
        matches by name/text

        - `is_not`: Exclude exact match. Inverse of 'is'

        - `contains`: Partial text match (case-insensitive). Value is matched
        using ILIKE

        - `not_contains`: Exclude partial text match. Inverse of 'contains'
      x-enumDescriptions:
        contains: Partial text match (case-insensitive). Value is matched using ILIKE
        is: >-
          Exact match. If value is a UUID, matches by ID; otherwise matches by
          name/text
        is_not: Exclude exact match. Inverse of 'is'
        not_contains: Exclude partial text match. Inverse of 'contains'
    BooleanOperator:
      type: string
      enum:
        - is
        - is_not
      title: BooleanOperator
      description: |-
        Operator for boolean filter conditions.

        - `is`: Match rows where the field equals the boolean value
        - `is_not`: Match rows where the field does not equal the boolean value
      x-enumDescriptions:
        is: Match rows where the field equals the boolean value
        is_not: Match rows where the field does not equal the boolean value
    NumericOperator:
      type: string
      enum:
        - eq
        - neq
        - gt
        - gte
        - lt
        - lte
      title: NumericOperator
      description: |-
        Operator for numeric filter conditions.

        - `eq`: Equal to (=)
        - `neq`: Not equal to (!=)
        - `gt`: Greater than (>)
        - `gte`: Greater than or equal to (>=)
        - `lt`: Less than (<)
        - `lte`: Less than or equal to (<=)
      x-enumDescriptions:
        eq: Equal to (=)
        gt: Greater than (>)
        gte: Greater than or equal to (>=)
        lt: Less than (<)
        lte: Less than or equal to (<=)
        neq: Not equal to (!=)
    ReportFilterField:
      type: string
      enum:
        - topics
        - prompts
        - tags
        - markets
        - intent
        - branded
        - platform
        - has_shopping_card
        - website_mentioned_in_answer
        - cited_page_url
        - cited_domain
        - website_mentioned_in_citation
        - volume
        - sentiment
      title: ReportFilterField
      description: A filter field usable as a leaf inside `advanced_filters`.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-KEY

````

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