App Store and Google Play reviews, as a REST API

Fetch reviews for any iOS or Android app as clean JSON. Cache-first: recently requested apps return instantly and new apps are fetched live in seconds. Built on the same pipeline that powers rivioo.app exports, and the same key works with the MCP server.

Quickstart

First reviews in five minutes.

  1. Get a key.
    Sign up, choose a plan, and create a key on the API keys tab of your workspace. It is shown once.
    Terminalshell
    export KEY=rk_live_your_key_here
  2. Find your app's id.
    Search is unmetered and never counts against your quota.
    Requestshell
    curl "https://api.rivioo.app/v1/apps/search?q=spotify&store=android" \
      -H "Authorization: Bearer $KEY"
    Response 200json
    {
      "data": [
        {
          "app_id": {
            "android": "com.spotify.music"
          }
        }
      ]
    }
    Use app_id in the next step.
  3. Fetch reviews.
    Fresh data returns instantly as a 200 with your reviews. If we need to fetch live, you get a 202 instead. That is step 4.
    request
    curl -X POST https://api.rivioo.app/v1/reviews/fetch \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{
        "store": "android",
        "app_id": "com.spotify.music",
        "limit": 500
      }'
  4. Got a 202? (Got a 200? You already have reviews, skip to step 5.)
    A 202 means a live fetch is running. Poll the meta.poll URL until status is completed (usually under a minute), then GET its reviews_url.
    Requestshell
    curl "https://api.rivioo.app/v1/jobs/3f6f…" -H "Authorization: Bearer $KEY"
    Response 200json
    {
      "job": {
        "status": "completed",
        "reviews_url": "/v1/jobs/3f6f…/reviews"
      }
    }
  5. Page through the rest.
    Follow meta.next_cursor from each page until it is null. That is the whole API.
    Requestshell
    curl "https://api.rivioo.app/v1/reviews?cursor=eyJ2IjoxLC…" -H "Authorization: Bearer $KEY"
    A review counts toward your monthly allowance the first time we deliver it to your account. Fetching it again within 30 days is free.

Authentication

Pass your key as a bearer token on every request:

request
curl https://api.rivioo.app/v1/usage \
  -H "Authorization: Bearer rk_live_your_key_here"

Keys are shown once when you create them. Only a hash is stored. If a key leaks, revoke it on the API keys tab of your workspace and create a new one.

Endpoints

Base URL
https://api.rivioo.app/v1
Fetch reviews for an app
POST /reviews/fetch

The core endpoint. If we have fresh data for the app, you get reviews immediately (HTTP 200). Otherwise a live fetch starts and you poll it (HTTP 202).

request
curl -X POST https://api.rivioo.app/v1/reviews/fetch \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{
    "store": "android",
    "app_id": "com.spotify.music",
    "country": "us",
    "limit": 500
  }'
FieldDescription
storeios or android (required)
app_idAndroid package name or iOS numeric track id (required)
country2-letter storefront code, default us. For the App Store it selects that country's reviews. For Google Play it selects the review languages (English and, in most countries where English is not the main language, the country's main language) and returns those reviews from every country, since Google Play reviews are per language, not per country
limitTotal reviews wanted, clamped to your plan's per-request max
cache_policyWhat to do with reviews we already hold for this app and country. use_cache (default) serves them when they are fresh enough and at least limit deep, otherwise starts a live fetch. ask returns status: "cache_choice_required" with HTTP 200 and no reviews when any are held, so you can ask your user; repeat the request with use_cache or refresh. If nothing is held it behaves like use_cache. refresh skips held reviews and starts a live fetch; allow_stale is ignored. If your monthly quota is used up, refresh returns the held reviews instead, since re-reading them is free. Any other value returns 400.
freshness_daysHow old cached data may be before we refresh it (1 to 30, default 7)
allow_staletrue serves older cached data instantly instead of refreshing
filtersOptional object that narrows the reviews before paging. ratings: star ratings to keep, for example [1, 2]. posted_from and posted_before: ISO 8601 timestamps with an offset. app_version: an exact version. Other fields return 400.

Cache hit (200): first page of reviews plus a next_cursor (same shape as /reviews below).

Response 202 (cache miss)json
{
  "job": {
    "id": "3f6f…",
    "status": "queued"
  },
  "meta": {
    "source": "scrape",
    "poll": "/v1/jobs/3f6f…",
    "estimated_seconds": 45
  }
}
Check a job's status
GET /jobs/{id}

Poll a fetch job. Status moves from queued to running to completed (or failed).

Response 200json
{
  "job": {
    "id": "3f6f…",
    "status": "completed",
    "reviews_url": "/v1/jobs/3f6f…/reviews"
  }
}
Get a completed job's reviews
GET /jobs/{id}/reviews

First page of a completed job's reviews. Same shape and pagination as /reviews below. Optional query parameters narrow the reviews before paging.

ParameterDescription
ratingsStar ratings to keep, comma-separated, for example ratings=1,2
posted_fromISO 8601 timestamp with offset; keeps reviews posted at or after it
posted_beforeISO 8601 timestamp with offset; keeps reviews posted before it
app_versionExact app version, for example 9.0.28.630
limitTotal reviews wanted across pages, up to the job's size and your plan's per-request max
page_sizeReviews per page (1 to 500, default 100)
Page through reviews
GET /reviews

Paginate with ?cursor=…. Follow meta.next_cursor from any page until it is null. Pages default to 100 reviews (page_size up to 500). Each review:

Review objectjson
{
  "id": "gp:AOqpTOH…",
  "store": "android",
  "app_id": "com.spotify.music",
  "country": "us",
  "lang": "en",
  "rating": 4,
  "title": null,
  "body": "Offline playlists are great on the subway…",
  "reviewer": "Jordan M.",
  "app_version": "9.0.28.630",
  "developer_reply": null,
  "developer_reply_at": null,
  "url": "https://play.google.com/store/apps/details?id=…",
  "posted_at": "2026-07-21T09:14:00.000Z"
}

For Google Play reviews, country is the country of the collection that first stored the review, not where the reviewer is; use lang instead.

Cursors expire after a short time. If one expires, re-request the first page. Reviews you received in the last 30 days are free to fetch again.
Check your usage Unmetered
GET /usage

Your plan, quota used and remaining, reset date, and today's refresh count.

Response 200json
{
  "plan": "pro",
  "quota": {
    "monthly_reviews": 50000,
    "used": 12480,
    "remaining": 37520,
    "resets_at": "2026-10-01T00:00:00.000Z"
  },
  "scrape_jobs_today": 14,
  "scrape_jobs_daily_cap": 60
}

Errors

Every error uses one envelope:

Error envelopejson
{
  "error": {
    "code": "QUOTA_EXCEEDED",
    "message": "Monthly review quota (50,000) exhausted. Resets 2026-10-01T00:00:00Z.",
    "status": 429
  }
}
CodeStatusMeaning
UNAUTHORIZED401Missing, malformed, or unknown key
KEY_REVOKED / CLIENT_SUSPENDED403Account inactive. Contact us
SUBSCRIPTION_EXPIRED403Paid access has lapsed. Renew on the billing tab
VALIDATION_ERROR400Bad parameter. The message says which
NOT_FOUND404No job with that id on your account
RATE_LIMITED429Over your per-minute request limit
QUOTA_EXCEEDED429Monthly review quota used up, and none of the matching reviews are free to fetch again
SCRAPE_CAP_REACHED429Daily refresh allowance used. Cached data still available

Rate limits and headers

Responses carry RateLimit-* headers (per minute) and X-Quota-Limit / X-Quota-Remaining (monthly reviews). Quota counts each review the first time we deliver it to your account, cached or fresh, per calendar month in UTC. Delivering the same review again within 30 days is free, whether through the REST API, MCP or a workspace export. It is a hard cap with no overage charges. Once it is used up, we still return reviews you received in the last 30 days and set meta.quota_limited to true; if none of the matching reviews qualify, the request fails with QUOTA_EXCEEDED. Unused quota does not roll over. Cached responses do not consume the daily refresh allowance.

Versioning and stability

v1 is stable. Breaking changes ship as a new version with 90 days notice and a migration guide. We may add new fields to responses at any time, so build your parser to ignore unknown keys.

Data coverage

Exactly what you get:

DimensionCoverage
StoresApple App Store and Google Play
StorefrontsEvery public App Store country, via the country parameter. Google Play reviews are per language, not per country: country picks the languages and the reviews come from every country
LanguagesEach review carries a lang code. iOS storefronts return reviews in every language. Google Play collections return reviews written in English and, in most countries where English is not the main language, in the country's main language too
History depthUp to your plan's per-request maximum of the most recent reviews per app per storefront: 2,500 on Plus, 5,000 on Pro
FreshnessLive fetches are current as of the request; cached data is at most freshness_days old (default 7)
FieldsRating, title, body, reviewer, app version, developer reply and timestamp, review URL, posted date

Plans

Priced by reviews delivered per month. Re-reading a review is free for 30 days. Hard cap, no overage charges. One key covers both the REST API and the MCP server.

Plus

For one person who works with reviews every week.

$29per month, billed monthly
plus tax where applicable
Get Plus
  • 10,000 reviews per month
  • 2,500 reviews per request
  • 30 requests per minute
  • 20 live refreshes per day
  • 1 active API key
Pro

Five API keys for separate tools and projects.

$99per month, billed monthly
plus tax where applicable
Get Pro
  • 50,000 reviews per month
  • 5,000 reviews per request
  • 60 requests per minute
  • 60 live refreshes per day
  • 5 active API keys

The allowance counts each review the first time it reaches your account through the REST API, MCP or a workspace export, cached or fresh. Re-reading a review is free for 30 days. The allowance resets on the 1st of each month (UTC), and unused reviews do not roll over.

Get a key

Keys are self-serve. The same key works with both the REST API and the MCP server.

  1. Sign up with Google or an email link.
  2. Choose Plus or Pro under Plan & billing. Access opens when the first payment is confirmed.
  3. Create a key under API keys & setup. Copy it straight away, it is shown once.
  4. Send it as a bearer token, or paste the connect snippet into Claude, Cursor or another MCP client.
Get started Need more than 50,000 reviews a month? Email admin@rivioo.app.