Running a Shopify store?Bestappify for merchants

For developers

API & MCP reference

Everything BestAppify knows about your apps is available over HTTP, and over MCP so Claude and Cursor can query it for you. Same data, same numbers as the dashboard — it all reads from one layer.

Authentication

Create a key in Dashboard → API & MCP and send it as a bearer token. Keys are shown once and stored only as a hash, so if you lose one, create another. X-API-Key works too, if a header called Authorization is awkward where you are.

curl -H "Authorization: Bearer ba_live_xxx" \
  https://bestappify.app/api/v1/apps

A key can read everything on your account, including revenue. Keep it server-side.

Responses

Every success is { data, meta } and every failure is { error: { code, message } }. Branch on code, not on the message — codes are stable, wording is not.

{
  "data": {
    "app": { "app": "fast-bundle", "name": "FBP | Fast Bundle Product", "app_id": 6174 },
    "keywords": [
      {
        "keyword": "product bundles",
        "keyword_id": 31,
        "position": 12,
        "last_known_position": 12,
        "previous_position": 17,
        "change": 5,
        "as_of": "2026-07-28",
        "is_current": true,
        "difficulty": 68,
        "competition": 41,
        "demand": 73
      }
    ]
  },
  "meta": { "generated_at": "2026-07-28T09:14:22.031Z", "count": 1 }
}

Three habits worth knowing, because they run through the whole API. A position of null means the app was not in the search results we captured — not that it has no rank. is_current: false means the rank history matched to your app lags the newest crawl, usually by a day, when a crawl saw the listing before matching it to our catalog — position is still the live figure. And where a number is reconstructed rather than reported (MRR, churn, trials, keyword demand), the response says so rather than presenting it as Shopify's own.

Rate limits

120 requests per minute and 10,000 per day, per key. Every response carries X-RateLimit-Remaining; a 429 carries Retry-After in seconds. MCP tool calls draw on the same allowance.

MCP server

One endpoint — https://bestappify.app/api/mcp — over streamable HTTP, authenticated with the same key. Fourteen read-only tools: your apps, keyword rankings and history, opportunities, competitors and overlap, review intelligence, listing analytics, revenue and churn, plus catalog search, app details, the leaderboard, movers and niches.

Claude Code

claude mcp add --transport http bestappify https://bestappify.app/api/mcp \
  --header "Authorization: Bearer ba_live_xxx"

Cursor — ~/.cursor/mcp.json

{
  "mcpServers": {
    "bestappify": {
      "url": "https://bestappify.app/api/mcp",
      "headers": { "Authorization": "Bearer ba_live_xxx" }
    }
  }
}

Claude Desktop — claude_desktop_config.json

Claude Desktop's custom connectors expect OAuth, so a key-authenticated server goes through mcp-remote, which adds the header for you.

{
  "mcpServers": {
    "bestappify": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://bestappify.app/api/mcp",
               "--header", "Authorization: Bearer ba_live_xxx"]
    }
  }
}

Then ask things like

  • “Which of my keywords dropped this week, and who took the position?”
  • “Compare my review complaints with my three closest competitors.”
  • “What did churn do after the pricing change in March?”
  • “Find categories with fewer than 40 apps where the leader holds under half the reviews.”

Endpoints

Base URL https://bestappify.app. Every {app} accepts the handle, the listing URL, or an id from /api/v1/apps.

Account

GET/api/v1/me

Your account, apps and rate limits

Confirms the key works and returns the app references every other endpoint accepts, plus how much of your rate limit you have used.

GET /api/v1/me

Your apps

GET/api/v1/apps

List your tracked apps

Every app on your account. The `app` field is the handle used in the paths below; `tracked_app_id` and `app_id` are returned for callers that prefer ids.

GET /api/v1/apps

GET/api/v1/apps/{app}/keywords

Keyword rankings

Your tracked keywords for one app with today's position, the week-over-week change, and the difficulty, competition and demand indices. `position` is the live standing and is null when the app did not appear in the latest crawl. `last_known_position` and `change` come from the rank history keyed to your app in our catalog; `is_current: false` means that history is a little behind the newest crawl, not that the app stopped ranking.

app
(path, required) App handle, listing URL, tracked_app_id or app_id.

GET /api/v1/apps/fast-bundle/keywords

GET/api/v1/apps/{app}/keywords/{keyword}

One keyword, with full rank history

Daily rank history for a single tracked keyword, oldest first, plus its current standing. `{keyword}` is the term (URL-encoded) or its keyword_id.

app
(path, required) App handle or id.
keyword
(path, required) Keyword term, URL-encoded, or its keyword_id.

GET /api/v1/apps/fast-bundle/keywords/product%20bundles

GET/api/v1/apps/{app}/opportunities

Keyword opportunities

Keywords one of your tracked competitors ranks for and this app does not, with the competitor's position.

app
(path, required) App handle or id.

GET /api/v1/apps/fast-bundle/opportunities

GET/api/v1/apps/{app}/competitors

Competitors and keyword overlap

Your tracked competitor set with current rank and rank change, plus the keyword overlap matrix showing where each of you places.

app
(path, required) App handle or id.
include
(query, optional) Set to `timeline` to also return the daily rank timeline for every app.

GET /api/v1/apps/fast-bundle/competitors

GET/api/v1/apps/{app}/reviews

Review intelligence

Rating distribution, monthly review trend, countries, the AI theme analysis (what merchants love, complain about and ask for) and a comparison against your tracked competitors.

app
(path, required) App handle or id.
recent
(query, optional) How many individual recent reviews to include. Default 10, max 50.

GET /api/v1/apps/fast-bundle/reviews?recent=25

GET/api/v1/apps/{app}/analytics

Listing analytics

Listing views, install clicks, installs, click-through and conversion from the Google Analytics property linked to the app, daily and totalled. Returns `connected: false` when no property is linked.

app
(path, required) App handle or id.
days
(query, optional) Window in days. Default 90, max 365.

GET /api/v1/apps/fast-bundle/analytics?days=30

GET/api/v1/apps/{app}/revenue

Revenue and churn

Monthly MRR, churn rate, trials, installs, uninstalls and net revenue from the Shopify Partner API. MRR and churn are derived from the subscription charge lifecycle — the Partner API publishes neither directly. Returns `connected: false` when the app is not linked to a Partner app.

app
(path, required) App handle or id.
months
(query, optional) Months of history. Default 12, max 36.

GET /api/v1/apps/fast-bundle/revenue?months=24

GET/api/v1/apps/{app}/intelligence

App intelligence

Rank trajectory over time, position in each category, nearest competitors by category rank, and how the app's entry price compares with its peers.

app
(path, required) App handle or id.

GET /api/v1/apps/fast-bundle/intelligence

Market data

GET/api/v1/market/apps

Search the App Store catalog

Search every app we hold by name — not only your own. This is how you find a competitor's handle before looking it up.

q
(query, required) Search term matched against the app name.
limit
(query, optional) Results to return. Default 20, max 50.

GET /api/v1/market/apps?q=bundle

GET/api/v1/market/apps/{app}

One catalog app

Any app in our catalog by handle, listing URL or id: rating, review count, description, categories, pricing plans and listing status.

app
(path, required) App handle, listing URL or id.
include
(query, optional) Set to `intelligence` to add rank trajectory and the pricing benchmark.

GET /api/v1/market/apps/judge-me-reviews?include=intelligence

GET/api/v1/market/leaderboard

Top apps by review volume

The App Store leaderboard, overall or for one category. Ranked by review count, because Shopify publishes no install numbers.

category
(query, optional) Category id or exact title. Omit for the overall board.
limit
(query, optional) Apps to return. Default 25, max 100.

GET /api/v1/market/leaderboard?category=Product%20bundles

GET/api/v1/market/movers

Week-over-week rank movement

Which apps climbed and which fell over the last week, from our daily rank snapshots. `change` is positive for a climb; `rank_a_week_ago: null` marks an app new to the ranking.

category
(query, optional) Category id or exact title.
limit
(query, optional) Apps to return. Default 25, max 100.

GET /api/v1/market/movers

GET/api/v1/market/niches

Category growth and concentration

Every category with its app count, growth and the leader's share of reviews — for judging whether a niche is crowded or open.

limit
(query, optional) Categories to return. Default 30, max 100.

GET /api/v1/market/niches

GET/api/v1/market/categories

List categories

The App Store categories we hold at least five apps for, with counts. These ids and titles are what `?category=` accepts.

GET /api/v1/market/categories

Error codes

CodeHTTPMeaning
missing_api_key401No Authorization header or X-API-Key header was sent.
invalid_api_key401The key does not exist or has been revoked.
rate_limited429More than 120 requests in the last minute. Retry-After says when to try again.
daily_limit_reached429More than 10,000 requests in the last 24 hours.
app_not_found404The app reference is not one of your tracked apps.
keyword_not_tracked404That keyword is not tracked for the given app.
category_not_found404No category matched the id or title given.
missing_query400A required query parameter was absent.
app_not_in_catalog409The app is tracked but our crawler has not matched it to a listing yet.
service_unavailable503The API is misconfigured or the database is unreachable. Safe to retry.
internal_error500An unexpected failure on our side.

Ready to pull your data?

Keys take a few seconds to create, and the same one drives the API and the MCP server.

Create an API key