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.
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
- Choose your identifiers first. The Firebase apps are registered with
your app's identifiers, so set
androidApplicationIdandiosBundleIdbefore you start. See Branding. - Create a project in the Firebase console, or use the one your website already uses.
- Add an Android app with exactly your
androidApplicationId, and download itsgoogle-services.json. - Add an iOS app with exactly your
iosBundleId, and download itsGoogleService-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).
- Add the capability. In Xcode, select the Runner target, open
Signing & Capabilities, press + Capability and add Push
Notifications. Xcode creates
Runner.entitlementsand points the build at it. - Add your Firebase file. Put
GoogleService-Info.plistinios/Runner/and add it to the Runner target in Xcode. - 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 entitlementAt 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_KEYis the whole key including itsBEGIN/ENDlines. Its line breaks may be written as\n.- Or set
FCM_SERVICE_ACCOUNT_PATHto 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.
- 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.
- Send the test from the Testing tab.
- 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.