{
  "openapi": "3.0.1",
  "info": {
    "title": "G2 Scraper — Reviews by Product Name · AI Insights + Emails",
    "description": "Scrape G2.com software reviews — search by product name (Slack, HubSpot) or by category, no G2 URL needed. Get ratings, pros and cons, verified-reviewer details, star and date filters, deterministic review insights, opt-in AI pain-point analysis and contact-email enrichment. $1.50 per 1,000 reviews.",
    "version": "0.0",
    "x-build-id": "kLTvxwk901HfakbeZ"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~g2-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-g2-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/memo23~g2-scraper/runs": {
      "post": {
        "operationId": "runs-sync-memo23-g2-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/memo23~g2-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-g2-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "searchQueries": {
            "title": "🔍 Search G2 by product or company name",
            "type": "array",
            "description": "Find products by name — e.g. `Slack`, `HubSpot`, `Salesforce` — and scrape their reviews. No need to know the G2 URL or slug. Each query runs its own G2 search; use **Max items** to cap results.",
            "items": {
              "type": "string"
            }
          },
          "categorySlugs": {
            "title": "🗂️ G2 categories",
            "type": "array",
            "description": "Scrape every product in a G2 category. Accepts a category slug (`crm`, `project-management`), a subcategory path (`crm/sales-acceleration`), or a full `https://www.g2.com/categories/...` URL.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Start URLs (optional)",
            "type": "array",
            "description": "Optional — use instead of, or alongside, the search fields above. Accepts G2 product review URLs, search URLs (`https://www.g2.com/search?query=...`), category URLs, and vendor URLs.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "productSlugs": {
            "title": "Product slugs (reviews shortcut)",
            "type": "array",
            "description": "Optional shortcut, used in addition to Start URLs: list bare G2 product slugs (e.g. <code>postman</code>, <code>hubspot-marketing-hub</code>) and each maps to that product's reviews page — no URL building needed. The review sorting & filter options below apply to these too.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max Listings",
            "type": "integer",
            "description": "Maximum results to scrape PER start URL — each URL you paste gets its own allowance (e.g. 3 search URLs × 100 = up to 300 rows). Total spend stays bounded by the run's cost limit.",
            "default": 10000
          },
          "maxReviews": {
            "title": "Max reviews per product",
            "minimum": 0,
            "type": "integer",
            "description": "Cap on review rows per /products/{slug}/reviews URL. Falls back to Max Listings when unset. Only applies to review URLs."
          },
          "sortOrder": {
            "title": "Sort reviews by",
            "enum": [
              "g2_default",
              "most_recent",
              "most_helpful",
              "highest_rated",
              "lowest_rated"
            ],
            "type": "string",
            "description": "How G2 orders the reviews before your Max Listings cap is applied. \"Most recent\" + a low cap = the freshest reviews only.",
            "default": "g2_default"
          },
          "starFilterCondition": {
            "title": "Star filter — condition",
            "enum": [
              "exactly",
              "minimum",
              "maximum"
            ],
            "type": "string",
            "description": "How the star value below is applied: exactly that star bucket, that many stars and above (minimum), or that many and below (maximum). Ignored unless a star value is set.",
            "default": "exactly"
          },
          "starFilterValue": {
            "title": "Star filter — stars (1–5)",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Only reviews in the selected star bucket(s). Example: condition \"Minimum of\" + 4 → only 4★ and 5★ reviews. Note G2's buckets include half-stars (the 4★ bucket spans 3.5–4.0)."
          },
          "lookbackDays": {
            "title": "Published within last N days",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Only reviews published within this many days. Forces most-recent ordering so the scraper can stop early at the cutoff — fewer pages fetched, faster and cheaper. Leave empty for all time."
          },
          "maxConcurrency": {
            "title": "Max Concurrency",
            "type": "integer",
            "description": "Maximum number of pages that can be processed at the same time.",
            "default": 100
          },
          "minConcurrency": {
            "title": "Min Concurrency",
            "type": "integer",
            "description": "Minimum number of pages that will be processed at the same time.",
            "default": 1
          },
          "maxRequestRetries": {
            "title": "Max Request Retries",
            "type": "integer",
            "description": "Number of times the crawler will retry a failed request before giving up.",
            "default": 100
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "enrichEmails": {
            "title": "Enrich with contact emails (experimental, billed per email)",
            "type": "boolean",
            "description": "If enabled, finds a contact email for each result from its own website (or by discovering it from the name). Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Billed per contact email found; only charged when an email is returned, never for misses.",
            "default": false
          },
          "qualifyByPayment": {
            "title": "💳 Qualify by payment (flag businesses that take money online)",
            "type": "boolean",
            "description": "Requires \"Enrich with contact emails\". Scans each business's website — reusing the pages already fetched for email discovery, so no extra cost or time — for payment processors and e-commerce platforms (Stripe, Shopify, PayPal, Paddle, Lemon Squeezy, WooCommerce, Square, Chargebee and more). Adds takesPayments (is this a real paying business?), paymentProcessors (which stack), stripeLiveKey (the public key if exposed) and paymentConfidence. Turn raw contacts into monetization-qualified leads. No extra charge — included with each enriched company.",
            "default": false
          },
          "reviewInsights": {
            "title": "📊 Review insights — instant digest per product (no AI, billed per product)",
            "type": "boolean",
            "description": "Adds one `review_insights` row per product: rating breakdown & sentiment split, the recurring software complaint themes (bugs, pricing, support, missing features, onboarding, integrations…), top negative-review terms, and feature-request snippets. Deterministic — instant, no AI credits or keys required. Billed per product analyzed.",
            "default": false
          },
          "painPointAnalysis": {
            "title": "Run AI pain-point analysis (one report per product)",
            "type": "boolean",
            "description": "Adds a single `painPointAnalysis` row per product alongside the reviews: the top complaint themes (each with a severity score and how often it recurs), the missing features users keep asking for, quick wins, overall sentiment, and a short summary — the 'what should we fix / build next' teardown, straight from real reviews. Analyzes up to 200 reviews per product. Requires a paid Apify plan; billed per product analyzed.",
            "default": false
          },
          "pageConcurrency": {
            "title": "Page concurrency",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many list pages (product reviews, search results, or category listings) to fetch in parallel. Each page is an independent unblocker call (fresh IP + anti-bot bypass), so higher = faster with no extra credit cost — but keep it within your scrape.do plan's concurrent-request limit. If exceeded, requests get a 429 and are auto-retried with back-off (slower, but no data lost). Default 3 is safe for the current plan; raise it after upgrading scrape.do.",
            "default": 3
          },
          "pageDelayMs": {
            "title": "Delay between page batches (ms)",
            "minimum": 0,
            "type": "integer",
            "description": "Optional pause between parallel page batches. Leave at 0 for fastest scraping (the unblocker already rotates IPs and handles anti-bot per request). Raise it only if you want to be extra gentle.",
            "default": 0
          },
          "slowMode": {
            "title": "Slow mode (extra anti-bot back-off)",
            "type": "boolean",
            "description": "Adds extra warm-up delays and longer back-off between pages for DataDome evasion. Disable only if you've verified your proxy + IPs are clean.",
            "default": true
          },
          "useCachedData": {
            "title": "Use cached data when available",
            "type": "boolean",
            "description": "Serve results instantly from our G2 database when we already hold a recent copy of the page (much faster, and no proxy cost). Cached rows are marked with servedFromCache and dataAsOf so you always see how old they are. Turn off to force a live scrape.",
            "default": true
          },
          "maxCacheAgeDays": {
            "title": "Max cache age (days)",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Only serve cached results newer than this many days. Lower = fresher but more live scraping. Defaults: sellers 30d, products 14d, reviews 7d."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}