Reviews
A single endpoint returns the app's Shopify App Store reviews as a paginated object: "list" — GET /api/v1/apps/:app/reviews. Each row is one review (rating, body, reviewing store, developer reply); the envelope's metadata carries a summary (total + average + star distribution) and echoes back the filters you sent. Filter by rating, has_reply, or a start_date/end_date window, and sort by date or rating. Reviews Shopify has purged from the listing are held back by default — ask for them with include_archived=true.
Reviews are a scraped surface, stored from the public App Store listing — there is no Shopify Partner integration involved, so this endpoint never returns a 409. Freshness depends on the last scrape, and a missing field (body, author, country, usage_duration, review_date) comes back as null rather than being dropped.
App Store reviews
Returns the app's stored App Store reviews, newest first by default. The list is true-paginated — total_count is the count after filters, and has_more tells you when to fetch the next page. The envelope's metadata.summary is computed over the filtered set (so filtering to rating=1 gives you the 1-star total and average), and metadata.filters echoes the parameters that were applied. There is no date gate — reviews are always available for a tracked app.
Path parameter
- Name
app- Type
- string
- Description
The team app's ULID, e.g.
01JN4HKQX0000000000000000.
Query parameters
- Name
rating- Type
- integer
- Description
Filter to a single star rating,
1–5. Out-of-range values return a422.
- Name
has_reply- Type
- boolean
- Description
Filter by whether the developer has replied. Accepts
true/false/1/0/yes/no.
- Name
start_date- Type
- string
- Description
YYYY-MM-DD. Only reviews posted on or after this date.
- Name
end_date- Type
- string
- Description
YYYY-MM-DD. Only reviews posted on or before this date. Must be greater than or equal tostart_date.
- Name
sort- Type
- string
- Description
Sort column:
date(default) orrating. Any other value returns a422.
- Name
order- Type
- string
- Description
Sort direction:
desc(default) orasc.
- Name
page- Type
- integer
- Description
The page to return. Default
1.
- Name
per_page- Type
- integer
- Description
Reviews per page. Default
25, maximum100.
- Name
include_archived- Type
- boolean
- Description
When
true, the response also carries anarchivedblock undermetadata(its ownsummary+reviews) holding the app's purged reviews — ones Shopify removed from the public listing, which Ranksy keeps on record. Archived reviews are never mixed into the primarydatalist or itssummary, so your totals and averages stay identical with the flag on or off. Acceptstrue/false/1/0/yes/no.
Request
curl -G https://ranksyapp.com/api/v1/apps/01JN4HKQX0000000000000000/reviews \
-H "Authorization: Bearer rk_live_..." \
-d rating=5 \
-d has_reply=true \
-d sort=date \
-d order=desc \
-d per_page=25
Response
{
"object": "list",
"url": "/api/v1/apps/01JN4HKQX0000000000000000/reviews",
"page": 1,
"per_page": 25,
"total_count": 128,
"has_more": true,
"metadata": {
"summary": {
"total_reviews": 128,
"avg_rating": 4.72,
"rating_distribution": { "5": 104, "4": 14, "3": 5, "2": 2, "1": 3 }
},
"filters": {
"rating": 5,
"has_reply": true,
"start_date": null,
"end_date": null,
"sort": "date",
"order": "desc"
}
},
"data": [
{
"id": "123456789",
"rating": 5,
"body": "Works exactly as described and support is fast.",
"author": "Acme Store",
"store_name": "Acme Store",
"country": "US",
"usage_duration": "About 1 year",
"review_date": "2026-05-01",
"has_reply": true,
"reply": "Thanks for the kind words — glad it helped!",
"reply_date": "2026-05-02"
},
{
"id": "123456788",
"rating": 5,
"body": null,
"author": null,
"store_name": null,
"country": "GB",
"usage_duration": "3 months",
"review_date": "2026-04-28",
"has_reply": false,
"reply": null,
"reply_date": null
}
]
}
Response shapes
The list envelope is the shared catalog object: "list" shape; each item in data is a review row. Reviews are not a date-windowed series, so coverage and currency are not present.
List envelope (object: "list")
- Name
object- Type
- string
- Description
Always
"list".
- Name
url- Type
- string
- Description
The endpoint path for this resource.
- Name
page- Type
- integer
- Description
The current page number (1-based).
- Name
per_page- Type
- integer
- Description
Reviews per page.
- Name
total_count- Type
- integer
- Description
Total reviews across all pages, after filters.
- Name
has_more- Type
- boolean
- Description
Whether further pages exist.
- Name
metadata- Type
- object
- Description
Carries
summary(total_reviews,avg_rating,rating_distributionkeyed5→1, all over the filtered set) andfilters(the rating / reply / date / sort parameters that were applied). Withinclude_archived=trueit also carries anarchivedblock (summary+reviews) covering purged reviews — see Archived (purged) reviews.
- Name
data- Type
- array
- Description
The review rows for this page.
Review row
- Name
id- Type
- string
- Description
Shopify review id, e.g.
"123456789".
- Name
rating- Type
- integer
- Description
Star rating the merchant left,
1–5.
- Name
body- Type
- string
- Description
Review text, or
nullwhen the merchant left only a rating.
- Name
author- Type
- string
- Description
Reviewing store name, or
nullwhen not captured.
- Name
store_name- Type
- string
- Description
Reviewing store name (same value as
author);nullwhen not captured.
- Name
country- Type
- string
- Description
Two-letter country code of the reviewing store, or
nullwhen unknown.
- Name
usage_duration- Type
- string
- Description
How long the merchant had used the app when reviewing (e.g.
"About 1 year"), ornullwhen unknown.
- Name
review_date- Type
- string
- Description
Date the review was posted (
YYYY-MM-DD), ornullwhen unknown.
- Name
has_reply- Type
- boolean
- Description
Whether the developer has replied to this review.
- Name
reply- Type
- string
- Description
Developer reply text, or
nullwhen there is none.
- Name
reply_date- Type
- string
- Description
Date of the developer reply (
YYYY-MM-DD), ornullwhen there is no reply.
Archived (purged) reviews
Shopify sometimes purges reviews from an app's public listing — the merchant deletes theirs, the reviewing store closes, or Shopify removes it. When that happens the review vanishes from the App Store, but Ranksy keeps the original on record and marks it archived.
Archived reviews are excluded from this endpoint by default: they are absent from data, from total_count, and from every figure in metadata.summary. That is deliberate — it keeps the API's numbers identical to the ones on your Ranksy dashboard.
Pass include_archived=true to get them back as their own labeled set:
Request
curl -G https://ranksyapp.com/api/v1/apps/01JN4HKQX0000000000000000/reviews \
-H "Authorization: Bearer rk_live_..." \
-d include_archived=true
The purged set arrives under metadata.archived, never merged into data:
Response (truncated)
{
"object": "list",
"total_count": 128,
"metadata": {
"summary": {
"total_reviews": 128,
"avg_rating": 4.72,
"rating_distribution": { "5": 104, "4": 14, "3": 5, "2": 2, "1": 3 }
},
"filters": { "rating": null, "has_reply": null, "start_date": null, "end_date": null, "sort": "date", "order": "desc" },
"archived": {
"summary": {
"total_reviews": 4,
"avg_rating": 1.75,
"rating_distribution": { "5": 0, "4": 0, "3": 1, "2": 0, "1": 3 }
},
"reviews": [
{
"id": "123456700",
"rating": 1,
"body": "Stopped syncing after the update.",
"author": "Acme Store",
"store_name": "Acme Store",
"country": "US",
"usage_duration": "5 months",
"review_date": "2026-03-14",
"has_reply": false,
"reply": null,
"reply_date": null
}
]
}
},
"data": []
}
- Name
metadata.archived.summary- Type
- object
- Description
Same shape as
metadata.summary(total_reviews,avg_rating,rating_distribution), computed over the purged set alone.
- Name
metadata.archived.reviews- Type
- array
- Description
The purged reviews, same review row shape as
data. Yourrating,has_reply,start_date,end_date,sort, andorderparameters apply to this set too.
metadata.archived.reviews is not paginated — the flag returns every purged review matching your filters in one block, and page / per_page / has_more / total_count continue to describe the primary data list only.
Pagination
The list is paginated. Use page and per_page (default 25, max 100) to walk the result set, and check has_more / total_count to know when to stop. total_count and the metadata.summary are computed after your filters, so paging never changes them within a single filtered query.
Errors
Beyond the universal 401 / 403 / 422 / 429 (see Errors), this endpoint adds nothing. There is no 409 — reviews are a scraped surface, not a Partner-integration metric — and no 400, since sort is whitelisted (date / rating): an unknown sort token, an out-of-range rating, or a bad date surfaces as 422 validation_failed.