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

# Rank brands by share-of-conversation vs share-of-shelf gap

> Brands ranked by the GAP between share of social conversation and share of shelf inside one category. Over-indexed attention with under-distribution is the ranging signal a retail buyer wants and the deck slide a challenger brand wants - one endpoint, two customer types. Requires BOTH corpora bound to the same category axis and the same brand key, which is why nobody holding one of them can reproduce it. The join is on brand KEY, never on name: a row whose key is absent from the other side is dropped and COUNTED in `unmatched`, because matching by name mislabels a real brand as under-distributed. Carries TWO coverage blocks and TWO freshness values - social counts mention subjects on a weekly refresh, shelf counts products on a daily one, and merging either pair would be a lie with a familiar shape. `shelf_brands_not_in_conversation` is the mirror finding: stocked and unspoken of.



## OpenAPI

````yaml https://api.syntalic.com/openapi.json get /v1/social/attention-vs-shelf
openapi: 3.1.0
info:
  title: 'Syntalic — Data Analytics for Agentic Commerce '
  version: 1.0.0
  contact:
    name: Syntalic
    email: support@syntalic.com
    url: https://syntalic.com
  description: >-
    Competitive pricing data across US and Canadian e-commerce retailers
    (Amazon, Walmart, Target, Best Buy, Home Depot, etc.). Serves price
    comparisons, deal alerts, brand tracking, promotional intelligence, and
    market analytics to AI agents via x402 and MPP micropayments.
  x-guidance: >-
    This API has three endpoint groups organized by use case:


    **Shopper endpoints** ($0.01/query): Use these for price comparisons and
    deal hunting. Start with /v1/shopper/best-price?q=<product> to find the
    cheapest option across retailers. Use
    /v1/shopper/deal-finder?category=<category> to find discounted products. Use
    /v1/shopper/price-drop-alert?q=<product> to check for recent price drops.


    **Marketing endpoints** ($0.01/query): Use these for competitive analysis.
    /v1/marketing/competitive-landscape?category=<category> shows all products
    in a category with pricing. /v1/marketing/brand-tracker?brand=<brand> tracks
    a brand's pricing over time.
    /v1/marketing/share-of-shelf?category=<category> shows brand market share.


    **Analyst endpoints** ($0.02/query): Use these for market-level insights.
    /v1/analyst/inflation?category=<category> shows price trends over time.
    /v1/analyst/price-dispersion?category=<category> shows price spread across
    retailers.


    All endpoints accept an optional 'country' parameter (us or ca, defaults to
    us). Query parameters use 'q' for free-text search and 'category' for
    category-level queries.


    Marketing and analyst responses carry a `meta` block (served_from,
    freshness_seconds, schema_version) for staleness budgeting and a `resolved`
    block describing how the category input was matched against the taxonomy.
    Every response also sends an X-Data-Freshness-Hours header.


    **Free pre-payment rejection:** requests that cannot be served are rejected
    BEFORE any payment challenge — invalid params (400 INVALID_PARAMS),
    retailers that are not serving-eligible (404 RETAILER_NOT_SERVING_ELIGIBLE,
    with the catalog quality status and the serving_eligible_retailers list in
    error.details), and shopper queries that resolve to nothing in the catalog
    (404 NO_RESULTS). You only pay when the API can actually execute your query.
    Retailer values are case-insensitive (amazon == Amazon).
servers:
  - url: https://api.syntalic.com
security: []
paths:
  /v1/social/attention-vs-shelf:
    get:
      tags:
        - Social
      summary: Rank brands by share-of-conversation vs share-of-shelf gap
      description: >-
        Brands ranked by the GAP between share of social conversation and share
        of shelf inside one category. Over-indexed attention with
        under-distribution is the ranging signal a retail buyer wants and the
        deck slide a challenger brand wants - one endpoint, two customer types.
        Requires BOTH corpora bound to the same category axis and the same brand
        key, which is why nobody holding one of them can reproduce it. The join
        is on brand KEY, never on name: a row whose key is absent from the other
        side is dropped and COUNTED in `unmatched`, because matching by name
        mislabels a real brand as under-distributed. Carries TWO coverage blocks
        and TWO freshness values - social counts mention subjects on a weekly
        refresh, shelf counts products on a daily one, and merging either pair
        would be a lie with a familiar shape. `shelf_brands_not_in_conversation`
        is the mirror finding: stocked and unspoken of.
      operationId: getAttentionVsShelf
      parameters:
        - name: category
          in: query
          required: true
          schema:
            type: string
          example: grocery-gourmet-food
          description: >-
            Category root slug (department, not aisle). No wildcard: these
            answers are ranked comparisons.
        - name: country
          in: query
          required: false
          schema:
            type: string
            enum:
              - us
              - ca
            default: us
          description: Country for the SHELF side of the join.
        - name: window
          in: query
          required: false
          schema:
            type: string
            enum:
              - 7d
              - 30d
              - 90d
            default: 30d
          description: Rollup window. Only published windows are accepted.
        - name: platform
          in: query
          required: false
          schema:
            type: string
            enum:
              - all
              - tiktok
              - instagram
            default: all
          description: TikTok and Instagram are the only platforms in the corpus.
        - name: organic_only
          in: query
          required: false
          schema:
            type: boolean
            default: false
          description: Exclude posts marked as ads.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 25
            minimum: 1
            maximum: 100
          description: Maximum ranked brands to return.
      responses:
        '200':
          description: Attention vs shelf ranking
          content:
            application/json:
              schema:
                type: object
                properties:
                  category:
                    type: string
                  country:
                    type: string
                  currency:
                    type: string
                  window_days:
                    type: integer
                  platform:
                    type: string
                  organic_only:
                    type: boolean
                  brands:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  corpus_mentions:
                    type: integer
                    description: >-
                      The conversation the shares divide up. A share of 40
                      mentions is not the same kind of fact as a share of
                      40,000.
                  thin_corpus:
                    type: string
                    description: >-
                      Present when the whole category's corpus is below the
                      depth floor: the ranking is arithmetic, not a market
                      signal.
                  unmatched:
                    type: object
                    additionalProperties: true
                    description: >-
                      Rows dropped per side because their brand key has no
                      counterpart. Counted, never fuzzy-matched.
                  coverage:
                    type: object
                    additionalProperties: true
                    description: >-
                      TWO blocks — social counts mention subjects, shelf counts
                      products. Never merged.
                  freshness:
                    type: object
                    additionalProperties: true
                    description: TWO values — weekly social, daily serving. Never the max.
                  snapshot:
                    type: object
                    additionalProperties: true
                    nullable: true
                  resolved:
                    type: object
                    properties:
                      input:
                        type: string
                      category_path:
                        type: string
                        nullable: true
                      department:
                        type: string
                        nullable: true
                      match_source:
                        type: string
                        nullable: true
                      match_confidence:
                        type: number
                        nullable: true
                      alternates:
                        type: array
                        items:
                          type: object
                          additionalProperties: true
                    additionalProperties: true
                  meta:
                    type: object
                    properties:
                      served_from:
                        type: string
                      freshness_seconds:
                        type: number
                      schema_version:
                        type: string
                      computed_at:
                        type: string
                        format: date-time
                      price_observed_at_min:
                        type: string
                        format: date-time
                        nullable: true
                      price_observed_at_max:
                        type: string
                        format: date-time
                        nullable: true
                    additionalProperties: true
        '400':
          description: >-
            Invalid query parameters or unsupported enum values. Rejected by
            preflight BEFORE the payment challenge — no payment is requested or
            charged for malformed requests.
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - type
                  - title
                  - status
                properties:
                  type:
                    type: string
                    format: uri-reference
                  title:
                    type: string
                    example: Bad Request
                  status:
                    type: integer
                    const: 400
                  detail:
                    type: string
                  instance:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                    additionalProperties: true
                additionalProperties: true
        '402':
          description: Payment challenge required before executing paid work
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - type
                  - title
                  - status
                properties:
                  type:
                    type: string
                    format: uri-reference
                  title:
                    type: string
                    example: Payment Required
                  status:
                    type: integer
                    const: 402
                  detail:
                    type: string
                  instance:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                    additionalProperties: true
                additionalProperties: true
        '404':
          description: >-
            No matching result. error.code distinguishes the cases: NO_RESULTS
            (the query resolves to nothing in the catalog),
            RETAILER_NOT_SERVING_ELIGIBLE (the requested retailer exists but is
            not serving-eligible — error.details carries its catalog
            quality_status and the serving_eligible_retailers list to retry
            against), or NOT_PUBLISHED (a social rollup the current publish run
            does not compute yet — a gap in what we publish, not a finding about
            the category). Structurally-unservable requests are rejected by
            preflight before any payment challenge.
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - type
                  - title
                  - status
                properties:
                  type:
                    type: string
                    format: uri-reference
                  title:
                    type: string
                    example: Not Found
                  status:
                    type: integer
                    const: 404
                  detail:
                    type: string
                  instance:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                    additionalProperties: true
                additionalProperties: true
        '429':
          description: Rate limit exceeded
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - type
                  - title
                  - status
                properties:
                  type:
                    type: string
                    format: uri-reference
                  title:
                    type: string
                    example: Too Many Requests
                  status:
                    type: integer
                    const: 429
                  detail:
                    type: string
                  instance:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                    additionalProperties: true
                additionalProperties: true
        '500':
          description: Unexpected server error
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - type
                  - title
                  - status
                properties:
                  type:
                    type: string
                    format: uri-reference
                  title:
                    type: string
                    example: Internal Server Error
                  status:
                    type: integer
                    const: 500
                  detail:
                    type: string
                  instance:
                    type: string
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                    additionalProperties: true
                additionalProperties: true

````