Apps
The Apps resource is the entry point to everything else in the API: GET /api/v1/apps lists the apps your team tracks (a paginated object: "list"), and GET /api/v1/apps/:app returns a single-app overview — listing facts, categories, which integrations are connected, and the latest Partner metrics snapshot. The app's ULID from either response is the :app you pass to the metrics, rankings, reviews, and other per-app endpoints.
Apps are team-scoped: every key only ever sees the apps tracked by its own team, and addressing an app outside that team returns a 404 (resource_not_found), not a 403. Unlike the metrics endpoints, neither call requires a connected Partner integration — an app with no integrations still lists, with its integrations flags false and its metrics block null.
List apps
Returns the team's tracked apps as a paginated list of app rows. Filtering and sorting use Spatie QueryBuilder filter[...] and sort syntax; an unknown filter or sort key is rejected with a 400 (not 422).
Query parameters
- Name
filter[name]- Type
- string
- Description
Case-insensitive partial match on the App Store listing name. Max 255 chars.
- Name
filter[status]- Type
- string
- Description
Exact match on listing status (e.g.
published). Max 50 chars.
- Name
filter[built_for_shopify]- Type
- boolean
- Description
Restrict to apps that do (
true) or do not (false) carry the Built for Shopify badge.
- Name
sort- Type
- string
- Description
A sortable field, optionally prefixed with
-for descending (e.g.sort=-name). Max 50 chars. Unknown fields return a400.
- Name
page- Type
- integer
- Description
The page to return. Default
1.
- Name
per_page- Type
- integer
- Description
Rows per page. Default
25, maximum200.
Not date-windowed, so the response carries no coverage block and no currency.
Request
curl -G https://ranksyapp.com/api/v1/apps \
-H "Authorization: Bearer rk_live_..." \
-d "filter[built_for_shopify]=true" \
-d sort=-name \
-d per_page=25
Response
{
"object": "list",
"url": "/api/v1/apps",
"page": 1,
"per_page": 25,
"total_count": 3,
"has_more": false,
"data": [
{
"object": "app",
"ulid": "01JN4HKQX0000000000000000",
"slug": "my-app",
"name": "My App",
"listing": {
"rating": 4.8,
"reviews_count": 1240,
"built_for_shopify": true,
"status": "published",
"developer": "Acme Inc.",
"launched_at": "2024-03-15",
"url": "https://apps.shopify.com/my-app"
},
"integrations": {
"partner_api": true,
"analytics": false,
"app_store": true
},
"last_synced": {
"partner_api": "2026-05-29T03:14:00+00:00",
"analytics": null
}
}
]
}
Retrieve an app
Returns a single-app overview: everything in an app row plus a richer detail block — the listing's subtitle / introduction, the App Store categories, the latest Partner metrics snapshot, and a partner_sync health block.
The metrics block is the latest stored daily partner_metrics_daily row and is null when the app has no Partner integration or no daily rows yet. partner_sync is null when no sync data exists, and only includes the keys whose values are known. This endpoint never returns a 409 — it reports integration state in integrations / metrics rather than gating on it.
Path parameter
- Name
app- Type
- string
- Description
The team app's ULID, e.g.
01JN4HKQX0000000000000000.
Takes no query parameters.
Request
curl https://ranksyapp.com/api/v1/apps/01JN4HKQX0000000000000000 \
-H "Authorization: Bearer rk_live_..."
Response
{
"object": "app",
"ulid": "01JN4HKQX0000000000000000",
"slug": "my-app",
"name": "My App",
"listing": {
"rating": 4.8,
"reviews_count": 1240,
"built_for_shopify": true,
"status": "published",
"developer": "Acme Inc.",
"launched_at": "2024-03-15",
"url": "https://apps.shopify.com/my-app",
"subtitle": "The fastest way to do the thing.",
"introduction": "My App helps merchants do the thing in one click."
},
"categories": [
{ "slug": "marketing", "name": "Marketing" }
],
"integrations": {
"partner_api": true,
"analytics": false,
"app_store": true
},
"last_synced": {
"partner_api": "2026-05-29T03:14:00+00:00",
"analytics": null
},
"metrics": {
"date": "2026-05-29",
"mrr": 12450.5,
"gross_revenue": 980.25,
"net_revenue": 784.2,
"installs": 27,
"uninstalls": 12,
"active_merchants": 1830,
"active_subscriptions": 640,
"paying_customers": 612,
"churn_rate": 0.034,
"active_installs": 2147,
"active_installs_real": 2024
},
"partner_sync": {
"partner_sync_status": "complete",
"partner_sync_last_complete_at": "2026-05-29T03:14:00+00:00"
}
}
Response shapes
The app object
Returned both as each row in the list and as the base of the single-app overview. The list row stops at last_synced; the overview adds categories, metrics, partner_sync, and the subtitle / introduction listing fields.
- Name
object- Type
- string
- Description
Always
"app".
- Name
ulid- Type
- string
- Description
The app's ULID — the stable public identifier used as
:appin every other endpoint.
- Name
slug- Type
- string
- Description
The app's URL slug within the team.
- Name
name- Type
- string | null
- Description
App name from its App Store listing, or
nullwhen the listing has not been scraped yet.
- Name
listing- Type
- object | null
- Description
App Store listing facts (see below), or
nullwhen the app has no scraped listing.
- Name
categories- Type
- array
- Description
Overview only. App Store categories the app is listed in (each
{ slug, name }); empty array when none. Theslugis the{handle}forGET /categories/{handle}.
- Name
integrations- Type
- object
- Description
Which data integrations are connected:
partner_api,analytics, andapp_store(alwaystruefor tracked apps).
- Name
last_synced- Type
- object
- Description
Last successful sync timestamps (ISO 8601) per integration:
partner_apiandanalytics, eachnullwhen never synced.
- Name
metrics- Type
- object | null
- Description
Overview only. The latest daily Partner metrics snapshot (see below), or
nullwhen the app has no Partner integration or no daily rows yet.
- Name
partner_sync- Type
- object | null
- Description
Overview only. Partner-sync health block, or
nullwhen no Partner sync data exists. Keys (partner_sync_status,partner_sync_last_complete_at,partner_sync_last_error_at,partner_sync_error_reason) are present only when known.
listing
- Name
rating- Type
- number | null
- Description
Average star rating (1 decimal), or
nullwhen unrated.
- Name
reviews_count- Type
- integer
- Description
Total number of reviews on the listing.
- Name
built_for_shopify- Type
- boolean
- Description
Whether the app carries the Built for Shopify badge.
- Name
status- Type
- string | null
- Description
Listing status (e.g.
published/unlisted), ornullwhen unknown.
- Name
developer- Type
- string | null
- Description
Developer / publisher name, or
nullwhen not captured.
- Name
launched_at- Type
- string | null
- Description
Listing launch date (
YYYY-MM-DD), ornullwhen unknown.
- Name
url- Type
- string | null
- Description
Public App Store listing URL, or
nullwhen unknown.
- Name
subtitle- Type
- string | null
- Description
Overview only. Listing subtitle / tagline, or
nullwhen not captured.
- Name
introduction- Type
- string | null
- Description
Overview only. Listing introduction / short description, or
nullwhen not captured.
metrics
The latest stored daily snapshot from partner_metrics_daily. Present on the overview only, and null when the app has no Partner integration or no daily rows. For time series and per-metric snapshots, use the Metrics endpoints.
- Name
date- Type
- string
- Description
Date of the snapshot (
YYYY-MM-DD).
- Name
mrr- Type
- number
- Description
Monthly recurring revenue at the snapshot date, in the app's base payout currency.
- Name
gross_revenue- Type
- number
- Description
Gross revenue for the snapshot day (before Shopify's cut).
- Name
net_revenue- Type
- number
- Description
Net revenue for the snapshot day (after Shopify's cut).
- Name
installs- Type
- integer
- Description
Installs recorded on the snapshot day.
- Name
uninstalls- Type
- integer
- Description
Uninstalls recorded on the snapshot day.
- Name
active_merchants- Type
- integer
- Description
Active merchants at the snapshot date.
- Name
active_subscriptions- Type
- integer
- Description
Active subscriptions at the snapshot date.
- Name
paying_customers- Type
- integer
- Description
Paying customers at the snapshot date.
- Name
churn_rate- Type
- number
- Description
Churn rate at the snapshot date — a fraction (
0.034= 3.4%), not a percentage.
- Name
active_installs- Type
- integer
- Description
Current active install base — every
INSTALLEDrow, including test / dev stores (so it mirrors the Shopify Partner Dashboard's install count). A live count, not a stored daily-snapshot column.
- Name
active_installs_real- Type
- integer
- Description
Current active install base excluding test / dev stores — the "real" count the dashboard uses for ARPU and active-base figures.
List envelope (object: "list")
GET /apps returns the standard list envelope. It is not date-windowed, so it carries no coverage block and no currency.
- Name
object- Type
- string
- Description
Always
"list".
- Name
url- Type
- string
- Description
The path of this list resource (
/api/v1/apps).
- Name
page- Type
- integer
- Description
The current page number (1-based).
- Name
per_page- Type
- integer
- Description
Rows per page.
- Name
total_count- Type
- integer
- Description
Total rows across every page.
- Name
has_more- Type
- boolean
- Description
Whether more pages follow this one.
- Name
metadata- Type
- object
- Description
Endpoint-specific metadata; shape varies by endpoint.
- Name
data- Type
- array
- Description
The app rows for this page.
Errors
Beyond the universal 401 / 403 / 429 (see Errors), the Apps endpoints return:
404 resource_not_found— onGET /apps/:appwhen the addressed app does not exist or is not tracked by your team. App access is team-scoped, so an app belonging to another team surfaces as404, never403.422 validation_failed— bad query parameters (e.g.per_pageabove200, or a malformedfilter).400— onGET /appswhen afilter[...]orsortkey is not in the allowed set. Spatie QueryBuilder rejects unknown keys before validation runs.
Neither endpoint returns a 409: listing and overview never gate on a connected Partner integration — they report integration state in the integrations flags and a null metrics block instead.