MMashDiv

Push notifications

Push needs your own Firebase project wired into both halves — the Firebase files in the Android and iOS builds, and a Firebase service account in your server's .env. How to set up each half, how to test it from the admin, what customers see, which events are pushed, and what tapping a notification does.

6 min readUpdated 26 September 2026mobile, push, notifications, firebase, fcm, apns, google-services, ios, android

Push is optional. Without it the app builds, runs and publishes normally: customers still see their notifications in the app's own inbox (the bell on the home screen), and a notification that arrives while the app is open is shown as a phone notification over the app's live connection. What push adds is delivery while the app is closed: the events that matter — money arriving, a withdrawal failing, a P2P trade waiting for a reply — reach the phone's lock screen whenever they happen.

The app ships as source, so push needs your own Firebase project. No configuration file for it can come with the package.

Two halves, one Firebase project

Half What it needs Where
Android build google-services.json android/app/
iOS build GoogleService-Info.plist, the Push Notifications capability, and an APNs key uploaded to Firebase ios/Runner/, Xcode, the Firebase console
Your server A Firebase service account: FCM_PROJECT_ID, FCM_CLIENT_EMAIL, FCM_PRIVATE_KEY, or FCM_SERVICE_ACCOUNT_PATH Your server's .env

A phone's push address belongs to the Firebase project whose files were in the build. Your server can only send to it with a service account from that same project. Neither half reports that the other is missing or mismatched: the app signs in normally, the server starts normally, and nothing arrives.

1. Create the Firebase project

  1. Choose your identifiers first. The Firebase apps are registered with your app's identifiers, so set androidApplicationId and iosBundleId before you start. See Branding.
  2. Create a project in the Firebase console, or use the one your website already uses.
  3. Add an Android app with exactly your androidApplicationId, and download its google-services.json.
  4. Add an iOS app with exactly your iosBundleId, and download its GoogleService-Info.plist.

Firebase is used for push and nothing else. The app contains no Firebase Analytics, Crashlytics or other tracking SDK.

2. The Android build

Put google-services.json in android/app/ and build. There is nothing else to change: the project applies Google's services plugin only when that file is present, and says which way it went on every build:

google-services.json found - Firebase push ENABLED
google-services.json not found - Firebase push DISABLED. The app builds and runs; see the note in android/app/build.gradle.kts to enable it.

The file must come from a Firebase Android app registered with your androidApplicationId. A file issued for any other id stops the build with No matching client found for package name. If you change the id, add an Android app with the new id in Firebase and download its file.

The app already declares Android's notification permission, so Android 13 and later show the system prompt without further changes.

3. The iOS build

The iOS project ships without the Push Notifications capability. Without it, the permission prompt still appears and the customer still agrees, and no notification is ever delivered. The build still archives, and the app only logs the failure, so nothing tells you except the release preflight (below).

  1. Add the capability. In Xcode, select the Runner target, open Signing & Capabilities, press + Capability and add Push Notifications. Xcode creates Runner.entitlements and points the build at it.
  2. Add your Firebase file. Put GoogleService-Info.plist in ios/Runner/ and add it to the Runner target in Xcode.
  3. Upload an APNs key to your Firebase project, in its Cloud Messaging settings. Apple delivers every iOS push; Firebase hands the message to Apple with this key.

Once GoogleService-Info.plist is in the project, the release preflight refuses a build without the capability:

[ios-push] iOS push cannot work: Firebase is configured but the app has no aps-environment entitlement

At the time of writing, push had not been exercised on an iPhone build of this app. Send yourself a test (below) from a TestFlight build before you submit.

4. Your server

Push credentials are environment variables, not admin settings. From the same Firebase project, create a service account key (Project settings → Service accounts → Generate new private key), then set either the three values from it or the path to the file in your server's .env:

FCM_PROJECT_ID="your-project-id"
FCM_CLIENT_EMAIL="firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com"
FCM_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
  • FCM_PRIVATE_KEY is the whole key including its BEGIN/END lines. Its line breaks may be written as \n.
  • Or set FCM_SERVICE_ACCOUNT_PATH to the downloaded JSON file. When it is set, it is used instead of the three values above. Give an absolute path.
  • Restart the backend after changing .env.

FCM is switched on by a non-empty FCM_PROJECT_ID (or FCM_SERVICE_ACCOUNT_PATH). If one of the other two values is then missing, or a value looks like a placeholder (such as your-project-id), the server turns FCM off and logs why, for example Missing FCM_PRIVATE_KEY, or FCM_PROJECT_ID still holds the example value shipped in .env.example — FCM disabled. If you do not use push, leave FCM_PROJECT_ID empty. The details, and web push for browsers (VAPID_*, which the app does not use), are on Notifications.

Treat the service account key as a secret: it goes in the server's .env only, never in app_config.json or anywhere in the app.

Test it

The admin has a push tester under Admin → System → Communication Tools → Notification Service, on the Testing tab. Push sends a real notification titled Test Push Notification to your own account, or to the user ID you enter.

  1. Sign in to the app on a phone, with the account you will test, using a build that contains your Firebase file. On the app's Stay informed sheet, tap Turn on notifications (Continue on an iPhone), then allow notifications in the phone's own prompt. The sheet appears once per install: if you already answered it on this phone, allow notifications for the app in the phone's settings instead.
  2. Send the test from the Testing tab.
  3. Read the result. Under the server's message, Provider Status shows VAPID, FCM and User Has Tokens, each with ✓ or ✗.
Result Meaning
Test push notification sent successfully The server handed it to Firebase. If the phone shows nothing, check the iOS capability and APNs key, or the phone's notification settings for the app
No push providers configured. Set VAPID_* or FCM_* environment variables. The server half is missing or was refused. Read the backend log
User has no push notification subscriptions. Enable push notifications in your browser first. This account has no registered device. For an app user that means the app never registered: the build has no Firebase file, the customer declined the permission, or they have not signed in since the build was installed
Failed to deliver push notification Nothing was sent. Your server sends a push only to an account whose push preference is on, and this message is what the tester shows when it is off. The app turns it on when it registers an account that never chose, so for an app user this usually means they switched push off themselves. Any other error text is Firebase's own reason
FCM: ✗ while VAPID: ✓ The FCM_* values are missing or were refused; web push alone cannot reach the app

The Settings tab of the same screen names only one push provider, and names vapid (Web Push) whenever web push keys are set, even when FCM is working too. Use the Testing tab's FCM result instead.

What customers see

  • One question, asked once. In a build with Firebase, when a customer signs in (with a password, with Google, or after a two-factor code), registers, or opens the app with a saved sign-in, and the phone does not yet allow the app's notifications, the app shows its own Stay informed sheet: "Get notified about deposits, withdrawals and account security events." On Android it offers Turn on notifications and Not now. On an iPhone it has a single Continue, because the iPhone's own prompt that follows has Don't Allow. The phone's prompt appears only after the customer continues. Whatever the answer, the app records it and never raises the subject by itself again on that install. If the phone already allows notifications, nothing is shown and the phone is registered.
  • Without Firebase, a build asks for the phone's permission once per install, the first time it shows a notification that arrived while the app was open.
  • Nothing else to turn on. When the app registers the phone, it sends your server an id for that account on that phone, and your server (Core 6.6.3 or later) switches push on for a customer who has never set a push preference. A customer who switched push off stays off. The id is worked out on the phone from a random secret made once per install and the account, so each account on a shared phone has its own, and it is not a hardware identifier. Builds before 5.4.0 sent no id, so their users received no push until they switched it on themselves; the updated build registers them at their next sign-in or start.
  • Declined? Nothing is sent to that phone, and the app does not ask again. The customer can allow notifications for the app in the phone's settings; the app registers the phone the next time it opens signed in.
  • Signing out removes the phone's push address and tells your server to stop sending to that phone for that account, so the next person to use the handset does not receive the previous account's notifications.

Which events are pushed

Not every notification becomes a push. Your server pushes the events the app can take the customer to — for example deposits, withdrawals, transfers and P2P trade updates. Other notices appear in the app's inbox only. The title of a push is cut at 65 characters and the text at 240.

What tapping a notification does

When it arrives What the customer sees What a tap does
The app is open A notification shown by the app Wallet events open the Wallet tab. P2P, staking, token offering, store, NFT, copy trading, support and account events open the Home tab, where those features are. Anything else leaves the app where it is
The app is in the background or closed A notification shown by the phone Opens the app. It does not go to a particular screen

The app has no deep links. A push cannot open a specific trade, order or screen, and the links in your emails open your website, not the app.

After an update

google-services.json and GoogleService-Info.plist are yours and are not in any release you download. The Push Notifications capability lives in the Xcode project, so taking a new release's ios/Runner.xcodeproj removes it. After every update, copy both Firebase files across and add the capability again. See Updating your app.

What it deliberately does not do

  • No push without your Firebase project. There is no shared or vendor project behind the app.
  • No routing from a background tap. See the table above.
  • No web push in the app. The VAPID_* keys serve browsers only.
  • No analytics. Firebase is in the app for push delivery alone.

Declaring push in the stores' privacy forms is covered on Data safety and privacy.