FCM Token Registration API
This document explains how the GOFA app registers a device push token with the backend.
Why this endpoint exists
A push notification can only be sent after the mobile app has:
- requested notification permission from the user,
- received a native FCM token from Firebase,
- identified the current signed-in user, and
- stored the token in Firestore under that user.
In the current GOFA mobile architecture:
- the Flutter shell gets the native FCM token,
- the WebView frontend asks Flutter for that token through a bridge,
- the frontend sends the token to the backend,
- the backend stores it under the signed-in user document.
Endpoint
POST /api/fcm/register
Authentication
This endpoint requires a signed-in user.
Use one of the following:
Authorization: Bearer <firebase_id_token>- or the authenticated session cookie flow already used by the app
In the current mobile flow, the frontend uses a Firebase ID token.
Request body
{
"fcmToken": "string",
"platform": "ios",
"installationId": "native-1772433667723-17uxidu",
"deviceInfo": {
"source": "flutter_webview",
"environment": "uat",
"app": "silvercare"
}
}
Field meaning
fcmToken: the native FCM token returned by Firebase Messagingplatform: usuallyios,android, orwebinstallationId: a stable installation identifier for one app installation on one devicedeviceInfo: optional metadata for debugging and device tracking
Response
Successful response:
{
"success": true,
"tokenHash": "...",
"tokenKey": "installation:native-1772433667723-17uxidu"
}
How the backend stores tokens
The current implementation stores tokens in the user document under:
Clients/{clientId}/ClientUsers/{uid}/fcmTokens
When installationId is provided, the backend uses this key format:
installation:{installationId}
This is important because it prevents duplicate token entries for the same app installation.
Important implementation detail
Do not generate installationId in the WebView using localStorage if the app can load from different origins.
Why:
- Web storage is scoped by origin.
- If the app runs on different URLs such as
https://...,http://192.168.x.x:5173, or another dev host, the browser storage changes. - That produces multiple installation records for the same phone.
Recommended approach:
- Generate and persist
installationIdin the Flutter shell. - Return it to the frontend through the WebView bridge.
Current GOFA implementation
Relevant backend file:
gofa-web-nextjs/src/app/api/fcm/register/route.ts
Relevant frontend files:
sc-gofa-beta1/src/services/fcmTokenService.tssc-gofa-beta1/src/services/nativeFcmRegistrationService.ts
Relevant Flutter file:
gofa-silvercare-flutter/lib/screens/webview_screen.dart
Recommended registration timing
A mature app should not register a token on every render.
Recommended timing:
- after the user signs in successfully,
- after notification permission is granted,
- after a token refresh event,
- when the signed-in user changes,
- optionally as a low-frequency heartbeat.
Troubleshooting
Problem: duplicate fcmTokens entries
Likely cause:
- unstable
installationId
Fix:
- move
installationIdgeneration to native Flutter storage
Problem: token exists but pushes do not arrive
Possible causes:
- APNs key is not configured in Firebase for the iOS app
- notification permission is not granted
- the backend is sending only
dataand not a notification payload