App Store catalog

The catalog endpoints expose Ranksy's view of the public Shopify App Store — the same scraped data that powers the public site, not your team's private partner metrics. GET /api/v1/shopify/apps searches and lists the whole catalog; GET /api/v1/categories/:handle returns one category (with optional review insights); and GET /api/v1/categories/:handle/rankings returns the scraped ranked apps inside a category. These are cross-app — you can read any app or category in the store, not just your own.


GET/api/v1/shopify/apps

Search the catalog

List and filter the Shopify App Store catalog. This is a standard offset-paginated collection — data plus a meta block (total, current_page, last_page, per_page) — not the object: "list" envelope used by series endpoints. Each row is a full catalog app.

Query parameters

  • Name
    page
    Type
    integer
    Description

    Page to return. 1-based, default 1.

  • Name
    per_page
    Type
    integer
    Description

    Rows per page. Minimum 1, maximum 1000.

  • Name
    state
    Type
    string
    Description

    Filter by listing state: Active, Delisted, or Deleted.

  • Name
    category
    Type
    string
    Description

    Restrict to apps in a category, by category handle (e.g. store-management).

  • Name
    min_installs
    Type
    integer
    Description

    Only apps with at least this many estimated installs. Minimum 0.

  • Name
    updated_since
    Type
    string
    Description

    ISO 8601 date-time. Only apps whose catalog record changed at or after this instant.

Request

GET
/api/v1/shopify/apps
curl -G https://ranksyapp.com/api/v1/shopify/apps \
  -H "Authorization: Bearer rk_live_..." \
  -d category=store-management \
  -d state=Active \
  -d min_installs=500 \
  -d per_page=2

Response

{
  "data": [
    {
      "id": "48213.acme-reviews",
      "token": "acme-reviews",
      "platform": "shopify",
      "name": "Acme Reviews",
      "description": "Collect and display product reviews.",
      "state": "Active",
      "categories": ["store-management", "marketing"],
      "plans": [
        { "name": "Free", "monthly_cost_cents": 0 },
        { "name": "Pro", "monthly_cost_cents": 1999 }
      ],
      "installs": 12840,
      "installs_30d": null,
      "installs_90d": null,
      "review_count": 1284,
      "reviews_30d": null,
      "reviews_90d": null,
      "average_rating": 4.9,
      "vendor_name": "Acme Labs",
      "vendor_email": null,
      "vendor_website": "https://acmelabs.io",
      "app_store_url": "https://apps.shopify.com/acme-reviews",
      "icon_url": "https://cdn.shopify.com/.../icon.png",
      "created_at": "2023-04-11T00:00:00+00:00",
      "free_trial_days": 14
    }
  ],
  "meta": {
    "total": 1820,
    "current_page": 1,
    "last_page": 910,
    "per_page": 2
  }
}

GET/api/v1/categories/:handle

Retrieve a category

A single App Store category, addressed by its handle (slug). The response is a single-object envelope (object: "category") carrying category meta — slug, name, apps_count — plus a review-insight payload selected by insight_type.

The default overview payload adds stats, rating_distribution, and sentiment_distribution. The complaints and features variants replace those with their own keys (pain points / missing features, common / loved features); the overview-only keys are then omitted entirely.

Path parameter

  • Name
    handle
    Type
    string
    Description

    The category slug, e.g. store-management. Unknown / untracked handles return a 404 resource_not_found.

Query parameters

  • Name
    insight_type
    Type
    string
    Description

    Which insight payload to attach: overview (default — rating + sentiment distributions), complaints (pain points / missing features), or features (common + loved features).

Request

GET
/api/v1/categories/:handle
curl https://ranksyapp.com/api/v1/categories/store-management \
  -H "Authorization: Bearer rk_live_..."

Response (overview)

{
  "object": "category",
  "slug": "store-management",
  "name": "Store management",
  "apps_count": 1820,
  "insight_type": "overview",
  "stats": {
    "total_reviews": 184203,
    "average_rating": 4.6
  },
  "rating_distribution": [
    { "rating": 5, "count": 142018, "percentage": 77.1 },
    { "rating": 4, "count": 21884, "percentage": 11.9 }
  ],
  "sentiment_distribution": [
    { "sentiment": "positive", "count": 151204, "percentage": 82.1 },
    { "sentiment": "negative", "count": 12940, "percentage": 7.0 }
  ]
}

GET/api/v1/categories/:handle/rankings

Category rankings

The scraped ranked apps within a category — App Store category rank plus the movement since the previous scrape, one ranking row per app. Returned as the object: "list" envelope. The underlying scrape is top-50: that slice is fetched once and paginated client-side, so total_count never exceeds 50.

The category summary, the scrape source / data_date, the echoed sort, and a category block (slug, name, total_apps) ride in the envelope metadata. There is no coverage block — catalog lists are not date-windowed.

Path parameter

  • Name
    handle
    Type
    string
    Description

    The category slug, e.g. store-management. Unknown / untracked handles return a 404 resource_not_found.

Query parameters

  • Name
    sort
    Type
    string
    Description

    Ordering: rank (scraped category rank ascending — the default), rating (descending), or reviews (descending).

  • Name
    page
    Type
    integer
    Description

    Page to return. 1-based, default 1.

  • Name
    per_page
    Type
    integer
    Description

    Rows per page. Minimum 1, maximum 50.

Request

GET
/api/v1/categories/:handle/rankings
curl -G https://ranksyapp.com/api/v1/categories/store-management/rankings \
  -H "Authorization: Bearer rk_live_..." \
  -d sort=rank \
  -d per_page=2

Response

{
  "object": "list",
  "url": "/api/v1/categories/store-management/rankings",
  "page": 1,
  "per_page": 2,
  "total_count": 50,
  "has_more": true,
  "metadata": {
    "source": "scraped",
    "data_date": "2026-05-29",
    "sort": "rank",
    "category": {
      "slug": "store-management",
      "name": "Store management",
      "total_apps": 1820
    },
    "summary": {}
  },
  "data": [
    {
      "rank": 1,
      "change": 0,
      "app": {
        "slug": "acme-reviews",
        "name": "Acme Reviews",
        "rating": 4.9,
        "reviews_count": 1284,
        "developer": "Acme Labs",
        "built_for_shopify": true
      }
    },
    {
      "rank": 2,
      "change": 1,
      "app": {
        "slug": "bolt-bulk-editor",
        "name": "Bolt Bulk Editor",
        "rating": 4.8,
        "reviews_count": 932,
        "developer": "Bolt Apps",
        "built_for_shopify": false
      }
    }
  ]
}

Response shapes

Catalog app

A row of GET /shopify/apps. Cross-app public catalog data; the installs_30d / installs_90d / reviews_30d / reviews_90d / vendor_email fields are reserved and always null in v1.

  • Name
    id
    Type
    string
    Description

    Stable catalog id, {numericId}.{slug} (e.g. 48213.acme-reviews).

  • Name
    token
    Type
    string
    Description

    The app's App Store slug.

  • Name
    platform
    Type
    string
    Description

    Always "shopify".

  • Name
    name
    Type
    string | null
    Description

    Listing name.

  • Name
    description
    Type
    string | null
    Description

    The listing introduction / tagline.

  • Name
    state
    Type
    string
    Description

    Listing state: Active, Delisted, or Deleted.

  • Name
    categories
    Type
    string[]
    Description

    Category handles this app is listed under. Present only when expanded.

  • Name
    plans
    Type
    array
    Description

    Pricing plans, sorted by display order: each { name, monthly_cost_cents }. Present only when expanded.

  • Name
    installs
    Type
    integer | null
    Description

    Estimated total installs.

  • Name
    review_count
    Type
    integer
    Description

    Total review count.

  • Name
    average_rating
    Type
    number | null
    Description

    Average star rating, rounded to one decimal.

  • Name
    vendor_name
    Type
    string | null
    Description

    Developer name. Present only when expanded.

  • Name
    vendor_website
    Type
    string | null
    Description

    Developer website. Present only when expanded.

  • Name
    app_store_url
    Type
    string
    Description

    Canonical App Store listing URL.

  • Name
    icon_url
    Type
    string
    Description

    App icon URL.

  • Name
    created_at
    Type
    string | null
    Description

    Listing launch date, ISO 8601.

  • Name
    free_trial_days
    Type
    integer | null
    Description

    Longest free-trial length across the app's plans, or null. Present only when plans are expanded.

Category (object: "category")

The single-object response of GET /categories/:handle. The head is always present; the trailing three keys appear only for insight_type=overview.

  • Name
    object
    Type
    string
    Description

    Always "category".

  • Name
    slug
    Type
    string
    Description

    The category slug (the :handle path param).

  • Name
    name
    Type
    string
    Description

    Human-readable category name.

  • Name
    apps_count
    Type
    integer
    Description

    Number of apps listed in this category.

  • Name
    insight_type
    Type
    string
    Description

    Which insight payload this response carries: overview, complaints, or features.

  • Name
    stats
    Type
    object
    Description

    Overview only. Aggregate review stats: { total_reviews, average_rating }.

  • Name
    rating_distribution
    Type
    array
    Description

    Overview only. Review count + share per star rating, 5 down to 1: { rating, count, percentage }.

  • Name
    sentiment_distribution
    Type
    array
    Description

    Overview only. Review count + share per sentiment bucket (positive, neutral, mixed, negative): { sentiment, count, percentage }.

Ranking row

One row of GET /categories/:handle/rankings.

  • Name
    rank
    Type
    integer
    Description

    The app's scraped rank within this category for the latest data date.

  • Name
    change
    Type
    integer
    Description

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

  • Name
    app
    Type
    object
    Description

    Card for the ranked app: { slug, name, rating, reviews_count, developer, built_for_shopify }.


Errors

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

  • 404 resource_not_found — on categories/:handle and categories/:handle/rankings only: the addressed category does not exist or is not tracked (inactive categories 404 too). error.param is handle. The catalog search (/shopify/apps) never 404s — an over-filtered query returns an empty data array instead.

Catalog endpoints never read a Shopify Partner integration, so they never return a 409.

Was this page helpful?