API reference
The App Revs API is a REST API over Apple's public App Store data: keyword popularity and difficulty, search positions, genre charts, ratings, reviews, publishers, and the apps and keyword lists of your account. Requests go over HTTPS; requests and responses are JSON.
- Base URL:
https://api.apprevs.com/api/v1 - MCP server:
https://api.apprevs.com/mcp, whose tools call the endpoints below. See MCP server. - Markdown copy of this page:
https://raw.githubusercontent.com/onlyoneaman/ios-reviews/main/docs/API.md
Authentication
Endpoints marked Auth: none read stored data and need no credentials. Endpoints marked Auth: API key call the App Store live or touch your account.
- Sign in at
https://apprevs.com/with Google. - Open
https://apprevs.com/app/settingsand generate an API key. The key is shown once. - Send it in the
X-API-Keyheader.
X-API-Key: ar_live_your_api_key
The web app authenticates its own requests with a Firebase ID token in Authorization: Bearer <token>; do not send an API key that way. /users/* and /admin/* accept Firebase tokens only.
Errors
Errors use HTTP status codes and a JSON body with a single error string.
{ "error": "Keyword not analyzed in this store yet" }
| Status | Meaning |
|---|---|
400 |
A parameter is missing or invalid. |
401 |
No credentials on an endpoint that needs them. |
403 |
The credentials do not cover the resource (for example, an app your connected App Store Connect key does not sell). |
404 |
Nothing stored for that app, term, publisher or store. |
500 |
Something failed on our side. |
Successful responses carry "success": true. Health endpoints use status instead.
Rate limits
No rate limits are enforced. Live App Store lookups are cached server-side (12 hours for app records, 24 hours for reviews and storefront scans, a day for keyword analyses), so repeated calls for the same thing are cheap. Be reasonable, and keep keys out of client-side code.
Conventions
countryis a lowercase ISO 3166-1 alpha-2 storefront code (us,gb,de). It defaults touseverywhere.track_idis the numeric App Store id of an app (389801252is Instagram).artist_idis the numeric id of a publisher.- Popularity is Apple Ads' search popularity, 5 to 100, for the month; a term Apple reports at its floor is returned as
5. Difficulty is 0 to 100 from the rating counts of the ten apps ranking, and comes withdifficulty_inputs. positionis 1-based within the search results andnullwhen the app is not in the first 200.- Dates are ISO 8601. Days are
YYYY-MM-DD; months are the first day of the month. - All endpoints are
GETunless the heading says otherwise.
Keywords
GET /keywords/{term}
The stored analysis of one keyword in a store: popularity, difficulty and its inputs, result count, the top 10 apps, related head terms, and the position of app_id when given.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
term |
string | yes | The keyword, in the path (URL-encode spaces). |
country |
string | no | Storefront. Default us. |
app_id |
integer | no | An app whose position in the results to report. |
Returns 404 when the term was never analyzed in that store; GET /keywords/analyze does that.
curl "https://api.apprevs.com/api/v1/keywords/habit%20tracker?country=us"
{
"success": true,
"term": "habit tracker",
"store": "us",
"popularity": 61,
"ads_popularity": 52,
"popularity_genre": "PRODUCTIVITY_UTILITIES",
"rank_in_genre": 378,
"popularity_change_12m": -1,
"popularity_history": [ { "month": "2025-06-01", "popularity": 63, "rank_in_genre": 277 } ],
"difficulty": 69,
"difficulty_inputs": { "median_ratings": 13237, "top10_ratings": 1051713, "giants": 2, "title_match": 8, "fresh": 8 },
"result_count": 192,
"top_apps": [ { "id": 1438388363, "name": "Habit Tracker", "ratings": 146849, "avg": 4.8, "updated": "2026-09-10", "price": 0, "genre": "Productivity", "icon": "https://…", "developer": "…" } ],
"related_head_terms": [],
"branded": false,
"position": null,
"analyzed_at": "2026-09-17T20:05:56+00:00"
}
GET /keywords/analyze
Analyze up to 25 keywords now: one App Store search and one Apple Ads read per term. One analysis exists per keyword and store, shared by every caller and reused while under 24 hours old.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | yes | Comma-separated keywords, at most 25. |
country |
string | no | Storefront. Default us. |
app_id |
integer | no | An app whose position to report on each row. |
force |
boolean | no | true re-analyzes even when a fresh analysis exists. Default false. |
Each row carries popularity (the latest month's top-500 score, or null), ads_popularity (the current score for any term), last_seen (the last month and score the term was in a top 500, when it no longer is), popularity_history, difficulty, difficulty_inputs, position, result_count, top_apps, related_head_terms and analyzed_at.
curl "https://api.apprevs.com/api/v1/keywords/analyze?q=habit%20tracker,streaks&country=gb&app_id=6443918070" \
-H "X-API-Key: ar_live_your_api_key"
GET /keywords/{term}/history
Monthly popularity of one term across the genres it appears in.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
term |
string | yes | The keyword, in the path. |
country |
string | no | Storefront. Default us. |
period_type |
string | no | MONTHLY (default) or WEEKLY where weekly data is loaded. |
Returns periods (every month loaded for the store), count and data rows shaped like GET /most-searched, oldest first. A month missing from data means the term was not in any genre's top 500.
GET /most-searched
Apple Ads search popularity: the 500 most searched terms per genre and month, scored 5 to 100, for 90 storefronts with 15 months of history.
Auth: none (anonymous callers get at most 100 rows per request)
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. The response's stores lists the loaded ones. |
month |
string | no | YYYY-MM. Default: the latest month. |
genre |
string | no | One of BUSINESS, EDUCATION, ENTERTAINMENT, FINANCE, FOOD_DRINK, GAMES, HEALTH_FITNESS, LIFESTYLE, NEW_PUBLICATION, PHOTO_VIDEO, PRODUCTIVITY_UTILITIES, SHOPPING, SOCIAL_NETWORKING, SPORTS, TRAVEL. |
q |
string | no | Substring match on the term. |
min_popularity |
integer | no | Default 0. |
max_popularity |
integer | no | Default 100. |
period_type |
string | no | MONTHLY (default) or WEEKLY. |
limit |
integer | no | Default 1000, at most 5000. |
offset |
integer | no | Default 0. |
curl "https://api.apprevs.com/api/v1/most-searched?country=us&genre=HEALTH_FITNESS&limit=5"
{
"success": true,
"store": "us",
"period": "2026-08-01",
"period_type": "MONTHLY",
"pagination": { "current_page": 1, "total_pages": 100, "total_count": 500, "limit": 5, "offset": 0, "has_next_page": true, "has_prev_page": false, "next_page": 2, "prev_page": null },
"filters": { "genre": "HEALTH_FITNESS", "min_popularity": "0", "max_popularity": "100", "q": null },
"data": [
{ "text": "strava", "popularity": 77, "popularity_in_genre": 100, "popularity_1to5": 5, "rank_in_genre": 1, "genre": "HEALTH_FITNESS", "period_type": "MONTHLY", "month": "2026-08-01", "country": "us", "store": "us" }
]
}
A term outside a genre's top 500 is absent, which is not the same as zero demand.
Apps
GET /apps/search
Search the App Store live by name or keyword, in Apple's order. Nothing is stored.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | yes | The search. |
country |
string | no | Storefront. Default us. |
limit |
integer | no | Default 10, at most 50. |
curl "https://api.apprevs.com/api/v1/apps/search?q=instagram&country=us&limit=5" \
-H "X-API-Key: ar_live_your_api_key"
{
"success": true,
"query": "instagram",
"country": "us",
"count": 5,
"results": [
{
"trackId": 389801252,
"trackName": "Instagram",
"artistName": "Instagram, Inc.",
"averageUserRating": 4.7,
"userRatingCount": 27000000,
"primaryGenreName": "Photo & Video",
"price": 0,
"formattedPrice": "Free",
"version": "…",
"trackViewUrl": "https://apps.apple.com/us/app/…"
}
]
}
GET /apps/lookup/{track_id}
The full App Store record of one app: metadata, rating, count, version, release and update dates, description, screenshots. Cached for up to 12 hours and stored.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
force |
boolean | no | true bypasses the cache. Default false. |
Returns { "success": true, "app": { … }, "cached": <boolean> }. The record has the same shape either way; cached says whether it came from storage or from Apple just now.
curl "https://api.apprevs.com/api/v1/apps/lookup/389801252?country=us" \
-H "X-API-Key: ar_live_your_api_key"
GET /apps/storefront/{track_id}/{country}
The stored record of an app in a store: the same shape as a cached lookup. An app seen only in search results or charts has a thin record (name, icon, numbers; no description or screenshots).
Auth: none
Returns 404 when the app was never seen in that store.
GET /apps/{track_id}/storefronts
Rating and rating count for one app in the 46 largest storefronts, from the last scan (scanned_at, within 24 hours; the nightly job rescans apps requested in the last 14 days). total_ratings sums the stores; average_rating is the count-weighted average over the rated ones. Ratings and written reviews are separate on the App Store, so a store can show ratings here and return nothing from /reviews.
Auth: none to read; API key to rescan
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
force |
boolean | no | true rescans now (API key). Default false. |
curl "https://api.apprevs.com/api/v1/apps/6753146599/storefronts"
{
"success": true,
"track_id": 6753146599,
"scanned": 46,
"available": 45,
"rated": 15,
"total_ratings": 28,
"average_rating": 4.69,
"scanned_at": "2026-09-18T01:56:26+00:00",
"data": [
{ "country": "se", "rating": 4.75, "ratings": 4, "price": "Free", "version": "1.0.7" }
]
}
data is sorted by ratings descending and lists only stores where the app is available.
GET /apps/{track_id}/keywords
Every analyzed keyword whose search results include the app, best position first, and every genre chart it is on in the store.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
Each row in data: keyword, position, result_count, popularity, ads_popularity, difficulty, branded (the results are one brand's apps), own_name (the term shares a word with the brand part of this app's name), analyzed_at. Covers keywords analyzed by anyone for that store; analyses refresh nightly. scanned_at is when the name scan last completed for this store (or null) and scanning whether one is running. charts[] has every genre chart the app is on: label ("Top Free · Health & Fitness"), chart, genre, position, movement (places gained over the last week, negative for lost, null with under two days of data).
curl "https://api.apprevs.com/api/v1/apps/341232718/keywords?country=us"
POST /apps/{track_id}/keywords/scan
The name scan: up to 25 terms built from the app's name (its words and adjacent pairs, what Apple's search box suggests after each, and top-500 terms containing them), each analyzed unless already analyzed today. Recorded per app and store and not repeated for a week; apps in projects are rescanned weekly by the nightly job.
Auth: API key
Body:
| Field | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
force |
boolean | no | true scans even if one ran this week. Default false. |
wait |
boolean | no | true runs the scan inline and answers when done. Default false. |
A scan takes about a minute. Without wait the reply is 202 with scanning: true and what the app ranks for so far; poll GET /apps/{track_id}/keywords until scanning is false. With wait the reply carries candidates, scanned (terms analyzed this time) and error (a term Apple refused; the scan is then not recorded and retried on the next open).
curl -X POST "https://api.apprevs.com/api/v1/apps/6443918070/keywords/scan" \
-H "Content-Type: application/json" -H "X-API-Key: ar_live_your_api_key" \
-d '{ "country": "us", "wait": true }'
GET /apps/{track_id}/competitors
Apps sharing the top 100 with this app on the keywords it ranks for, most shared first.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
Each competitor: id, name, icon, ratings, avg, shared (keywords), ahead (keywords where it ranks above this app), keywords[] with theirs, ours and popularity. Derived from stored analyses: the name scan is what makes it non-empty for an app nobody has tracked, and tracking more keywords widens it. Carries the same scanned_at and scanning fields as /keywords.
GET /apps/{track_id}/overview
The app in one view, from stored data.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
Returns keywords (how many it ranks for, how many with demand, the best ones, terms whose demand is fading or rising), leader (the app it shares the most top-10s with, how often it is ahead, and gaps: keywords where the leader is top 3 and this app is outside the top 10), competitors, voice (what the leader's users complain about and like once someone has summarized its reviews; null until then), stores (the leader's ratings by store, this app's coverage and languages, and missing_languages: languages of stores holding 3% or more of the leader's ratings that this app does not ship), name_words (words the apps above it share in their names and this one lacks) and actions, next steps written from those facts.
GET /apps/{track_id}/charts
Every genre chart the app is on in any store read (top free, paid and grossing, 25 genres, the 20 largest stores, nightly), best position first: country, chart, genre, label, position, movement (places gained over the last week).
Auth: none
GET /apps/{track_id}/positions
Where the app stands in search per store, from stores where it was checked on purpose (its name scan ran there, or the store's head table is seeded). Per store: checked (terms analyzed), top10 (searched terms above Apple's floor it is in the top 10 of), top10_generic (those that are a search for a kind of app rather than a brand) and best, the headline term (keyword, position, popularity, own_name, branded): the most searched generic one, else another brand's name it sits beside, else its own name. A store with no qualifying term is left out. Project apps are scanned in the 20 chart stores weekly.
Auth: none
GET /apps/{track_id}/rating-history
Rating and rating count by day for an app in a store, with its written reviews per day and its releases.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
days |
integer | no | Default 30, at most 365. |
Returns the daily rows, reviews[] (per day: day, reviews, positive for 4 and 5 stars, negative for 1 and 2, as far back as the review feed reached when the app's reviews were last read) and releases[] (version, released_at, notes), which includes versions known only from reviews, dated by their first review.
GET /apps/{track_id}/changes
The app's listing timeline in one store, newest first: field (version with its release notes in detail when the app was opened here, price, name, description as a hash, screenshots, languages, min_os, size), day, value. An app is observed by every search, chart and lookup it appears in, so the timeline exists for apps nobody opened.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
GET /apps/{track_id}/countries
Every store where App Revs holds a record of the app.
Auth: none
{ "success": true, "track_id": 389801252, "countries": ["us", "gb", "in"] }
Reviews
GET /apps/{track_id}/reviews
Written reviews for an app from the App Store feed, with a rating summary. Served from the last read for 24 hours; a signed-in caller's request also runs a read when the last is over a day old, and the nightly job re-reads apps opened in the last 14 days. A visitor gets 404 when no read has run yet.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
track_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
limit |
integer | no | Reviews requested. Default 490; the read stops at the limit or when the feed ends. |
curl "https://api.apprevs.com/api/v1/apps/389801252/reviews?country=us&limit=200" \
-H "X-API-Key: ar_live_your_api_key"
{
"success": true,
"app_id": "389801252",
"app_name": "Instagram",
"reviews": [
{ "rating": 5, "title": "…", "content": "…", "author": "…", "version": "…", "review_date": "…" }
],
"summary": {
"total_reviews": 200,
"average_rating": 4.31,
"rating_distribution": { "5": 120, "4": 30, "3": 20, "2": 10, "1": 20 }
}
}
GET /apps/{track_id}/reviews/summary
The star split of the written reviews stored for the app in a store (the latest 490 someone read): count, positive (4 and 5 stars), neutral, negative (1 and 2), newest, fetched_at.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
Returns 404 when none are stored.
GET /apps/{track_id}/insights
The most recent stored AI summary of an app's reviews. A read of stored data; nothing is generated.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
model |
string | no | Default: the newest summary for the app, whatever the model. |
Returns 404 when none exists.
POST /apps/research
Generate a summary of a set of reviews with an LLM and store it, attributed to your account.
Auth: API key
Body:
| Field | Type | Required | Description |
|---|---|---|---|
app_name |
string | yes | |
track_id |
integer | yes | |
reviews |
array | yes | Objects with rating, title, content. |
country |
string | no | Default us. |
model |
string | no | Default gemini-3.8-flash; also gemini-3.5-flash-lite, gemini-3.1-pro-preview. |
Returns sentiment, top likes and dislikes, improvement suggestions and an executive summary.
curl -X POST "https://api.apprevs.com/api/v1/apps/research" \
-H "Content-Type: application/json" -H "X-API-Key: ar_live_your_api_key" \
-d '{ "app_name": "Instagram", "track_id": 389801252, "country": "us", "reviews": [ { "rating": 2, "title": "…", "content": "…" } ] }'
GET /apps/insights/recent
The summaries generated by your account, newest first.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | no | Default 20, at most 50. |
Publishers
GET /developers/{artist_id}
A publisher and every app they sell in a store, most rated first, from Apple's own developer record (re-read when over a day old) plus what App Revs keeps per app.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
artist_id |
integer | yes | In the path. |
country |
string | no | Storefront. Default us. |
Returns artist (id, name, seller_name, seller_url, view_url), count, total_ratings, gained_7d (across apps followed daily) and apps[] with id, name, icon, genre, price, rating, ratings, released, updated, version, gained_7d, chart (best genre chart place). 404 when the publisher is unknown in that store.
POST /developers/{artist_id}/claim
Mark a publisher as yours: every app in Apple's record of it becomes a project (role mine) and new ones follow nightly.
Auth: API key
Body: { "country": "us" } (optional). DELETE on the same path undoes the claim; the projects stay.
GET /me/developers
Your claims, with Apple's record of each publisher.
Auth: API key
GET /me/asc, POST /me/asc, DELETE /me/asc/{id}
App Store Connect API keys connected to your account. POST with { "issuer_id", "key_id", "private_key", "country"? } checks the key by listing the team's apps, stores it, and claims every publisher those apps belong to as verified. GET lists connections (never the key itself) with label, capabilities (apps, analytics), status (ok, or invalid once Apple refuses it) and last_used_at. DELETE forgets one. Every key is re-checked nightly: the team's apps re-listed (new apps become your projects), permissions re-probed, a refused key marked invalid.
Auth: API key
GET /apps/{track_id}/owner
What only the owner sees, through a connected key whose team sells the app: pipeline (the live version, every version's state, the latest builds with their marketing version) and metadata (name and subtitle per locale, the live version's keyword field with each term's position and demand, top-10 terms with demand the field lacks, field terms wasted on words already in the name, what's new, promotional text).
Auth: API key; 403 without a key that covers the app
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
Store
GET /apps/new
Apps released in the last days that already sit in a head term's top 200 or on a genre chart in the store, most rated first. A release date in the future is a pre-order and is left out.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
days |
integer | no | Default 30, at most 180. |
genre |
integer | no | Apple genre id, for example 6013 for Health & Fitness. |
limit |
integer | no | Default 50, at most 200. |
Each app: id, name, icon, developer, genre, released, ratings, avg, price, lists (how many searches and charts it appears in) and best (the best place it holds: kind, key, label, position, popularity).
GET /apps/rising
Apps gaining ratings fastest in a store, from the nightly counts: fastest growth per day first. Counts exist for the apps on the US charts, every followed app and every app in their top 10s.
Auth: none
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Storefront. Default us. |
days |
integer | no | Default 7, at most 90. |
genre |
integer | no | Apple genre id. |
exclude_genre |
integer | no | Apple genre id to leave out, for example 6014 for games. |
launched |
integer | no | Only apps released in the last N days, at most 730. |
min_gain |
integer | no | At least this many new ratings. Default 20. |
limit |
integer | no | Default 50, at most 200. |
Each app: the first and last counted day inside the window, before (the first count), gained, pct (of before, null when it was 0), from_day, to_day, span_days.
GET /storefronts
Every storefront and what is read for it: popularity_month (latest month of Apple Ads popularity, null for stores without a table), charts (nightly genre charts), ratings_scan (in the 46-store scan), default_language, additional_languages. Cached an hour.
Auth: none
GET /localizations
Default and additional metadata languages for every App Store storefront, keyed by storefront code, plus the sorted languages list and updated date. Cached a day.
Auth: none
Benchmarks
App-economics benchmarks by category, country and region: acquisition cost (Apple Search Ads), store conversion, subscription funnel, lifetime value, retention and ad rates. Static reference data, cached a day.
GET /benchmarks
The full dataset in one payload: categories, countries, regions, and the acquisition, storeConversion, subscriptions, monetization and retention reference tables, plus an updated date.
Auth: none
curl "https://api.apprevs.com/api/v1/benchmarks"
GET /benchmarks/categories
One row per app category with every metric merged: cptUs, cpiUs, cpaUs, convUs, installToTrial, trialToPaid, installToPaid, installLtv12mo, rpiD14, ltvPayerY1, priceMonthly, iapPayerRate, subsOnly, storeCvr, rating, d30, sessionLen, iosD1 and more. null where a figure isn't reliably published for that category.
Auth: none
GET /benchmarks/countries
Apple Search Ads cost across 42 markets: cpt, cpi, cpa, ttr, cr (tap→install), cpm.
Auth: none
GET /benchmarks/regions
Subscription funnel for six regions: rpiD14, rpiD60, installToTrial, trialToPaid, installToPaid, ltvPayer12mo, trialLtvLift, plan mix and refund.
Auth: none
Projects
A project is one of your apps (track_id set; positions are computed for it) or an idea with no app yet. Keyword lists belong to a project. A project's id is an opaque 10-character string ("5xswnyqkkl"), the same one in web app URLs.
GET /projects
Your projects. Each carries keyword_counts per store, free-text notes and its role (mine, competitor, or null for ideas).
Auth: API key
POST /projects
Follow an app or start an idea.
Auth: API key
Body:
| Field | Type | Required | Description |
|---|---|---|---|
track_id |
integer | one of | An App Store app. Returns the existing project if you already have it. |
name |
string | one of | An idea with no app. |
country |
string | no | Default store. |
role |
string | no | For an app: mine (default) or competitor. |
GET /projects/{id}, PATCH /projects/{id}, DELETE /projects/{id}
One project. PATCH takes name, country, notes and role.
Auth: API key
POST /projects/{id}/keywords/copy
Copy every keyword, in every store, to another of your projects, for example from an idea to the app once it ships.
Auth: API key
Body: { "to": "<project id>" }.
GET /projects/{id}/suggestions
Keywords the project's app ranks for that are not on its list, from everything analyzed for the store.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Default: the project's store. |
track_id |
integer | no | Look at another app, such as a competitor; the only way an idea gets suggestions. |
GET /projects/{id}/keywords/{term}
One keyword across every store the project tracks it in, most searched first: country, popularity, ads_popularity, difficulty, result_count, position (of the project's app), analyzed_at.
Auth: API key
Keyword lists
GET /keywords/tracked
A project's keyword list for one store, with each term's analysis.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string | yes | |
country |
string | no | Default: the project's store. |
days |
integer | no | The window for visibility. Default 7. |
Rows for an app project include position and position_history (one point per day). The response also carries releases (the app's version history in the store), popularity_tracked (false when the store has no monthly popularity table, so rows carry the current score only) and, for an app project, visibility: score is the sum over the list of popularity times a weight for the app's position (1 at #1, 0.75 at #2, 0.21 at #10, 0.12 to #20, 0.05 to #50, 0.02 beyond, 0 unranked); before is the same sum at the positions of days ago at today's popularity, so delta and delta_pct move only when ranks move; up, down and measured count keywords that rose, fell and had a point that old.
POST /keywords/tracked
Add keywords to a project's list in a store. Saves them and returns their analysis (reused when under a day old unless force). They are checked nightly from then on.
Auth: API key
Body:
| Field | Type | Required | Description |
|---|---|---|---|
project_id |
string | yes | |
keywords |
array of strings | yes | |
country |
string | no | Default: the project's store. |
force |
boolean | no | true re-analyzes. Default false. |
curl -X POST "https://api.apprevs.com/api/v1/keywords/tracked" \
-H "Content-Type: application/json" -H "X-API-Key: ar_live_your_api_key" \
-d '{ "project_id": "5xswnyqkkl", "keywords": ["habit tracker", "streaks"], "country": "us" }'
DELETE /keywords/tracked/{id}
Remove one keyword from a list.
Auth: API key
Account
GET /me/week
This week for every app you follow, yours first.
Auth: API key
| Parameter | Type | Required | Description |
|---|---|---|---|
days |
integer | no | Default 7, at most 30. |
Each app: ratings (gained in the window and the window before, plus total and average), charts and keywords (lists where its position moved: key, from, to, change), changes (releases and listing changes in the window), reviews (the written-review split of the last 30 days), best_chart, last_release, keyword_count (its list in the store), ranked (terms it ranks for among everything analyzed for the store, and how many in the top10) and visibility (the same score as GET /keywords/tracked, over every ranked term, with before, delta and delta_pct).
Site build
Endpoints the static site is built from. Anonymous; stored data only. /apps/storefront/all and /sitemap/apps answer with an encoded body ({ "d": "…" }) rather than plain JSON.
GET /apps/storefront/all
The (track_id, country) pairs that get a static page: every app someone opened plus, in stores whose head table is seeded, the 1,200 apps holding the most top-10 slots.
GET /sitemap/apps
App URL data for the sitemap.
GET /public/keyword-pages
Everything the public keyword pages need for a store in one response: every head term analyzed (the latest month's top 500 per genre, about 7,500 for the US) with slug, popularity, popularity_history, difficulty, difficulty_inputs, result_count, related_head_terms, top_apps (10, from the apps' own rows), branded, analyzed_at. Tens of megabytes for the US; cached an hour.
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Default us. |
GET /public/app-rankings
For every app with a static page in a store, the head terms it ranks for within the first 50 results, keyed by track id. Cached an hour.
| Parameter | Type | Required | Description |
|---|---|---|---|
country |
string | no | Default us. |
{ "success": true, "store": "us", "count": 1236,
"data": { "341232718": [ { "term": "calorie tracker", "position": 1, "popularity": 71 } ] } }
Health
GET /ping
Liveness. Returns { "status": "success", "message": "pong" }.
GET /health
Health with the running version.
GET /apps/health
Health of the app data path.
Client errors
POST /errors
A browser reports a render error. Anonymous or signed in (the user is attached). Always answers 202; reports beyond sixty a minute are dropped without being stored.
Body: { "message", "stack"?, "path"?, "scope"? }.