{
  "openapi": "3.0.1",
  "info": {
    "title": "Apple App Store Review Scraper: Complaint & Bug Finder",
    "description": "🍎 Apple App Store Review Scraper pulls iOS app reviews at scale — rating, title, text, date, version, country & developer responses. 🔍 Ideal for ASO, sentiment, competitor analysis & product feedback. 📊 Export CSV/JSON; filter by locale, date or version. 🚀",
    "version": "0.1",
    "x-build-id": "qCpjpJ0EFvTepCnx3"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapier~apple-app-store-review-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapier-apple-app-store-review-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/scrapier~apple-app-store-review-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapier-apple-app-store-review-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/scrapier~apple-app-store-review-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapier-apple-app-store-review-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": {
          "appStoreLinks": {
            "title": "🎯 App Store links to audit",
            "type": "array",
            "description": "One App Store link per row — e.g. `https://apps.apple.com/us/app/quicken-simplifi-budget-smart/id1449777194`. A bare numeric app ID works too. The store region is read from the `/us/` segment of the link (defaults to `us`). The base keys `url` and `urls` are still accepted and are merged with this list.",
            "items": {
              "type": "string"
            }
          },
          "reviewsPerApp": {
            "title": "📦 How many reviews to KEEP per app",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "The run stops for an app once this many reviews have passed the whole funnel. This counts kept rows, not scanned ones — with tight filters the actor may read all 500 available reviews to fill 20 slots. Apple's hard ceiling is 500 per app per store region. Default 20.",
            "default": 20
          },
          "sortBy": {
            "title": "↕️ Which feed to read",
            "enum": [
              "mostRecent",
              "mostHelpful"
            ],
            "type": "string",
            "description": "`mostRecent` = newest first, the freshest complaints. `mostHelpful` = the reviews other users voted up, and the feed where Apple actually populates helpful-vote counts. Measured 2026-07-19 across two independent 10-app samples of the **US** storefront, pages 1–3, n=1,500 reviews each: **44.5–47.7%** of most-helpful reviews carry a non-zero vote count versus **3.1–3.9%** of recent ones. Apple retired `mostCritical` and `mostFavorable` — both return HTTP 500 on every app tried, so only the two working values are offered here.",
            "default": "mostRecent"
          },
          "keepStarRatings": {
            "title": "⭐ Keep only these star ratings",
            "type": "array",
            "description": "Select nothing to keep every rating. For complaint triage pick 1 and 2. Read from Apple's own `im:rating` value on each review, never inferred from the text.",
            "items": {
              "type": "string",
              "enum": [
                "1",
                "2",
                "3",
                "4",
                "5"
              ],
              "enumTitles": [
                "★ 1 star",
                "★★ 2 stars",
                "★★★ 3 stars",
                "★★★★ 4 stars",
                "★★★★★ 5 stars"
              ]
            },
            "default": []
          },
          "mustContainKeywords": {
            "title": "🔤 Must mention at least one of these",
            "type": "array",
            "description": "Case-insensitive substring match across the review title AND body. A kept row reports which term fired in the `matchedKeyword` column. Leave empty to skip this stage. Example: `crash`, `refund`, `face id`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "mustNotContainKeywords": {
            "title": "🚫 Drop reviews mentioning any of these",
            "type": "array",
            "description": "Case-insensitive substring match across title and body. Useful for stripping recurring off-topic noise out of a complaint feed. Leave empty to skip this stage.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "minHelpfulVotes": {
            "title": "👍 Minimum helpful votes",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only reviews at least this many people marked helpful (Apple's `im:voteSum`). ⚠️ Only meaningful with sortBy = `mostHelpful`: on the recency feed only 3.1–3.9% of reviews carry any votes (US storefront, pages 1–3, two samples of n=1,500), so a threshold there drops almost everything. The run logs a loud warning if you combine them. 0 = off.",
            "default": 0
          },
          "minReviewLength": {
            "title": "📏 Minimum review length (characters)",
            "minimum": 0,
            "type": "integer",
            "description": "Drops one-line ratings with no substance so the output is feedback a product team can act on. Counts characters of the review body. 0 = off. Try 120 for a substantive-feedback-only run.",
            "default": 0
          },
          "dedupeByReviewId": {
            "title": "🧹 Drop duplicate review IDs",
            "type": "boolean",
            "description": "Apple's feed can repeat the same review across pages. When on, each Apple review ID is emitted at most once per run (across all apps and pages). Duplicates are counted in the log.",
            "default": true
          },
          "tagIssues": {
            "title": "🏷️ Tag each review with an issue type",
            "type": "boolean",
            "description": "Adds `issueType` (highest-priority category that fired), `issueTypes` (all that fired), `issueSignals` (the exact phrases matched, so every tag is auditable) and `isComplaint`. A review matching no phrase gets `issueType = null` — never a guessed category. Note `issueType` marks the TOPIC a review discusses, not its sentiment (a 5-star review can be tagged `ads`); `isComplaint` is the separate judgement — true at 1-2 stars, or at 3 stars with a non-feature-request tag, and always false at 4-5 stars.",
            "default": true
          },
          "onlyReviewsWithIssues": {
            "title": "🎯 Keep only reviews that got an issue tag",
            "type": "boolean",
            "description": "Drops praise and content-free reviews outright — the fastest route to a pure bug/complaint list. Turns issue tagging on automatically if it was off.",
            "default": false
          },
          "onlyIssueTypes": {
            "title": "🗂️ Restrict to specific issue types",
            "type": "array",
            "description": "Keep only reviews whose primary `issueType` is one of these. Select nothing to keep all tagged types. Example: pick crash + bug for a release post-mortem, or billing for a refund-pressure audit.",
            "items": {
              "type": "string",
              "enum": [
                "crash",
                "bug",
                "login_auth",
                "billing",
                "data_sync",
                "performance",
                "ads",
                "ui_ux",
                "support",
                "feature_request"
              ],
              "enumTitles": [
                "💥 Crash / freeze / won't open",
                "🐛 Bug / glitch / not working",
                "🔐 Login & authentication",
                "💳 Billing, refunds & subscriptions",
                "🔄 Sync & lost data",
                "🐌 Performance & battery",
                "📺 Ads",
                "🎨 UI / UX & redesign complaints",
                "🎧 Customer support",
                "💡 Feature request"
              ]
            },
            "default": []
          },
          "pagesPerApp": {
            "title": "📄 Max feed pages to scan per app",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Apple serves 50 reviews per page and hard-stops after 10 pages (page 11 returns HTTP 400), so 10 is the real maximum. Lower it to cap how much the funnel scans. Default 10. Also accepted as the base keys `max_pages` / `maxPages`.",
            "default": 10
          },
          "pageDelaySeconds": {
            "title": "⏱️ Pause between pages (seconds)",
            "minimum": 0,
            "maximum": 30,
            "type": "integer",
            "description": "Politeness delay between feed pages; a small random jitter is added on top. Default 2. Also accepted as the base keys `delay_between_pages` / `delayBetweenPagesSeconds`.",
            "default": 2
          },
          "proxyConfiguration": {
            "title": "🌐 Proxy",
            "type": "object",
            "description": "Optional. Apple's review feed is keyless and works with no proxy at all; the actor only escalates to a proxy if the store starts refusing requests."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}