API reference
One base URL, one key, JSON in and out. Every endpoint below is also an MCP tool with the same name.
openapi.json · Error codes · MCP server
Base URL
https://storelift.net/v1
Every path below is relative to it. Send GET for reads and POST only on /actions.
Authentication
Send the key in Authorization: Bearer <key> or in x-api-key. Create keys under Settings › API; each key carries scopes, an optional IP allow list, an optional app list and an optional monthly credit budget. A key that reaches its budget answers 402 key_budget_reached until the month turns; the other keys keep working.
Live keys (sl_live_) for the REST API are on Pro and above, or on any plan with a credit pack. Free includes one live key that works on the MCP server only. Test keys (sl_test_) return the sandbox data on every plan. Assistants sign in over OAuth through the MCP server on every plan.
Credits and limits
Each call costs the credits listed on it; /account and /usage cost 0, and a write's preview costs 0. Every response carries x-credits-used, x-credits-limit, x-credits-remaining and x-credits-reset.
Requests per second are set per plan; past it you get 429 rate_limited with retry-after. Hive endpoints open with purchased API credits or with Hive Explorer and also count against a daily allowance: 500 calls on pack credits, 10,000 with Hive Explorer. Credits per call
Sandbox
https://storelift.net/v1/sandbox answers every read below that has a sample response, with no key and no credits. The data is fixed and dated, so tests stay stable.
Test keys (sl_test_) return the same data on the live base URL and never write.
Reading a rank
A rank has three states and they stay distinct: measured: false means the query was not measured that day, rank: null means it was measured and the app is outside the results read, and a number is the rank.
Errors
Every error has the same body: { "error": "<code>", "message": "…", "docs": "…" }. error is stable; branch on it, not on message. Some codes add fields such as scope, field or limit. All error codes
Worked examples
Three jobs, from the first call to the result you keep. Every command runs against the sandbox, so it spends no credits and changes nothing, and each response is what the sandbox returns for it.
With your own key the paths are the same without /sandbox and each call costs the credits listed on it. A test key (sl_test_) answers with the sandbox data there too, at 0 credits.
Add this week's keyword ranks to a report
Read one app's keywords in one storefront and keep a single row. Run it weekly and the rows line up into a trend.
Find the app id.
curl "https://storelift.net/v1/sandbox/apps"Response
Read every tracked keyword of that app in the storefront.
curl "https://storelift.net/v1/sandbox/apps/sbx-lumen/keywords?country=us"Response (keywords: 2 of 8 rows)
Fold the answer into the row you store. A keyword with measured: true and rank: null was measured and the app is absent from the results; it is counted apart from a keyword that was not measured.
function weeklyRow(body) {
const ranked = body.keywords.filter((k) => k.measured && k.rank !== null);
const best = ranked.reduce((a, b) => (a && a.rank <= b.rank ? a : b), null);
return {
measuredAt: body.measuredAt,
country: body.country,
platform: body.platform,
keywords: body.keywords.length,
ranked: ranked.length,
absent: body.keywords.filter((k) => k.measured && k.rank === null).length,
notMeasured: body.keywords.filter((k) => !k.measured).length,
best: best && { term: best.term, rank: best.rank },
};
}Result
{
"measuredAt": "2026-09-27T02:10:00.000Z",
"country": "us",
"platform": "ios",
"keywords": 8,
"ranked": 6,
"absent": 2,
"notMeasured": 0,
"best": {
"term": "nature sounds",
"rank": 29
}
}An app id the workspace does not have answers 404:
curl "https://storelift.net/v1/sandbox/apps/sbx-unknown/keywords?country=us"{
"error": "not_found",
"message": "No such app in this workspace.",
"docs": "https://storelift.net/docs/api/errors#not_found"
}Ask who ranks above you
The same data through the MCP server: the assistant makes two tool calls. To send them by hand, put a test key in STORELIFT_TEST_KEY.
list_appsreturns the app id.curl "https://storelift.net/mcp" \ -H "Authorization: Bearer $STORELIFT_TEST_KEY" \ -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_apps","arguments":{}}}'Response
get_rivalsreturns the apps ranking above it, keyword by keyword.curl "https://storelift.net/mcp" \ -H "Authorization: Bearer $STORELIFT_TEST_KEY" \ -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_rivals","arguments":{"appId":"sbx-lumen","country":"us"}}}'Response (rivals: 2 of 3 rows)
What the answer says, rival by rival. ourRank: null is a keyword the app is absent from.
function rivalsAhead(body) {
return body.rivals.map((r) => ({
name: r.name,
ratings: r.ratings,
aheadOn: r.terms.length,
absentOn: r.terms.filter((t) => t.ourRank === null).length,
}));
}Result
[
{
"name": "Calm Rain",
"ratings": 57046,
"aheadOn": 8,
"absentOn": 2
},
{
"name": "Noisli",
"ratings": 16114,
"aheadOn": 8,
"absentOn": 2
},
{
"name": "Deep Sleep Tones",
"ratings": 64683,
"aheadOn": 8,
"absentOn": 2
}
]An app id the workspace does not have comes back as a tool error the assistant can read, not as a failed request:
curl "https://storelift.net/mcp" \
-H "Authorization: Bearer $STORELIFT_TEST_KEY" \
-H "content-type: application/json" \
-d '{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"get_rivals","arguments":{"appId":"sbx-unknown","country":"us"}}}'ERROR: No such app in this workspace.See what a credential can read, over HTTP or MCP
The first call of any integration: which plan, which scopes, which apps and how many credits are left. GET /account and the whoami tool return the same body, and neither costs credits.
Over HTTP.
curl "https://storelift.net/v1/sandbox/account"Response
The same answer as a tool call.
curl "https://storelift.net/mcp" \ -H "Authorization: Bearer $STORELIFT_TEST_KEY" \ -H "content-type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'Response
Check the scope a call needs before you make it, and read the balance before a batch.
function allowance(body) {
return {
plan: body.plan,
auth: body.auth,
scopes: body.scopes,
apps: body.apps.map((a) => a.id),
creditsLeft: body.credits.limit - body.credits.used,
ratePerSecond: body.ratePerSecond,
};
}Result
{
"plan": "studio",
"auth": "test_key",
"scopes": [
"apps:read",
"reviews:read",
"ai:read",
"revenue:read",
"hive:read",
"hive:spy",
"hive:estimate",
"ads:read"
],
"apps": [
"sbx-lumen",
"sbx-quill"
],
"creditsLeft": 50000,
"ratePerSecond": 10
}Without credentials the MCP endpoint answers 401 with a JSON-RPC error, and a client that supports MCP authorization starts the OAuth sign-in from it:
curl "https://storelift.net/mcp" \
-H "content-type: application/json" \
-d '{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'{
"jsonrpc": "2.0",
"id": 9,
"error": {
"code": -32001,
"message": "No credentials were sent. Sign in with OAuth on any plan, or add Authorization: Bearer <your Storelift API key>. Live keys require Pro, Studio, Enterprise, or an eligible Free account with purchased API credits or active Explorer. Tool access still depends on plan, scopes and credits. Generate a key at Storelift → Settings → API keys."
}
}Common parameters
These read the same on every endpoint that takes them; each endpoint lists the ones it takes.
| Parameter | In | Type | Description |
|---|---|---|---|
appId | path | string | app id from list_apps |
country | query | string | country code, e.g. tr, us (defaults to the app's first country) |
platform | query | ios | android | defaults to ios |
country | query | string | storefront code, e.g. us (defaults to us) |
Account
The key's own plan, scopes and usage, the account search and the alert feed. Reading plan and usage costs 0 credits.
- GET
/alertsThe alert feed of this workspace — rank drops and rises, keywords entering or leaving the results, rivals… - GET
/portfolioToday across every app in the workspace, one row per app: live users, users and new users, ad revenue,… - GET
/accountWho this key or session belongs to: plan, how it authenticated, the scopes it carries, the apps it may… - GET
/usageEvery quota of the workspace with what is used and the reset time: tracked keywords, apps, discovery, AI… - GET
/searchSearch this account's own records — app names and store ids, tracked keywords, and the rival apps that… - GET
/fetchThe full record behind one id from search: an app card, one tracked keyword with its current state and…
Your apps
The apps this workspace tracks: ranks, rivals, reviews, store page, listing timeline, featuring, charts and listing checks.
- GET
/appsList the apps tracked in this Storelift account (id, name, countries, keywords) - GET
/apps/{appId}/keywordsKeyword ranks for one app in one App Store / Google Play country - GET
/apps/{appId}/rivalsApps that rank ABOVE this app in search - GET
/apps/{appId}/aiApp mentions in a dated sample of AI engine answers; this does not reproduce what ChatGPT, Claude or… - GET
/apps/{appId}/ai-checkStart an AI visibility sample for one app in one country, with the engines available for the run - GET
/apps/{appId}/historyKeyword rank history for one country - GET
/apps/{appId}/pageThe app's own store listing signals for one country (name and subtitle are not included): version, in-app… - GET
/apps/{appId}/reviewsRecent reviews for one country: `list` holds the App Store reviews, `android` the Google Play reviews (a… - GET
/apps/{appId}/chartsApp Store chart position for one country: current ranks per list (free / paid / grossing, overall and in… - GET
/apps/{appId}/reviews/searchSearch one app's reviews in one storefront by text, star rating, app version and date range, newest first… - GET
/apps/{appId}/reviews/statsStar-rating distribution, average and share of 1–2 star reviews for one app in one storefront, plus a… - GET
/apps/{appId}/reviews/summaryReview AI for one app in one storefront: a summary of the recent reviews and the themes in them —… - GET
/apps/{appId}/reviews/reply-draftA developer reply draft for one review, in the storefront's language - GET
/apps/{appId}/timelineDated changes to one app's listing — new version, screenshots, in-app events, featuring from the store… - GET
/apps/{appId}/todayOne app's day in one answer — the Today screen: purchases, trials and renewals from the connected sources,… - GET
/apps/{appId}/competitionHow many apps compete on each keyword in one storefront, returned for terms seen on two or more apps - GET
/apps/{appId}/rivals/{rivalId}One rival of your app in one storefront: its name, rating and rating count with a 90-day history of them… - GET
/apps/{appId}/rivals/{rivalId}/adnetworksHow a rival monetises with ads: the ad networks it works with, each marked DIRECT or RESELLER - GET
/apps/{appId}/rivals/{rivalId}/marketA rival's market in one storefront: on Google Play the exact install count and in-app purchase price… - GET
/apps/{appId}/storefront-auditYour iOS listing in every App Store storefront: where the app is sold, which storefronts serve the… - GET
/apps/{appId}/suggestNew keyword ideas for one app in one storefront, written in that storefront's search language: terms of… - POST
/apps/{appId}/validate-listingCheck a draft App Store listing before it goes to App Store Connect - GET
/apps/{appId}/draftA listing draft — title, subtitle, promotional text and description — built from the keywords measured for… - GET
/apps/{appId}/localizeWrite the full App Store listing for a new locale — name, subtitle, keyword field and description — from… - GET
/apps/{appId}/shot-textThe caption text on your first four App Store screenshots in one storefront - GET
/apps/{appId}/chart-moversWho moved in the app's own category chart: risers and fallers (3+ places), new entrants and drop-outs,… - GET
/apps/{appId}/featuringWhere Apple shows the app today, per country: editorial cards (dedicated: true when the story is about… - GET
/apps/{appId}One tracked app with its platform ids, countries, tracked keywords per country and the latest measurement… - GET
/apps/{appId}/weekly-planThis week's listing suggestions for the app — the same list as the dashboard's "This week" card, best first
Revenue & Apple Ads
The connected sources per app: revenue, subscription events, the App Store funnel, prices and offer codes, the before/after of a change, and Apple Ads campaigns, keywords, search terms and commands. Scopes revenue:read and ads:read.
- GET
/apps/{appId}/revenueRevenue and downloads for one app from the sources the user connected: App Store Connect daily units per… - GET
/apps/{appId}/subscriptionsSubscription event counts for one app from the RevenueCat / Adapty webhook: per day and per country —… - GET
/apps/{appId}/funnelThe App Store conversion funnel for one app from App Store Connect analytics: impressions → product page… - GET
/apps/{appId}/campaignsApple Ads campaigns that promote one app (matched by the app's App Store id, not by name): spend,… - GET
/apps/{appId}/ads-keywordsEvery Apple Ads keyword bought for one app across its campaigns (last 28 days), by spend: bid, match type,… - GET
/apps/{appId}/ads-search-termsThe searches people actually typed that triggered the app's Apple Ads (last 28 days), by spend: the search… - GET
/apps/{appId}/ads-commandsApple Ads commands for one app's campaigns — from the dashboard, from automation rules and from… - GET
/apps/{appId}/search-popularityApple's own search popularity, from the Apple Ads account connected to this workspace: the most searched… - GET
/apps/{appId}/pricingProduct prices and offer codes for one app from the RevenueCat or Adapty webhook, over the last 365 days:… - GET
/apps/{appId}/country-pricesCountry prices for one of the app's products, read from App Store Connect / Google Play (Pro): per country… - GET
/apps/{appId}/change-impactWhat a change did: for one change day (a new version, screenshots, subtitle, keyword field, a campaign…
Hive
Any app or market the Storelift network measures, whether you track it or not. Part of Hive Explorer.
- GET
/rank-checkThe live rank of one of your apps for any search term in one storefront, as the store shows it right now —… - GET
/keyword-difficultyDemand and difficulty inputs for one App Store search term in one storefront: its demand (`demand`) and… - GET
/hive/findFind apps across the top charts we measure: filter by category, storefront, chart (Top Grossing, Top Free,… - GET
/hive/chartsOne top chart as we last measured it: the ranked app ids for a storefront, list kind and optional… - GET
/hive/moversWho climbed, who fell, who entered and who left one top chart, against the same chart N days ago - GET
/hive/newApps seen on a top chart for the first time, newest first, with the publisher behind each one - GET
/hive/publisher/{publisherId}Every app of one publisher that we have seen on a chart, with the day each was first seen - GET
/hive/resolveFind any app's id: by name or developer (the top matches in that storefront, with publisher, category,… - GET
/hive/similar/{appId}The store's own similar-apps shelf for any app (Apple's You Might Also Like, Google's Similar apps), in… - GET
/hive/reviews/{appId}Any app's recent reviews in one storefront, newest first: stars, title, text, version and date, plus the… - POST
/hive/keywords/{term}/metrics/measureStart a measurement of one keyword's popularity and/or difficulty in one storefront when the stored value… - GET
/hive/apps/{id}Any app's latest daily measurement - GET
/hive/keywords/{term}/ranksWho ranks for a keyword, day by day - GET
/hive/keywords/{term}/metricsRead a keyword's current popularity and difficulty - GET
/hive/keywords/{term}/metrics/historyRead stored keyword metric observations over time - GET
/hive/spy/{id}The keywords any app ranks for - GET
/hive/estimate/{id}Revenue and downloads for any app - GET
/hive/gapKeyword gap across several apps - GET
/hive/researchKeyword research from a seed term - GET
/hive/landscapeWhat it takes to rank in a category
Writes
Every write runs in two steps: a preview that changes nothing, then a confirm with the token it returned.
- GET
/jobs/{jobId}Status of a long-running job started by a confirmed action (Apple Ads command, review reply, listing… - POST
/actionsPreview a write - POST
/actions/confirmApply a previewed write