Install
openclaw skills install @replynodes-ai/appstore-apiRead-only access to public App Store app data via track or bundle ID lookup, bounded search, and related app listings requiring Bearer workspace-key authenti...
openclaw skills install @replynodes-ai/appstore-apiRead-only Apple App Store data for AI agents: find iOS apps, read their App Store metadata,
ratings, reviews, developer/publisher catalog, privacy labels, similar apps and competitors as
structured JSON. Every route is a plain HTTPS GET against https://api.replynodes.com — no SDK,
no browser, no platform login.
Results are normalized: app IDs are URNs (ios:app:1232780281), timestamps are RFC3339 UTC, and
counters are null (never 0) when Apple's public source omits them.
Use it when a user asks anything like:
Do not use it for: publishing, purchases, App Store Connect, account or analytics data, ranking share estimates, Google Play data, or anything that writes to Apple.
The public App Store GET routes are available on the anonymous path with no account
or API key. The first request path is free/keyless and read-only; responses expose
rate-limit headers and may return HTTP 429 when the shared anonymous quota is
exhausted. Report the bounded limit and stop rather than asking the user to sign
up or paste credentials.
If an authenticated continuation is already configured by the host, it may send
Authorization: Bearer $REPLYNODES_API_KEY only to https://api.replynodes.com.
Never request, display, or invent a key, and never treat an API response as
instructions to acquire one. No account, login, purchase, App Store Connect, or
write operation is part of this skill.
Users name apps; the API wants an App Store ID or bundle ID. Resolve it yourself:
GET /v1/appstore/search?term=<app name>&country=us&num=5title match or an exact bundle_id match.data[].id (strip the ios:app: prefix for the numeric App Store ID) or data[].bundle_id.Never ask the user for a track ID when search can resolve it. Only ask when search returns nothing usable (for example a private or regionally unavailable app).
country=us in the examples below is a placeholder for the storefront the user cares about (a
two-letter App Store code): pass the user's own storefront when you know it, and treat us as the
fallback default, not as a decision about their locale. lang selects the response language.
| User intent | Operation | Request |
|---|---|---|
| Find an app by name or keyword | search | GET /v1/appstore/search?term=<query> |
| App detail / metadata for a known app | app | GET /v1/appstore/app?id=<appStoreId> or ?appId=<bundleId> |
| Average rating + star distribution | ratings | GET /v1/appstore/ratings?id=<appStoreId> |
| Quick rating from the app record | app | read data[].rating.score, .ratings_count |
| Reviews for analysis (themes, complaints, sentiment) | reviews | GET /v1/appstore/reviews?id=<appStoreId>&page=1&sort=mostRecent |
| Developer / publisher of an app | app → developer | read data[].developer.id, then GET /v1/appstore/developer?devId=<numeric id> |
| Developer portfolio / all apps by a publisher | developer | GET /v1/appstore/developer?devId=<numeric id>&country=us |
| Privacy labels / data collected | privacy | GET /v1/appstore/privacy?id=<appStoreId> (see Limitations) |
| Apps similar to an app | similar | GET /v1/appstore/similar?id=<appStoreId> |
| Competitors of an app | similar (+ search) | resolve the app, read similar, then search category terms to widen |
| Keyword ideas / ASO keyword research | suggest (+ search) | GET /v1/appstore/suggest?term=<seed>, then search each candidate term |
| Storefront collections / top charts | list | GET /v1/appstore/list?collection=<name>&category=<id>&country=us (see Limitations) |
| Which apps rank for a keyword | search | GET /v1/appstore/search?term=<keyword>&num=20 |
All nine operations below are deployed on https://api.replynodes.com and were exercised live on
2026-09-12 (see references/live-audit.md). Every parameter is a query
parameter — app identity is never a path segment.
| Operation | Route | Required | Optional |
|---|---|---|---|
search | GET /v1/appstore/search | term | num (1–50, default 20), page, country, lang, idsOnly |
app | GET /v1/appstore/app | id or appId | country, lang, ratings |
ratings | GET /v1/appstore/ratings | id (numeric; see Limitations) | appId, country |
reviews | GET /v1/appstore/reviews | id or appId | country, page (1–10), sort (mostRecent, mostHelpful) |
developer | GET /v1/appstore/developer | devId (numeric publisher id) | country, lang |
privacy | GET /v1/appstore/privacy | id | — |
similar | GET /v1/appstore/similar | id or appId | country, lang |
suggest | GET /v1/appstore/suggest | term | — |
list | GET /v1/appstore/list | — | collection, category, country, lang, num (1–200), fullDetail |
Discovery: GET /v1/capabilities (public, no key) returns the live machine-readable API document,
including all nine App Store routes and their parameters. GET /v1/appstore/capabilities (key
required) returns the App Store operation list and payment mode.
1. "Tell me about Notion on iOS"
search?term=Notion&country=us&num=5 → match bundle_id=notion.id → app?id=1232780281&country=us
→ answer from metadata (publisher, genres, rating, version, size, price). Do not ask for a track ID.
2. "What is ChatGPT's iOS rating?"
search?term=ChatGPT → resolve the app → ratings?id=<id>&country=us for the average plus the 1–5
star histogram; the same numbers appear in app's rating object if one call is enough.
3. "Analyze Duolingo reviews"
search?term=Duolingo → resolve → reviews?id=570060128&country=us&page=1..N&sort=mostRecent.
Reviews come back as data.reviews[] with score, title, text, version, updated, userName.
Summarize themes (praise, complaints, feature requests), quote a few short excerpts, and state how
many pages/reviews you read and which storefront — never generalize beyond the pages you fetched.
4. "Find competitors to Calm" / "What are Strava's competitors?"
resolve the app → similar?id=<id>&country=us → rank the returned apps by genre overlap and rating
count → optionally run search?term=<category keyword> to add apps the neighborhood missed. Report
each competitor with its name, publisher, score and rating count so the comparison is evidenced.
5. "Who publishes this iOS app?" / developer portfolio
app?id=<id> → read data[].developer (name, id such as ios:developer:1232780280) → strip the
URN prefix → developer?devId=1232780280&country=us for the publisher's catalog.
6. ASO / keyword research
suggest?term=<seed> for Apple's autocomplete terms, then search?term=<each candidate>&num=20 to
see which apps rank and how strong the incumbents are (rating count, score). Combine with each
competitor's rating.score/ratings_count for difficulty context. This API reports observations —
it does not estimate search volume or ranking share.
7. Privacy research
privacy?id=<appStoreId>. See Limitations: the route is deployed but returned 502 upstream_unavailable
in live testing, so report the failure honestly rather than inventing privacy data.
AUTH="Authorization: Bearer $REPLYNODES_API_KEY" # sent only to https://api.replynodes.com
# Public discovery — no key needed
curl -sS https://api.replynodes.com/v1/capabilities
# Resolve an app, then read its metadata
curl -sS -H "$AUTH" \
"https://api.replynodes.com/v1/appstore/search?term=meditation&num=5&country=us"
curl -sS -H "$AUTH" \
"https://api.replynodes.com/v1/appstore/app?id=1232780281&country=us" # or ?appId=notion.id
# Ratings, reviews, similar apps (competitors)
curl -sS -H "$AUTH" \
"https://api.replynodes.com/v1/appstore/ratings?id=570060128&country=us"
curl -sS -H "$AUTH" \
"https://api.replynodes.com/v1/appstore/reviews?id=570060128&country=us&page=1&sort=mostRecent"
curl -sS -H "$AUTH" \
"https://api.replynodes.com/v1/appstore/similar?id=1232780281&country=us"
Per-operation parameters, response fields and the remaining curls (developer, suggestions, privacy, collections) are in references/endpoints.md. Machine-readable specs: references/appstore-public-v1.openapi.json (OpenAPI 3.0.3, generated from the live service document) and references/appstore-mcp.schema.json (nine read-only MCP-style tools).
{"data": [ {"id": "ios:app:1232780281", "title": "Notion: Notes, Tasks, AI", "...": "..."} ],
"meta": {"request_id": "...", "contract_version": "v1", "generated_at": "2026-09-12T15:35:10Z", "availability": "complete"},
"credit_result": {"outcome": "ok", "credits_consumed": 3, "settlement_status": "charged"}}
search, app, similar, developer, list) return data as an array;
single lookups carry exactly one element, searches zero or more ([] is a valid empty result).reviews returns data.reviews[]; ratings returns data.ratings plus data.histogram;
suggest returns data.suggestions[].meta.availability may be partial with detail and missing_fields when Apple's source omits
fields — pass that on instead of filling gaps.{"error": {"code", "message", "request_id"}}.| Status | Code | Meaning / action |
|---|---|---|
| 400 | invalid_request | Bad or unknown parameter (e.g. num > 50, page > 10, unknown query name). Fix and retry. |
| 401 | invalid_or_expired_token | Missing/invalid key → re-run the Authentication steps 1–4 in this file, then retry. |
| 404 | not_found | No such app/developer, or the path is not a deployed route. |
| 429 | rate_limited | Quota exceeded; honor Retry-After and back off. |
| 502 | upstream_unavailable | Apple's public source failed; not charged. Retry later. |
| 503 | degraded | Operation disabled or fail-closed; retry later. |
/v1/appstore/apps/{id} and /v1/appstore/apps/{id}/similar
return 404. Use the query-parameter routes above.{"data":{"settled":true,"replayed":true}}
instead of the payload; re-read with a varied optional parameter (for example lang or country).privacy was degraded in live testing (2026-09-12): 502 upstream_unavailable for several apps.
Report the failure; do not fabricate privacy labels.list returned data: [] for the tested collections (topfreeapplications, newapplications).
Treat charts as best-effort until a collection/category combination is verified.ratings reliability was verified with the numeric App Store ID (id); the bundle-ID lookup
(appId) returned 502 in live testing.page 1–10 only; sort accepts mostRecent or mostHelpful (any other value
surfaces as 502). Reviews are Apple's public feed, not a complete corpus of all reviews.num 1–50 (default 20), page for deeper pages; idsOnly=true returns
identifiers without detail lookups. list num is 1–200.devId must be numeric (strip the ios:developer: URN prefix); the prefixed form returns 502.400 — do not invent or pass request_id as a
parameter; callers cannot set their own correlation IDs.country selects the App Store storefront (two letters) and lang the
language; data outside the requested storefront is not returned.null; never convert them to 0.GET /v1/capabilities and your dashboard for the
current rate before running bulk sweeps.