{
  "openapi": "3.0.1",
  "info": {
    "title": "App Store Listing Change Feed - iOS ASO & Price Change Tracker",
    "description": "Watches iOS apps across App Store storefronts and emits only what changed since the last run: renamed title, edited description (word-level diff), new version and release notes, price change, new icon or screenshots, category move, delisting or new storefront.",
    "version": "1.0",
    "x-build-id": "N3dUhzwl2Z0HbNuB1"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/mibedk~app-store-listing-change-feed/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-mibedk-app-store-listing-change-feed",
        "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/mibedk~app-store-listing-change-feed/runs": {
      "post": {
        "operationId": "runs-sync-mibedk-app-store-listing-change-feed",
        "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/mibedk~app-store-listing-change-feed/run-sync": {
      "post": {
        "operationId": "run-sync-mibedk-app-store-listing-change-feed",
        "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": {
          "appIds": {
            "title": "Apps to watch",
            "type": "array",
            "description": "App Store URLs (https://apps.apple.com/us/app/facebook/id284882215), bare numeric App Store IDs (284882215), or 'id284882215' fragments - all three are accepted. This is the watchlist; each app is checked in every storefront listed below.",
            "default": [
              "https://apps.apple.com/us/app/id284882215",
              "https://apps.apple.com/us/app/id571800810",
              "https://apps.apple.com/us/app/id6448311069"
            ],
            "items": {
              "type": "string"
            }
          },
          "countries": {
            "title": "Storefronts",
            "type": "array",
            "description": "Two-letter App Store storefront codes, e.g. us, gb, de, jp, br. Each app is diffed independently per storefront, because titles, descriptions, prices and screenshots are localised. More storefronts means proportionally more 'app-checked' events.",
            "default": [
              "us"
            ],
            "items": {
              "type": "string"
            }
          },
          "seedFromChart": {
            "title": "Also watch a top chart",
            "enum": [
              "none",
              "top-free",
              "top-paid",
              "top-grossing"
            ],
            "type": "string",
            "description": "Optionally add the current Apple top chart for the first storefront to the watchlist. Use this to watch a whole category of competitors without listing them by hand. The chart is re-read on every run, so apps that climb into it are picked up automatically.",
            "default": "none"
          },
          "chartSize": {
            "title": "Chart positions to take",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "How many apps to take from the chart, from position 1 downwards. Ignored when 'Also watch a top chart' is 'none'.",
            "default": 25
          },
          "searchTerms": {
            "title": "Also watch App Store search results",
            "type": "array",
            "description": "Optional keywords, e.g. 'habit tracker'. The top App Store search results for each keyword in the first storefront are added to the watchlist. This is the fastest way to build a competitor set for an ASO keyword you care about.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxAppsPerSearchTerm": {
            "title": "Max apps per search term",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "How many search results to take per keyword. Ignored when no search terms are given.",
            "default": 25
          },
          "maxAppsPerRun": {
            "title": "Max app/storefront checks per run",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Hard cap on how many app-and-storefront pairs are checked - and charged as 'app-checked' - in a single run. 50 apps across 3 storefronts is 150 checks. Protects you from an accidental 200-app x 10-storefront watchlist. Apps you listed by hand are always checked before seeded ones.",
            "default": 200
          },
          "trackedFields": {
            "title": "Fields to treat as a change",
            "type": "array",
            "description": "Which listing fields produce a change event. 'Supported devices' is off by default because Apple adds new device models to nearly every app at the same time, which would bury the fields you actually care about.",
            "items": {
              "type": "string",
              "enum": [
                "title",
                "description",
                "version",
                "price",
                "icon",
                "screenshots",
                "genres",
                "minimumOs",
                "supportedDevices",
                "seller",
                "availability"
              ],
              "enumTitles": [
                "Title renamed",
                "Description edited (with word-level diff)",
                "New version shipped (with release notes)",
                "Price or currency changed",
                "Icon replaced",
                "Screenshots changed",
                "Category / genre moved",
                "Minimum iOS version raised or lowered",
                "Supported devices changed (noisy - off by default)",
                "Seller or developer name changed",
                "Delisted from a storefront / newly available in one"
              ]
            },
            "default": [
              "title",
              "description",
              "version",
              "price",
              "icon",
              "screenshots",
              "genres",
              "minimumOs",
              "seller",
              "availability"
            ]
          },
          "minDescriptionWordsChanged": {
            "title": "Minimum words changed to report a description edit",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Descriptions pick up small edits constantly. A description change is only reported when at least this many words were added or removed in total; smaller edits update the stored copy silently so the next real rewrite still diffs against what is published today. 1 reports every edit.",
            "default": 1
          },
          "storefrontLanguage": {
            "title": "Storefront language",
            "type": "string",
            "description": "Optional locale for the returned text, e.g. en_us, de_de, ja_jp. Leave empty to get each storefront's own default language. Changing this after the first run will make every localised field look edited once - turn on 'Reset stored state' for that run.",
            "default": ""
          },
          "maxChangeEvents": {
            "title": "Max change events per run",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on the number of change events returned and charged for in one run. A normal run on a stable watchlist returns single digits; this only matters on the run after you widen the watchlist.",
            "default": 500
          },
          "markDelistedAfterMisses": {
            "title": "Consecutive misses before reporting an app as delisted",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "The iTunes Lookup endpoint returns nothing for an app that is pulled from a storefront - and also, occasionally, for one that is simply having a bad minute. The actor waits for this many consecutive runs with the app missing before emitting a 'delisted' event, so a blip does not create a false alarm. Set to 1 to report immediately.",
            "default": 2
          },
          "includeBaselineRecords": {
            "title": "Emit a baseline record the first time an app is seen",
            "type": "boolean",
            "description": "The first run has nothing to compare against, so it cannot report changes. With this on, that run returns one 'baseline' record per app/storefront showing the listing as it stands now, so you can see the watchlist was picked up correctly. Baseline records are never charged as change events. Turn it off if you only ever want edits.",
            "default": true
          },
          "forceBaseline": {
            "title": "Reset stored state and re-baseline",
            "type": "boolean",
            "description": "Discards the remembered listing for every app in this run and treats them all as seen for the first time. Use after changing 'Storefront language', or to clear out state you no longer trust. Leave off for normal scheduled runs, otherwise the actor can never detect a change.",
            "default": false
          },
          "stateKeyValueStoreName": {
            "title": "State storage name",
            "type": "string",
            "description": "Name of the named key-value store holding the last-seen listing for each app and storefront. Runs sharing this name share a memory of the watchlist. Change it to run two independent watchlists side by side under one account.",
            "default": "app-store-change-feed-state"
          },
          "requestsPerMinute": {
            "title": "Requests per minute",
            "minimum": 1,
            "maximum": 60,
            "type": "integer",
            "description": "Apple rate-limits the iTunes Lookup endpoint at roughly 20 requests per minute per IP. Since one request carries up to 100 app IDs, the default of 18 is enough for a 1,800-app watchlist per minute. Lower it if you see HTTP 403 or 429 warnings.",
            "default": 18
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 120,
            "type": "integer",
            "description": "Per-request timeout for calls to Apple's lookup, search and chart endpoints.",
            "default": 30
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "How many times to retry a failing Apple request before giving up on it. A batch that fails every retry is skipped for the run - its apps are not charged for, and no delisting is inferred from the failure.",
            "default": 3
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional, and off by default so the actor is cheap to try. Apple's public endpoints do not IP-block, and batching keeps the request count low, so most watchlists never need a proxy. Turn it on if you run very large watchlists frequently and start seeing 403 or 429 warnings.",
            "default": {
              "useApifyProxy": false
            }
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}