FCM Service Account JSON: What It Is and How to Get It

Entrig
Ib Entrig Team

If you are wiring up Android push notifications, you will hit a step that says “upload your Firebase service account JSON” and it is not obvious what that means, where it lives, or why it is different from the other Firebase JSON file you already added to your app.

This covers what FCM actually is, why the credential exists, and how to get it. It takes about three minutes once you know where to click.


What FCM Is

Firebase Cloud Messaging is the only way to deliver a push notification to an Android device. It is not a preference or a vendor choice. Android’s push transport runs through Google’s servers, and FCM is the interface to it.

The flow has three parties:

  1. Your app registers with FCM on the device and receives a device token, a long string that uniquely identifies that installation.
  2. Your server stores that token and, when something happens worth notifying about, calls FCM saying “deliver this payload to this token.”
  3. FCM does the actual delivery to the device, handling the OS-level connection, retries, and the case where the phone is offline.

You cannot skip step 2 by having the app notify itself. A push notification exists precisely so that something can reach the user when your app is not running.


Why a Service Account JSON

Step 2 needs authentication. FCM will not accept “send a notification to every user of app X” from anyone who asks.

Historically that was a server key: a long static string you copied out of the Firebase console. If you find a tutorial telling you to do that, it is out of date. The legacy server key and the legacy send endpoint were deprecated and then switched off, and newer Firebase projects never had one at all.

The current mechanism is the HTTP v1 API, which authenticates with a service account: a non-human identity belonging to your Firebase project. The JSON file you download is that identity’s private key. Your server uses it to mint short-lived access tokens, and those tokens authorise the send.

Practically, this is better. The credential is scoped, revocable, and rotatable, and a leaked file can be killed without regenerating anything user-facing.


The File Everyone Confuses It With

This trips up nearly everyone, so it is worth being explicit.

google-services.jsonService account JSON
What it isClient configurationA private credential
Where it goesInside your Android app (app/)On your server, or your push provider
ContainsProject id, API key, app idA private key
Safe in the app bundle?Yes, it is designed for thatAbsolutely not
Safe in git?Generally yesNo
Downloaded fromProject Settings → General → Your appsProject Settings → Service accounts

Both are JSON, both come from the same console, and they are not interchangeable. If push is failing with an authentication error, the most common cause is that one has been used in place of the other.

The rule: google-services.json identifies your app. The service account key proves your server is allowed to send.


Getting the Service Account JSON

1. Create or open a Firebase project

Go to the Firebase Console and either create a project or open an existing one.

You do not have to adopt any other Firebase product. Using Firebase purely as a push delivery channel, while your database and auth live somewhere else entirely, is a completely normal setup.

2. Register your Android app

In Project Settings → General → Your apps, add an Android app. It asks for your package name, which has to match the applicationId in your app/build.gradle or build.gradle.kts exactly, including case.

Download the google-services.json it offers and put it in your app’s app/ directory. That is the client file, and you are done with it.

3. Generate the private key

Go to Project Settings → Service accounts, then click Generate new private key. Confirm the warning, and a .json file downloads.

That file is the one your server or push provider needs. It looks roughly like this:

{
  "type": "service_account",
  "project_id": "your-project-id",
  "private_key_id": "...",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...",
  "client_email": "firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com",
  "client_id": "..."
}

4. Store it somewhere safe

Treat it like a database password:

  • Do not commit it to version control
  • Do not bundle it in your mobile app
  • Do not paste it into client-side code

Anyone holding this file can send a notification to every user of your app. If it leaks, delete the key from Service accounts and generate a new one. Nothing user-facing breaks.


Common Failure Modes

“Invalid service account” or authentication errors on send. Usually google-services.json was uploaded where the service account key was expected. Check that your file has a private_key field.

SenderId mismatch. The device token was issued by a different Firebase project than the one your server is authenticating as. This normally means the app shipped with a google-services.json from project A while the server holds credentials for project B. Both sides have to be the same project.

UNREGISTERED or NotRegistered. The token is dead: the app was uninstalled, the data cleared, or the token rotated. This is expected and normal at low rates. Delete the token from your database when you see it, otherwise you accumulate dead tokens and your delivery rate quietly degrades.

Nothing arrives, no error. Check the package name matches Firebase exactly, including case. A mismatch drops the notification silently, which is the worst possible failure mode and a surprisingly common one.


Where This Fits

Getting the credential is the easy part. The work that follows is the part that becomes a project: storing device tokens, keeping them fresh, deciding who should receive a given notification, building the payload for each platform, and handling retries and dead tokens.

If your data lives in Supabase, Entrig does that half. You upload this service account JSON once, and notifications become something you configure against your existing tables rather than a service you build and maintain. It installs the Postgres trigger, resolves the recipients, and handles delivery to FCM and APNs.

You still need this file either way. Google requires your own credentials to deliver to your own app, and no service can remove that step.


Frequently asked questions

What is a Firebase service account JSON?

It is a private key file that lets a server authenticate as your Firebase project and send push notifications through the FCM HTTP v1 API. You download it once from Firebase Console under Project Settings, Service accounts, Generate new private key. It belongs on your server or in your push provider, never in your app.

What is the difference between google-services.json and the service account JSON?

They are two different files that people constantly confuse. google-services.json is client configuration that ships inside your Android app and identifies which Firebase project the app belongs to. The service account JSON is a private credential that lives on your server and proves you are allowed to send notifications to that project. Putting the service account file in your app is a security problem.

Where is the FCM server key? I cannot find it.

It is gone. The legacy FCM server key and the legacy HTTP API were deprecated and then shut down, so newer Firebase projects never had one. The replacement is the HTTP v1 API, which authenticates with a service account JSON instead of a static server key. Any tutorial telling you to copy a server key from the Cloud Messaging tab is out of date.

Do I need a Firebase project to send Android push notifications?

Yes. FCM is the only supported way to deliver push notifications to Android devices, and FCM is part of Firebase. You do not have to use any other Firebase product, and you do not need to move your database or auth. A Firebase project used purely as a delivery channel is a normal setup.

Is the Firebase service account JSON safe to commit to git?

No. It contains a private key that can send notifications to every user of your app. Treat it exactly like a database password: keep it out of version control, out of your mobile app bundle, and out of any client-side code.

Do I need FCM for iOS as well?

Not necessarily. iOS push is delivered by Apple's APNs. Some stacks route iOS notifications through FCM, which then talks to APNs on your behalf, and others talk to APNs directly. Either way you still need an APNs key from your Apple Developer account.