By Specita
Google Play service account JSON key: setup and safe use
How to create a Google Play service account JSON key, grant it Play Console access, limit its permissions, and fix the usual 401 and 403 errors.

A Google Play service account JSON key is the credential file that lets a script, CI job, or tool call the Google Play Developer API without a person signing in. You create the service account in Google Cloud, download its JSON key, then invite the account's email address in Play Console and grant it permissions. Without that last step, the key authenticates but can't reach your apps.
Treat the file like a password. Anyone who holds it can do whatever the account's permissions allow.
The steps below follow Google's documentation. We did not run them on a new account for this article, and console labels can change.
How to create the service account
Google's API getting started guide recommends a service account for server-to-server access. The setup runs across two consoles.
In Google Cloud:
- Select or create a project, and turn on the Google Play Android Developer API.
- Open IAM & Admin, then Service Accounts.
- Click Create service account and follow the steps.
- Open the new account, go to Keys, and add a JSON key. Your browser downloads the file, and this is your only copy.
In Play Console:
- Open Users and permissions.
- Click Invite new users.
- Enter the service account's email address, which ends in
.iam.gserviceaccount.com. - Choose which apps it can reach and what it can do, then send the invite.
If your organization blocks key creation, you may see an error when you try to add a key. An organization policy controls that, so ask your Google Cloud administrator.
Which permissions to grant
Give the account the least it needs, and scope it to specific apps where possible. Here's how to think about it by job:
| Job | What it needs |
|---|---|
| Upload to internal testing from CI | Permission to release to testing tracks |
| Release to production from CI | Release to production permission. Think hard before you automate this |
| Read release status for a dashboard | App-specific read access to app information |
| Billing APIs | View financial data and manage orders, as Google lists |
Permission names change, so check Google's permission list when you set this up. Don't make a service account an admin because a tool's setup page suggests it might be easier. If a tool needs admin rights to read data, ask why.
Use one account per job. A CI uploader and a read-only reporting tool shouldn't share a key. When one of them is retired, you can remove it without breaking the other.
How to store a Google Play service account JSON key
The JSON file belongs in a secret store. It should never be in your repository, a chat thread, or a shared drive.
In GitHub Actions, store it as an encrypted secret and write it to a file only for the step that needs it:
- name: Write Play key
run: echo '${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}' > "$RUNNER_TEMP/play.json"
Check that your logs don't print it. For fastlane, point json_key at the path in your Appfile or action, and read the path from the environment.
Rotate on a schedule and whenever someone with access leaves. To rotate, add a new key in Google Cloud, update your secret, confirm a run works, and then delete the old key. Google Cloud allows more than one key on an account, so you can do this with no gap.
If a key leaks, delete it in Google Cloud right away, then look through recent activity for anything you don't recognize. Deleting the key stops it working, while removing the Play Console user removes the access.
How to fix common errors
| Error | Usual cause | Fix |
|---|---|---|
401 or invalid credentials | Wrong file, or the key was deleted | Check client_email in the JSON, and confirm that the key still exists |
403 "The caller does not have permission" | The email isn't invited in Play Console, or the app isn't included | Open Users and permissions and check that account's apps |
403 API not enabled | The API is off in the Google Cloud project | Turn on the Google Play Android Developer API |
404 on a package | Wrong package name, or the app has no release yet | Check the package name |
| "APK specifies a version code that has already been used" | A repeat version code | Increment it. The key is fine |
New service accounts can take time to work after you grant access. If everything looks right and you still get a 403, wait and try again before you tear it down. Some developers report waits of hours for this to take effect. Google doesn't state a number on the pages we checked.
The client_email field in the JSON tells you exactly which account a file belongs to, which helps when you inherit a project with three similar files.
For agencies
Each client should own their own Google Cloud project, service account, and Play Console invite. If the service account lives in the agency's project, it's harder to hand over and easier to forget. At the end of a project, the client can then remove the agency's human users without breaking their pipeline, and the agency holds no leftover credentials.
Keep a short record for each client app: which accounts exist, what each one does, who owns the secret, and when it was last rotated. Store the record, and leave the key out of it.
Using the key with Specita
Specita connects to Google Play with a dedicated service account and read-only, app-specific permissions. It uses the Android Publisher and Play Developer Reporting scopes, and encrypts the JSON at rest. It then shows each track's release state in your product's release record. The Google Play setup guide lists the exact permissions.
To see what the release data means, read our guide to Google Play staged rollouts.
Google guidance checked on November 4, 2026.