> ## 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 Ads Report

> Sponsored-placement metrics grouped by one or more dimensions. This is the report behind the
UI Ads screen — use it for ad visibility, share of ad placements and advertiser breakdowns.

Only answers from AI models that serve ads (ChatGPT and Google AI Overviews) are in scope;
filtering to any other platform correctly returns no rows.

**Example:** "Which advertisers bid against my brand, by topic?"

**Dimensions** (at least 1 required): `topic`, `tag`, `market`, `model`, `query`, `date`, `website`, `branded`, `product`, `placement_type`, `advertiser`
- `product` rows also carry `product_image`, `product_link`, `brand_id` / `brand_name` / `brand_url` / `brand_logo`, `brand_is_self` and `product_source_type`; `advertiser` rows carry `advertiser_url`, `advertiser_logo`, `advertiser_is_self`
- `date` supports optional `date_aggregation_interval`: `day` (default) | `week` | `month`; buckets on the placement date
- `website` is the advertised brand, and auto-sets `website_type` to `SELF+COMPETITORS`; `product` / `advertiser` auto-set it to `ALL`, like the dashboard's Advertisers page (default otherwise is `SELF`)
- `product` is the ad creative — a product card (`AD_SHOPPING`) or a text ad (`AD_TEXT`)

**Measures** (omit for all): `ad_visibility`, `share_of_ad_placements`, `ad_placements`, `ad_answers`, `placements_with_self_brand`, `unique_advertisers`, `unique_ad_creatives`, `ad_rank`, `avg_quoted_price`
- `ad_visibility` = `ad_placements` / `ad_answers`, where `ad_answers` counts answers in the group holding at least one ad from any advertiser — matching the Ads dashboard
- `share_of_ad_placements` = this advertiser's placements / all tracked advertisers' placements, the definition behind the Ads dashboard KPI card. The dashboard's Advertisers table labels `ad_placements / ad_answers` as "share of ad placements"; that column is `ad_visibility` here
- `ad_placements` counts distinct **answers** in which the entity's ad appeared, not individual placements
- `avg_quoted_price` also returns `avg_quoted_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`, `advertisers`, `placement_type`, `source_type`, `price`, `product_rank`.
- `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`, `advertiser_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/ads
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/ads:
    post:
      tags:
        - Reports
      summary: Get Ads Report
      description: >-
        Sponsored-placement metrics grouped by one or more dimensions. This is
        the report behind the

        UI Ads screen — use it for ad visibility, share of ad placements and
        advertiser breakdowns.


        Only answers from AI models that serve ads (ChatGPT and Google AI
        Overviews) are in scope;

        filtering to any other platform correctly returns no rows.


        **Example:** "Which advertisers bid against my brand, by topic?"


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

        - `product` rows also carry `product_image`, `product_link`, `brand_id`
        / `brand_name` / `brand_url` / `brand_logo`, `brand_is_self` and
        `product_source_type`; `advertiser` rows carry `advertiser_url`,
        `advertiser_logo`, `advertiser_is_self`

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

        - `website` is the advertised brand, and auto-sets `website_type` to
        `SELF+COMPETITORS`; `product` / `advertiser` auto-set it to `ALL`, like
        the dashboard's Advertisers page (default otherwise is `SELF`)

        - `product` is the ad creative — a product card (`AD_SHOPPING`) or a
        text ad (`AD_TEXT`)


        **Measures** (omit for all): `ad_visibility`, `share_of_ad_placements`,
        `ad_placements`, `ad_answers`, `placements_with_self_brand`,
        `unique_advertisers`, `unique_ad_creatives`, `ad_rank`,
        `avg_quoted_price`

        - `ad_visibility` = `ad_placements` / `ad_answers`, where `ad_answers`
        counts answers in the group holding at least one ad from any advertiser
        — matching the Ads dashboard

        - `share_of_ad_placements` = this advertiser's placements / all tracked
        advertisers' placements, the definition behind the Ads dashboard KPI
        card. The dashboard's Advertisers table labels `ad_placements /
        ad_answers` as "share of ad placements"; that column is `ad_visibility`
        here

        - `ad_placements` counts distinct **answers** in which the entity's ad
        appeared, not individual placements

        - `avg_quoted_price` also returns `avg_quoted_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`,
        `advertisers`, `placement_type`, `source_type`, `price`, `product_rank`.

        - `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`, `advertiser_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_ads_report
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdsReportRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdsReportResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
components:
  schemas:
    AdsReportRequest:
      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 ad data by. At least one dimension is required.
          examples:
            - - website
            - - advertiser
            - - topic
              - date
        measures:
          items:
            $ref: '#/components/schemas/AdsMeasure'
          type: array
          title: Measures
          description: Ad metrics to include. If empty, all measures are returned.
          examples:
            - - ad_visibility
              - share_of_ad_placements
        filters:
          $ref: '#/components/schemas/AdsFiltersInput'
          description: >-
            Narrow results by topics, markets, advertisers, placement type, 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 only,
            'SELF+COMPETITORS' = plus competitors, 'ALL' = including untracked
            third-party brands.
          examples:
            - SELF+COMPETITORS
      additionalProperties: false
      type: object
      required:
        - project_id
        - dimensions
      title: AdsReportRequest
      description: Request parameters for the Ads Report API.
    AdsReportResponse:
      properties:
        info:
          $ref: '#/components/schemas/ResponseInfo'
          description: >-
            Information of the API request including total count and query
            details
        data:
          items:
            $ref: '#/components/schemas/AdsDataRow'
          type: array
          title: Data
          description: Array of ad data rows grouped by the requested dimensions
      type: object
      title: AdsReportResponse
      description: Response containing ads 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
    AdsMeasure:
      type: string
      enum:
        - ad_visibility
        - share_of_ad_placements
        - ad_placements
        - ad_answers
        - placements_with_self_brand
        - unique_advertisers
        - unique_ad_creatives
        - ad_rank
        - avg_quoted_price
      title: AdsMeasure
      description: >-
        Ad metrics to include in the report.


        - `ad_visibility`: Percentage of ad-bearing answers featuring this
        entity (0-100)

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

        - `ad_placements`: Number of distinct answers in which this entity's ad
        appeared

        - `ad_answers`: Total answers in the group containing at least one ad
        placement (the ad_visibility denominator)

        - `placements_with_self_brand`: Ad placements promoting your own brand's
        product

        - `unique_advertisers`: Number of distinct advertisers

        - `unique_ad_creatives`: Number of distinct ad creatives (product cards
        and text ads)

        - `ad_rank`: Average position of the ad within the answer (lower is
        better)

        - `avg_quoted_price`: Average quoted price across ad purchase links;
        also returns avg_quoted_price_currency
      x-enumDescriptions:
        ad_answers: >-
          Total answers in the group containing at least one ad placement (the
          ad_visibility denominator)
        ad_placements: Number of distinct answers in which this entity's ad appeared
        ad_rank: Average position of the ad within the answer (lower is better)
        ad_visibility: Percentage of ad-bearing answers featuring this entity (0-100)
        avg_quoted_price: >-
          Average quoted price across ad purchase links; also returns
          avg_quoted_price_currency
        placements_with_self_brand: Ad placements promoting your own brand's product
        share_of_ad_placements: >-
          This entity's placements as a percentage of all tracked-brand ad
          placements in the group (0-100)
        unique_ad_creatives: Number of distinct ad creatives (product cards and text ads)
        unique_advertisers: Number of distinct advertisers
    AdsFiltersInput:
      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
        advertisers:
          $ref: '#/components/schemas/StringFilterGroup'
          description: Filter by advertiser website ID, name or URL.
          examples:
            - condition: AND
              items:
                - operator: contains
                  value: shopify
      additionalProperties: false
      type: object
      title: AdsFiltersInput
      description: >-
        Filters for the Ads 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 ad creative ID or title.

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

        - `advertisers` — Filter by advertiser website ID, name or URL.

        - `placement_type` — 'AD_TEXT', 'AD_SHOPPING'.

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

        - `price` — Numeric: quoted price on an ad purchase link.

        - `product_rank` — Numeric: the ad's position within the answer.


        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.
    AdsDataRow:
      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')
        advertiser_id:
          type: string
          title: Advertiser Id
          description: Unique identifier of the advertiser
        advertiser_name:
          type: string
          title: Advertiser Name
          description: Display name of the advertiser
        advertiser_url:
          type: string
          title: Advertiser Url
          description: Advertiser website URL
        advertiser_logo:
          type: string
          title: Advertiser Logo
          description: Advertiser logo URL
        advertiser_is_self:
          type: boolean
          title: Advertiser Is Self
          description: True when the advertiser is your own website
        ad_visibility:
          type: number
          title: Ad Visibility
          description: Percentage of ad-bearing answers featuring this entity (0-100)
        share_of_ad_placements:
          type: number
          title: Share Of Ad Placements
          description: >-
            This entity's placements as a percentage of all tracked-brand ad
            placements in the group (0-100)
        ad_placements:
          type: integer
          title: Ad Placements
          description: Number of distinct answers in which this entity's ad appeared
        ad_answers:
          type: integer
          title: Ad Answers
          description: Total answers in the group containing at least one ad placement
        placements_with_self_brand:
          type: integer
          title: Placements With Self Brand
          description: Ad placements promoting your own brand's product
        unique_advertisers:
          type: integer
          title: Unique Advertisers
          description: Number of distinct advertisers
        unique_ad_creatives:
          type: integer
          title: Unique Ad Creatives
          description: Number of distinct ad creatives
        ad_rank:
          type: number
          title: Ad Rank
          description: Average position of the ad within the answer (lower is better)
        avg_quoted_price:
          type: number
          title: Avg Quoted Price
          description: Average quoted price across ad purchase links
        avg_quoted_price_currency:
          type: string
          title: Avg Quoted Price Currency
          description: Currency of avg_quoted_price (e.g. 'USD')
        previous_ad_visibility:
          type: number
          title: Previous Ad Visibility
          description: >-
            ad_visibility over the comparison date range (present only when a
            comparison range was requested)
        previous_share_of_ad_placements:
          type: number
          title: Previous Share Of Ad Placements
          description: share_of_ad_placements over the comparison date range
        previous_ad_placements:
          type: integer
          title: Previous Ad Placements
          description: ad_placements over the comparison date range
        previous_ad_answers:
          type: integer
          title: Previous Ad Answers
          description: ad_answers over the comparison date range
        previous_placements_with_self_brand:
          type: integer
          title: Previous Placements With Self Brand
          description: placements_with_self_brand over the comparison date range
        previous_unique_advertisers:
          type: integer
          title: Previous Unique Advertisers
          description: unique_advertisers over the comparison date range
        previous_unique_ad_creatives:
          type: integer
          title: Previous Unique Ad Creatives
          description: unique_ad_creatives over the comparison date range
        previous_ad_rank:
          type: number
          title: Previous Ad Rank
          description: ad_rank over the comparison date range
        previous_avg_quoted_price:
          type: number
          title: Previous Avg Quoted Price
          description: avg_quoted_price over the comparison date range
      type: object
      title: AdsDataRow
      description: A single row of ads 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.