{
  "openapi": "3.0.1",
  "info": {
    "title": "ASO Keyword Rank Tracker & Monitor - Google Play & App Store",
    "description": "See where apps rank in App Store and Google Play search, in the order each store's own search page shows them. Track your app's keyword rank across countries, get a row when it is not in the results, and use monitoring mode to be told only when a rank moves.",
    "version": "0.1",
    "x-build-id": "RVE9we7rdmCJGf4g3"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/neverempty~app-store-keyword-rank-tracker/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-neverempty-app-store-keyword-rank-tracker",
        "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/neverempty~app-store-keyword-rank-tracker/runs": {
      "post": {
        "operationId": "runs-sync-neverempty-app-store-keyword-rank-tracker",
        "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/neverempty~app-store-keyword-rank-tracker/run-sync": {
      "post": {
        "operationId": "run-sync-neverempty-app-store-keyword-rank-tracker",
        "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": {
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Search terms to look up, one per line (commas also separate them). Each keyword is searched in every store and country you pick. A repeated keyword (same words, any letter case) is searched once and gets a free 'duplicate' row. If you leave this field out with monitoring off, the example keyword 'habit tracker' is searched; with monitoring on it is required. An empty list is rejected. Up to 200 keywords per run.",
            "items": {
              "type": "string"
            }
          },
          "apps": {
            "title": "Apps to track (leave empty to list every app shown)",
            "type": "array",
            "description": "Your app and competitors: a Google Play package name (com.example.app) or URL (https://play.google.com/store/apps/details?id=com.example.app), an App Store id (389801252) or URL (https://apps.apple.com/us/app/instagram/id389801252). A dotted id is looked up both as a Google Play package and as an App Store bundle id. With apps listed you get one row per app per search, including a row that says 'not-in-shown-results' when the app is not on the search page. With the list empty you get one row for every app the search page shows. If the list has entries but none of them is an app id or store URL, the run stops without searching. A store none of your apps can be looked up in is not searched. Up to 50 apps.",
            "items": {
              "type": "string"
            }
          },
          "stores": {
            "title": "Stores",
            "type": "array",
            "description": "Which stores to search. Google Play: the order of play.google.com search (about 10 to 50 apps per search, depending on the keyword). App Store: the order of Apple's App Store search page on apps.apple.com (about 11 or 12 apps per search).",
            "items": {
              "type": "string",
              "enum": [
                "googlePlay",
                "appStore"
              ],
              "enumTitles": [
                "Google Play",
                "App Store"
              ]
            },
            "default": [
              "googlePlay",
              "appStore"
            ]
          },
          "countries": {
            "title": "Countries",
            "type": "array",
            "description": "Two-letter country codes (us, gb, de, jp, br, ...). Every keyword is searched in every country listed, in one run. Rankings differ by country. A country code the store rejects (Google Play answers some codes with an error, and Apple sends unknown codes to its US store) comes back as a free 'country-not-available' row. Google Play still shows a search page for some countries where it is not offered (for example cn), and those positions are returned as shown. Up to 50 countries.",
            "default": [
              "us"
            ],
            "items": {
              "type": "string"
            }
          },
          "language": {
            "title": "Google Play language",
            "type": "string",
            "description": "The language Google Play is asked to show the search in (en, ja, de, pt-BR, ...). It changes the order of Google Play results, so use the language your users search in. Google Play shows English for a language it does not know; every row says which language the page was shown in (languageShown). The App Store search is shown in the storefront's own language and does not use this field.",
            "default": "en"
          },
          "maxResults": {
            "title": "Maximum rows to return",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "With monitoring off, the run stops once this many charged rows have been returned, and a free row says how many rows and searches were left out. In monitoring mode it does not limit the changes returned: every search is checked, as far as the run's maximum total charge allows.",
            "default": 1000
          },
          "monitoringMode": {
            "title": "Monitoring mode: return an app only when its rank changes",
            "type": "boolean",
            "description": "Needs at least one app in 'Apps to track'. Off = every tracked app comes back with its current position, charged per row. On = the Actor remembers each app's position for each keyword, store and country and, on later runs, returns a row only when the position changed, the app entered the search page or left it, with the previous position and the positions gained. A change is only reported, and a first position only remembered, if a second read of the page a few seconds later shows the same position. The first run returns every pair once to set the baseline. **In monitoring mode every app checked on a search costs $0.30 per 1,000 checks, changed or not** (searches that could not be read are free), plus the row price for the rows returned. Example: 20 keywords in both stores for one app, checked every hour = 28,800 checks a month = $8.64. Positions are remembered per app, keyword, store and country; do not put the same pairs in two schedules that can run at the same time.",
            "default": false
          },
          "resetMonitoringState": {
            "title": "Forget what was remembered and start over",
            "type": "boolean",
            "description": "Clears every remembered position for this Actor, so the next monitoring run returns each pair once again as a first check. This affects all your monitoring runs. Turn it off again after one run: left on in a schedule, every run returns every pair as a first check and charges the row price for it.",
            "default": false
          },
          "useProxy": {
            "title": "Use a proxy if a store answers with a bot check",
            "type": "boolean",
            "description": "Every search page is requested directly first. Only if a store answers with a bot check, an empty response or no response is that page retried through a proxy session; the next page is requested directly again. The country of the results comes from the country you pick, not from where the request comes from. With it off, that answer is retried directly and then returned as a free 'blocked' row, and no proxy is paid for.",
            "default": true
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}