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

# G2 product index

> Page through a complete, validated snapshot of G2 public English product-review URLs, 100 rows per page in slug order. Each row contains id (product slug) and url. Use the opaque cursor to stay on one snapshot, or page for the current snapshot. Snapshots refresh daily and expire after 48 hours. Partial refreshes are never published. A nonempty uncached page costs five credits; empty pages, errors, cache hits and idempotent replays are free. Cache-Control no-cache bypasses the API response cache but does not force a full catalogue refresh.

Read G2's public product-review URL catalogue, **100 products per page**. Each item contains `id`, the product slug, and its public review-page `url`. Use the slug with the product or reviews endpoint. The catalogue includes English URLs from all product-review sitemap groups; localized duplicates are omitted and slugs are sorted.

Use **`pagination.next_cursor`** to continue on the same snapshot. `data.next_cursor` contains the same token. `pagination.has_more` is the stop signal. A cursor remains usable until its snapshot expires, at most 48 hours after collection. Expired or unavailable cursor snapshots return an uncharged **409 `CURSOR_EXPIRED`**. Alternatively, use one-based `page` to read the current snapshot; do not combine page and cursor. Page numbers across a refresh can refer to different rows.

The catalogue refreshes separately from requests. A refresh validates every numbered source file and rechecks the sitemap directory before publishing. Failed or incomplete refreshes retain the previous complete snapshot; snapshots older than 48 hours are not served. `collected_at`, `expires_at` and `snapshot_id` identify exactly which index you received. This indexes public URLs, not proof that every product is still active or has reviews.

A nonempty uncached page costs **5 credits**. An empty page beyond the catalogue, errors, cache hits and successful idempotent replays cost zero. `X-Max-Credits: 5` caps the request. `Cache-Control: no-cache` bypasses the API response cache and reads the current validated snapshot; it does not download the entire source catalogue again. Background refresh currently uses a bounded existing Firecrawl trial allowance; exhausted source capacity prevents further refreshes.

`total` is the number of unique products in this snapshot, `returned_count` is the page size and `dropped` is zero. No partial catalogue is presented as complete.

A response-cache hit cannot extend snapshot expiry. A successful idempotent replay preserves its original dated payload under the normal 24-hour replay contract; it does not represent a fresh catalogue snapshot.


## OpenAPI

````yaml GET /g2/product-index
openapi: 3.1.0
info:
  title: SocialQuery API
  version: '2026-10-09'
  description: >-
    Documented requests for public-source records. Inspect accepted inputs and
    credit amounts, then verify the selected operation before integrating
    preview coverage.
servers:
  - url: https://socialquery.dev/v1
security:
  - apiKey: []
paths:
  /g2/product-index:
    get:
      tags:
        - G2
      summary: G2 Product Index
      description: >-
        Page through a complete, validated snapshot of G2 public English
        product-review URLs, 100 rows per page in slug order. Each row contains
        id (product slug) and url. Use the opaque cursor to stay on one
        snapshot, or page for the current snapshot. Snapshots refresh daily and
        expire after 48 hours. Partial refreshes are never published. A nonempty
        uncached page costs five credits; empty pages, errors, cache hits and
        idempotent replays are free. Cache-Control no-cache bypasses the API
        response cache but does not force a full catalogue refresh.
      operationId: get_g2_product_index
      parameters:
        - name: page
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 2501
            default: 1
          description: >-
            One-based page in the current complete snapshot. Cannot be combined
            with cursor. Beyond the last page returns an empty list at zero
            credits.
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: >-
            Opaque cursor returned in pagination.next_cursor or
            data.next_cursor. Keeps the same complete snapshot for up to 48
            hours; expired cursors return uncharged 409. Cannot be combined with
            page.
        - name: Cache-Control
          in: header
          required: false
          example: no-cache
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          required: false
          example: 7a5e1b4c-2d8f-4a3b-9c1e-6e8b4d2a1f3c
          schema:
            type: string
        - name: X-Max-Credits
          in: header
          required: false
          description: >-
            Optional nonnegative integer cap on the maximum request hold. A live
            request whose hold exceeds this cap returns 422
            CREDIT_BUDGET_EXCEEDED before spending. Metered holds use the
            requested limit; cache hits and successful idempotent replays cost
            zero.
          schema:
            type: integer
            minimum: 0
      responses:
        '200':
          description: >-
            Page through a complete, validated snapshot of G2 public English
            product-review URLs, 100 rows per page in slug order. Each row
            contains id (product slug) and url. Use the opaque cursor to stay on
            one snapshot, or page for the current snapshot. Snapshots refresh
            daily and expire after 48 hours. Partial refreshes are never
            published. A nonempty uncached page costs five credits; empty pages,
            errors, cache hits and idempotent replays are free. Cache-Control
            no-cache bypasses the API response cache but does not force a full
            catalogue refresh.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SocialQueryResponse'
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          items:
                            type: array
                            maxItems: 100
                            items:
                              type: object
                              properties:
                                id:
                                  type: string
                                url:
                                  type: string
                                  format: uri
                              required:
                                - id
                                - url
                              additionalProperties: false
                          total:
                            type: integer
                            minimum: 0
                          returned_count:
                            type: integer
                            minimum: 0
                          dropped:
                            const: 0
                          next_cursor:
                            type:
                              - string
                              - 'null'
                          page:
                            type: integer
                            minimum: 1
                          snapshot_id:
                            type: string
                          collected_at:
                            type: string
                            format: date-time
                          expires_at:
                            type: string
                            format: date-time
                          source_files:
                            type: integer
                            minimum: 1
                          coverage_note:
                            type: string
                        required:
                          - items
                          - total
                          - returned_count
                          - dropped
                          - next_cursor
                          - page
                          - snapshot_id
                          - collected_at
                          - expires_at
                          - source_files
                          - coverage_note
                        additionalProperties: false
                      pagination:
                        type: object
                        properties:
                          next_cursor:
                            type:
                              - string
                              - 'null'
                          has_more:
                            type: boolean
                          page_size:
                            type: integer
                            minimum: 0
                        required:
                          - next_cursor
                          - has_more
                          - page_size
                        additionalProperties: false
                    required:
                      - data
                      - pagination
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '402':
          $ref: '#/components/responses/Error402'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '405':
          $ref: '#/components/responses/Error405'
        '409':
          $ref: '#/components/responses/Error409'
        '422':
          $ref: '#/components/responses/Error422'
        '429':
          $ref: '#/components/responses/Error429'
        '500':
          $ref: '#/components/responses/Error500'
        '502':
          $ref: '#/components/responses/Error502'
        '503':
          $ref: '#/components/responses/Error503'
        '504':
          $ref: '#/components/responses/Error504'
components:
  schemas:
    SocialQueryResponse:
      type: object
      required:
        - success
        - platform
        - endpoint
        - credits_used
        - credits_remaining
        - request_id
        - cached
        - data
      properties:
        success:
          type: boolean
          const: true
        platform:
          type: string
        endpoint:
          type: string
        credits_used:
          type: integer
          minimum: 0
        credits_remaining:
          type:
            - integer
            - 'null'
        request_id:
          type: string
        cached:
          type: boolean
        data:
          type: object
          additionalProperties: true
          description: >-
            The selected operation determines the resource fields in this
            object. Source data can omit a metric or report it as null.
    SocialQueryError:
      type: object
      required:
        - success
        - platform
        - endpoint
        - credits_used
        - credits_remaining
        - request_id
        - cached
        - error
      properties:
        success:
          type: boolean
          const: false
        platform:
          type: string
        endpoint:
          type: string
        credits_used:
          type: integer
          minimum: 0
        credits_remaining:
          type:
            - integer
            - 'null'
        request_id:
          type: string
        cached:
          type: boolean
        error:
          type: object
          required:
            - code
            - type
            - message
            - status
            - doc_url
          properties:
            code:
              type: string
            type:
              type: string
            message:
              type: string
            status:
              type: integer
            doc_url:
              type: string
              format: uri
  responses:
    Error400:
      description: Upstream rejected the request.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error401:
      description: Missing, expired, invalid, or revoked API key.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error402:
      description: Insufficient SocialQuery credits.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error403:
      description: Key scope or provider policy denied access.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error404:
      description: Endpoint or upstream resource not found.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error405:
      description: HTTP method is not supported.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error409:
      description: Idempotency conflict or request in progress.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error422:
      description: Invalid parameters.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error429:
      description: Request limit reached.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error500:
      description: Request processing failed.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error502:
      description: Upstream service failed.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error503:
      description: Provider or required service is unavailable.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
    Error504:
      description: Upstream service timed out.
      headers:
        X-Request-Id:
          schema:
            type: string
        X-Credits-Used:
          schema:
            type: integer
        X-Credits-Remaining:
          schema:
            type: string
        X-Cache:
          schema:
            type: string
            enum:
              - HIT
              - MISS
              - BYPASS
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SocialQueryError'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````

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