All posts
GuideJul 8, 2026 · 10 min

The Google Play Reviews API: Quotas, the 7-Day Window, and Workarounds

A working dev reference for the Google Play reviews API: service-account OAuth, list/get/reply, the 350-char cap, 200 GET/hr + 2000 POST/day quotas, and the 7-day window.

RA

The Argus Team

Reply Argus

The Google Play reviews API lives inside the Google Play Developer API as the `reviews` resource, and it gives you exactly three methods: `reviews.list` to pull recent reviews, `reviews.get` to fetch one by id, and `reviews.reply` to post a developer response. You authenticate with an OAuth service account, your reply text is capped at a hard 350 characters, and — the part that trips up almost everyone — the API only returns reviews from the last seven days. There is no backfill endpoint.

That last constraint is the one that ends most integration plans, so it's worth internalizing up front: the API is a live feed for recent activity and a reply channel, not an archive you can query for history. Below is the working reference — how to authenticate, the three calls with real request shapes, the two quota ceilings, the seven-day window and its only real workaround, and the fix for the `401` that stops nearly every first attempt.

Authenticating: a service account, not your personal login

The single biggest mistake on day one is reaching for a normal OAuth user-consent flow. The reviews resource is a server-to-server API — you authenticate as a service account, not as yourself. A service account is a non-human identity you create in Google Cloud; it gets a private key, requests its own access tokens, and acts on the app's behalf with no interactive login. Every review call carries a bearer token minted from that service account and scoped to `www.googleapis.com/auth/androidpublisher`.

There are two linkages that both have to be right, and this is where the setup goes sideways. First, the Google Cloud project that owns the service account has to be linked to your Play Console account. Second, the service account itself has to be invited into Play Console as a user and granted permission to reply to reviews on the specific app. Miss either one and your token is valid but powerless — you'll authenticate fine and then get told you don't own the app. Here's the order that works:

  1. 1

    Step 1 — Create the service account

    In Google Cloud Console, create a service account and generate a JSON key. Enable the Google Play Android Developer API on that project. Keep the JSON key out of your repo — it's a credential.

  2. 2

    Step 2 — Link the project to Play Console

    In Play Console under Setup → API access, link the Google Cloud project. This is the account-level handshake that lets the project's service accounts see your apps at all.

  3. 3

    Step 3 — Grant the service account access

    Still in Play Console, invite the service account's email as a user and give it the 'Reply to reviews' permission — account-wide or scoped to the specific app. This is a separate step from linking, and it's the one most people skip.

  4. 4

    Step 4 — Mint a token and call

    Use your language's Google auth library to exchange the JSON key for an access token with the androidpublisher scope, then attach it as a Bearer token. Access propagation can lag after step 3 — if the first call 401s, wait and retry before assuming a bug.

The three calls: list, get, reply

Every request hits `androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/reviews`, where `{packageName}` is your app's id (for example `com.yourcompany.app`). `reviews.list` returns recent reviews that have written comments — star-only ratings never appear, because there's no text to reply to. `reviews.get` fetches a single review by its id. `reviews.reply` posts your response to a review's `:reply` sub-path with a small JSON body.

One useful detail on `list`: pass `translationLanguage` and Google returns a machine translation of each review alongside the original, which is handy for triage across markets. Pagination is token-based — the response hands you a `tokenPagination.nextPageToken` you feed back as `token` on the next call, but remember it only ever pages within the seven-day window.

http
# List recent reviews (comments only, last 7 days)
GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/com.yourcompany.app/reviews?maxResults=100&translationLanguage=en
Authorization: Bearer {access_token}

# Get one review by id
GET …/applications/com.yourcompany.app/reviews/{reviewId}
Authorization: Bearer {access_token}

# Reply to a review (replyText max 350 chars)
POST …/applications/com.yourcompany.app/reviews/{reviewId}:reply
Authorization: Bearer {access_token}
Content-Type: application/json

{ "replyText": "Thanks for flagging this — the crash on launch is fixed in 4.3.1. Please update and reply here if it persists." }
The three review calls. Base path abbreviated as … after the first.

Each review in the `list`/`get` payload carries more than a star and a comment. You get the reviewer's language, the raw text plus an optional machine translation, the last-modified timestamp, and a `userComment` metadata block with the device model, Android OS version, and the app version code the review was left on. That last field is the quietly valuable one: it lets a reply name the exact build a bug landed in, which is what the widget example below leans on. Note too that there is no push or webhook for new reviews — Google gives you no callback, so a fresh review only surfaces when you next call `list`. Catching reviews promptly is entirely on your polling cadence.

A successful `reply` returns the text you posted plus a `lastEdited` timestamp. Each review holds exactly one developer response, so calling `reply` again on the same review edits the existing reply rather than stacking a second one — useful when you want to update an answer after a fix ships.

The 350-character reply limit is hard

`replyText` over 350 characters is rejected outright — this isn't a soft guideline you can occasionally exceed, it's a validation error. Google Play's cap is the tighter of the two big stores to design around: Apple publishes no official character limit for App Store responses, and community testing suggests you can run to a few thousand characters there, but on Play you get 350 and not one more. If you're templating replies for both stores, build to the Play ceiling and Apple takes care of itself.

Three hundred and fifty characters is less room than it sounds, and it forces a good habit: lead with the fix, cut the throat-clearing. The [character caps and formatting rules for every store](/blog/reply-rules-for-every-app-store) are worth a skim if you template across both, and we cover the wider set of mechanical differences in [App Store vs Google Play review replies](/blog/app-store-vs-google-play-review-replies). Here's what a reply that respects the cap actually looks like:

Works fine but the home-screen widget resets to the default city every morning. I have to re-add my location daily. Pixel 8.

Reply

Thanks for the detail — the widget dropping your saved location on the daily refresh is a real Pixel bug, and the fix ships in 5.2 this week. Until then, long-press the widget and re-pin your city; that holds through a reboot. Reply here if 5.2 doesn't sort it and we'll dig in.

That's 273 characters: names the bug, gives a workaround, promises a version, no filler. It's also the reply that actually moves your number — when Google announced recency-weighted ratings at I/O 2019, it reported that developers who respond to reviews see an average lift of 0.7 stars, and we dig into why in [does replying to app reviews raise your rating](/blog/does-replying-to-app-reviews-raise-your-rating).

The two quotas you'll hit: 200 GET/hr and 2,000 POST/day

The reviews API enforces two ceilings, applied separately and per-app, so a multi-app account gets its own budget on each title. Google's Reply to Reviews docs put them at:

  • GET — 200 requests per hour. This covers both `reviews.list` and `reviews.get`. Because `list` pages within a seven-day window, a single poll of a busy app can burn several of these on pagination alone, so poll on a schedule rather than in a tight loop.
  • POST — 2,000 replies per day. This is `reviews.reply`. For most apps it's generous headroom; for an agency answering across many titles it's a real number to watch, since it's per-app and resets daily.
  • Both are raiseable. If your volume genuinely exceeds these, Google lets you request a quota increase for the app. Design your polling and retry logic to back off on a `429` in the meantime rather than hammering the endpoint.

The 7-day window has no API workaround — only an export

reviews.list returns nothing older than roughly seven days. There is no date parameter, no offset, no 'give me everything since launch' — historical reviews are simply not reachable through the API. The only supported way to get older reviews is the Play Console's reviews export: Google drops monthly CSV files into a Google Cloud Storage bucket tied to your account (Download reports → Reviews). If you want a full history, you poll the API continuously to capture reviews inside their window and persist them yourself, and you use the CSV export to backfill everything before you started.

This is the design decision that reframes the whole integration. The API isn't a database you query — it's a stream you have to catch. Anyone who wants a durable, searchable review history has to stand up a poller that runs on a cron, dedupes on review id, writes to their own store, and reconciles against the CSV export for the pre-history. That's a small service, an ops burden, and a set of edge cases (token refresh, quota backoff, propagation delays) that you now own. This is the exact plumbing [ReplyArgus](/features) runs for you: it holds the service-account OAuth, polls both Google Play and the Apple App Store on a schedule, keeps the full history past the seven-day window, and drafts an on-brand reply for each review in the reviewer's own language — already fitted to Play's 350-character cap — so you approve instead of build.

Fixing the 401: 'This developer account does not own the application'

This is the error that stops nearly every first attempt, and it's misleading — it almost never means what it says. Your token is valid; the problem is the linkage between the service account and the app. The reason code is `developerDoesNotOwnApplication`, and it comes from one of a short list of causes:

  • The service account wasn't invited into Play Console. Linking the Cloud project (Setup → API access) is not the same as granting the service account user-level access. It needs to appear under Users and permissions with the reviews permission. This is the number-one cause.
  • Access hasn't propagated yet. After you grant permission, it can take time — sometimes up to a day — before calls succeed. A 401 minutes after setup is often just propagation, not a misconfiguration. Wait and retry before you go debugging.
  • Wrong package name. The `{packageName}` in the URL must match the app the service account has access to, exactly. A typo or the wrong app id surfaces as this same ownership error rather than a clean 404.
  • The Cloud project isn't linked at all, or is linked to a different Play Console account than the one that owns the app. Confirm the project shown under API access is the one whose service account you're using.

Skip the poller entirely — hand your reviews to an agent

If the goal is to read, triage, and reply to reviews rather than to run infrastructure, you can skip the API build. [ReplyArgus](/agentic-tools) exposes your live App Store and Google Play reviews to Claude, ChatGPT, or Cursor through an MCP connector, so instead of writing polling and reply code you ask your agent to 'draft replies to my unanswered 1-stars' and approve the results. Same three operations — list, draft, reply — behind a conversation instead of a cron job. We walk through the setup in [managing app reviews from Claude](/blog/manage-app-reviews-from-claude).

Frequently asked

What is the Google Play reviews API?
It's the `reviews` resource of the Google Play Developer API, with three methods: `reviews.list` (pull recent reviews), `reviews.get` (fetch one by id), and `reviews.reply` (post a developer response). It requires service-account OAuth, caps replies at 350 characters, and only returns reviews from the last seven days.
How do I authenticate to the Google Play reviews API?
With a service account, not a personal login. Create a service account in Google Cloud, enable the Google Play Android Developer API, link the Cloud project to Play Console under Setup → API access, then invite the service account as a user with the 'Reply to reviews' permission. Its token must carry the `androidpublisher` scope.
What's the character limit for a Google Play API reply?
350 characters, and it's a hard validation limit — `replyText` over 350 is rejected. Apple, by contrast, publishes no official limit for App Store responses (community testing suggests a few thousand characters), so if you write for both stores, design to Google Play's tighter 350-character cap.
Why can't I fetch old reviews from the Google Play API?
Because `reviews.list` only returns reviews from roughly the last seven days — there's no date range or offset parameter to reach older ones. The only supported backfill is the Play Console's reviews export, which drops monthly CSV files into a Google Cloud Storage bucket. For a full history you poll continuously and persist reviews yourself, plus the CSV export for pre-history.
What are the Google Play reviews API rate limits?
Two ceilings, applied per app: 200 GET requests per hour (covering `reviews.list` and `reviews.get`) and 2,000 POST requests per day (`reviews.reply`). Both can be raised by requesting a quota increase for the app if your volume genuinely exceeds them.
How do I fix the 401 'this developer account does not own the application' error?
Despite the wording, it's almost always a linkage issue, not a real ownership problem. Confirm the service account is invited into Play Console with the reviews permission (not just that the Cloud project is linked), that the package name in the URL is exact, and that you've waited for access to propagate — it can take up to a day after granting permission.

So the Google Play reviews API is small and honest about what it is: three calls, a service-account handshake, two quotas, a 350-character reply, and a hard seven-day window that turns any history requirement into a polling service you have to build and babysit. If that's the project, this reference is the whole map. If the actual goal is just to keep up with every review across both stores and answer well before the moment passes, that's the part worth handing off — [start free with ReplyArgus](/signup), no card, and it drafts your first reply in minutes, already sized for Play's 350-character limit and grounded in your own past replies.

Try it

Let Argus draft your next reply.

Watch it answer a real review in your voice. 10-day trial, no card to begin.

See the features or pricing.

Keep reading