Rankings

Two endpoints expose an app's App Store search position. GET /apps/:app/rankings returns a current snapshot of the latest scraped day across keyword and/or category surfaces; GET /apps/:app/rankings/history returns the rank series for one keyword or one category over a trailing window. Both are paginated lists (object: "list"); the row carries rank, change, and the keyword/category it belongs to.


Current rankings

A snapshot of the app's current scraped ranks on the latest scraped day. Each row is a keyword rank or a category rank; type chooses which surface(s) to return. Keyword rows carry keyword + is_sponsored; category rows carry category. A rank of 0 means the app was not found in the scraped results for that term. The snapshot is not date-windowed, so the envelope has no coverage block.

Path parameter

  • Name
    app
    Type
    string
    Description

    The team app's ULID, e.g. 01JN4HKQX0000000000000000.

Query parameters

  • Name
    type
    Type
    string
    Description

    Which ranking surface to return: all (default — both), keywords, or categories.

  • Name
    limit
    Type
    integer
    Description

    Rows to return. Default 20, minimum 1, maximum 50.

Request

GET
/api/v1/apps/:app/rankings
curl -G https://ranksyapp.com/api/v1/apps/01JN4HKQX0000000000000000/rankings \
  -H "Authorization: Bearer rk_live_..." \
  -d type=keywords \
  -d limit=20

Response

{
  "object": "list",
  "url": "/api/v1/apps/01JN4HKQX0000000000000000/rankings",
  "page": 1,
  "per_page": 20,
  "total_count": 2,
  "has_more": false,
  "metadata": { "summary": { "tracked_keywords": 2 } },
  "data": [
    {
      "rank": 7,
      "change": 2,
      "date": "2026-05-29",
      "category": null,
      "keyword": { "slug": "product-reviews", "keyword": "product reviews" },
      "app": { "slug": "acme-reviews", "name": "Acme Reviews" },
      "is_sponsored": false
    },
    {
      "rank": 0,
      "change": 0,
      "date": "2026-05-29",
      "category": null,
      "keyword": { "slug": "loyalty-rewards", "keyword": "loyalty rewards" },
      "app": { "slug": "acme-reviews", "name": "Acme Reviews" },
      "is_sponsored": null
    }
  ]
}

Ranking history

The rank series for one keyword or one category over a trailing window (scraped). type selects the surface; the term is then identified by name (the keyword string, or the category name) or — for categories — a category slug. Each point carries the scraped rank, the change vs the previous observation, and — for keyword history only — the page and is_sponsored. Points carry their own dates inline, so the envelope has no coverage block.

Path parameter

  • Name
    app
    Type
    string
    Description

    The team app's ULID, e.g. 01JN4HKQX0000000000000000.

Query parameters

  • Name
    type
    Type
    string
    Description

    Required. keyword or category — which surface the history is for.

  • Name
    name
    Type
    string
    Description

    The keyword string, or — for type=category — the category name (fuzzy-matched). Required when type=keyword. For type=category it is required unless a category slug is supplied.

  • Name
    category
    Type
    string
    Description

    A category slug (clean DX), e.g. store-management. Used for type=category as an alternative to name.

  • Name
    days
    Type
    integer
    Description

    Trailing window length in days. Default 30, minimum 1, maximum 90.

Request

GET
/api/v1/apps/:app/rankings/history
curl -G https://ranksyapp.com/api/v1/apps/01JN4HKQX0000000000000000/rankings/history \
  -H "Authorization: Bearer rk_live_..." \
  -d type=keyword \
  -d name="product reviews" \
  -d days=30

Response

{
  "object": "list",
  "url": "/api/v1/apps/01JN4HKQX0000000000000000/rankings/history",
  "page": 1,
  "per_page": 30,
  "total_count": 2,
  "has_more": false,
  "metadata": {
    "type": "keyword",
    "keyword": { "slug": "product-reviews", "keyword": "product reviews" }
  },
  "data": [
    { "date": "2026-05-28", "rank": 9, "page": 1, "change": null, "is_sponsored": false },
    { "date": "2026-05-29", "rank": 7, "page": 1, "change": 2, "is_sponsored": false }
  ]
}

Response shapes

Both endpoints return the standard object: "list" envelope. The currency and coverage keys exist on the envelope but are not used here — rankings are not money and not date-windowed, so they are omitted.

Ranking row

A row in the /rankings snapshot. The category and keyword cards are mutually exclusive per row; is_sponsored rides only on keyword rows.

  • Name
    rank
    Type
    integer
    Description

    Current scraped rank for this keyword/category. 0 means the app was not found in the scraped results for this term.

  • Name
    change
    Type
    integer
    Description

    Rank movement vs the previous scrape (positive = improved toward #1); 0 when there is no prior data point.

  • Name
    date
    Type
    string | null
    Description

    Date this rank was scraped (YYYY-MM-DD), or null when unknown.

  • Name
    category
    Type
    object | null
    Description

    { slug, name } for the category this rank belongs to; present only for category rows (type=categories), otherwise null.

  • Name
    keyword
    Type
    object | null
    Description

    { slug, keyword } for the keyword this rank belongs to; present only for keyword rows (type=keywords|all), otherwise null.

  • Name
    app
    Type
    object | null
    Description

    { slug, name } card for the ranked app; present only when the app relation is resolved on the row, otherwise null.

  • Name
    is_sponsored
    Type
    boolean | null
    Description

    Whether this keyword rank is a sponsored (ad) placement; present only on keyword rows, otherwise null.

History point

A point in the /rankings/history series. page and is_sponsored are present only for keyword history (type=keyword); category history omits them.

  • Name
    date
    Type
    string
    Description

    Date of this rank observation (YYYY-MM-DD).

  • Name
    rank
    Type
    integer | null
    Description

    Scraped rank on this date. 0 means the app was not found for this term on that day; null when the rank was not captured.

  • Name
    page
    Type
    integer | null
    Description

    Search-results page the app appeared on for this date; keyword history only, otherwise null.

  • Name
    change
    Type
    integer | null
    Description

    Rank movement vs the previous observation (positive = improved toward #1); null when there is no prior data point.

  • Name
    is_sponsored
    Type
    boolean | null
    Description

    Whether this keyword rank was a sponsored (ad) placement; keyword history only, otherwise null.


Errors

Beyond the universal 401 / 403 / 422 / 429 (see Errors), the rankings endpoints return:

  • 404 resource_not_found — on /rankings/history only: the addressed app, keyword, or category does not exist or is not tracked. /rankings instead returns an empty data list when nothing is tracked, so it never 404s.
  • 422 validation_failed — a bad query parameter. On /rankings/history, type is required, and name is required when type=keyword (or name/category for type=category).

These surfaces are scraped, not Partner-fed, so they never return the 409 that the metric endpoints do.

Was this page helpful?