Skip to content

API Endpoints

All API endpoints start with the /api/v1 prefix and require Sanctum token authentication (except authentication endpoints).

Base URL: http://localhost:7460/api/v1

MethodEndpointDescription
POST/auth/registerRegister a new user
POST/auth/loginLog in and get a token
MethodEndpointDescription
POST/auth/logoutLog out (revoke token)
GET/auth/meGet the authenticated user
MethodEndpointDescription
GET/account/profileGet user profile
PATCH/account/profileUpdate profile (name)
DELETE/account/profileDelete the account
PUT/account/passwordUpdate password
MethodEndpointDescription
GET/dashboardSummary statistics (total apps, versions, changes)
MethodEndpointDescription
GET/appsList tracked apps (?platform=ios|android)
POST/appsTrack a previously discovered app. platform+external_id must exist in the DB (discover first via search/chart); otherwise 422
GET/apps/searchSearch for apps in the stores (?term=X&platform=ios&country_code=us)
GET/apps/{platform}/{externalId}Get app details. The response includes unavailable_countries: string[] (derived from app_metrics.is_available = false)
GET/apps/{platform}/{externalId}/listingGet store listing (?country_code=us&locale=en-US). The AppAvailableCountry rule returns 422 if the app is not available in the selected country
GET/apps/{platform}/{externalId}/rankingsApp chart rankings for the selected day (?date=YYYY-MM-DD)
GET/apps/{platform}/{externalId}/sync-statusReturns the sync_statuses record (status, current_step, progress, failed_items)
POST/apps/{platform}/{externalId}/syncDispatches a refresh to the platform-specific on-demand queue
POST/apps/{platform}/{externalId}/trackTrack an app
DELETE/apps/{platform}/{externalId}/trackUntrack an app

Route constraints: platform must be ios or android, and externalId matches [a-zA-Z0-9._]+.

Discovery via direct URL is disabled by default (DISCOVER_{IOS,ANDROID}_ON_DIRECT_VISIT=false). A show/listing call for a platform+external_id that does not exist in the DB returns 404 — users must first register it through search/chart.

MethodEndpointDescription
GET/apps/{platform}/{externalId}/competitorsList an app’s competitors
POST/apps/{platform}/{externalId}/competitorsAdd a competitor
DELETE/apps/{platform}/{externalId}/competitors/{id}Remove a competitor
GET/competitorsList all competitor apps
MethodEndpointDescription
GET/apps/{platform}/{externalId}/keywordsKeyword density (?locale=en-US&ngram=2) — computed on demand from the current listing
GET/apps/{platform}/{externalId}/keywords/compareCompare keywords (?app_ids=1,2,3&locale=en-US)
MethodEndpointDescription
GET/changes/appsStore listing changes for tracked apps (?field=title&app_id=123&page=2)
GET/changes/competitorsStore listing changes for competitor apps (same query params)

Both endpoints return a paginated envelope (PaginatedChangeResponse: data, links, meta) plus meta_ext.has_scope_apps: boolean so the UI can distinguish “no results” from “user has nothing tracked yet”. Optional query params: field, app_id (integer, filter to a single app from the user’s scope), page (integer).

MethodEndpointDescription
GET/chartsChart rankings (?platform=ios&collection=top_free&country_code=us&category_id=X)
MethodEndpointDescription
GET/explorer/screenshotsBrowse screenshots (?platform=ios&category_id=X&search=term&per_page=12)
GET/explorer/iconsBrowse icons (?platform=android&search=term&per_page=12)
MethodEndpointDescription
GET/countriesList active countries. The internal zz “Global” sentinel is filtered out of the response
GET/store-categoriesList store categories (?platform=ios&type=app)
MethodEndpointDescription
GET/publishers/searchSearch publishers (?term=X&platform=ios&country_code=us)
GET/publishersList publishers from tracked apps
GET/publishers/{platform}/{externalId}Publisher details. 404 for unknown publisher
GET/publishers/{platform}/{externalId}/store-appsPublisher’s store apps. 404 for unknown publisher
POST/publishers/{platform}/{externalId}/importImport a publisher’s apps. Each external_ids[*] must already exist in the DB; otherwise 422

Publisher route constraints: externalId matches [a-zA-Z0-9._%+ -]+ (allows spaces and plus signs).

ScopeLimit
Authentication endpoints (public)5 requests per minute
All other endpoints (local)500 requests per minute
All other endpoints (production)60 requests per minute

All errors follow this format:

{
"message": "Error description"
}

Common HTTP status codes: 401 (unauthenticated), 403 (unauthorized), 404 (not found — e.g. unknown app/publisher), 422 (validation error — e.g. AppAvailableCountry failure or a platform+external_id that has not yet been discovered), 429 (rate limit exceeded).