FCM v1 fid (Firebase Installation ID) target returns 404 UNREGISTERED on iOS, while the full registration token delivers
The Firebase Admin SDK (Python 7.5.0) recently added a fid send target and deprecated token (see docs: https://firebase.google.com/docs/cloud-messaging/send/admin-sdk#send-messages-to-specific-devices).
I'm trying to deliver an FCM notification to an iOS device by its Firebase Installation ID, but every FID-targeted send comes back 404 NOT_FOUND with errorCode: UNREGISTERED. In the exact same call with the same project, same OAuth token, same message payload, targeting the device's full FCM registration token instead returns 200 and delivers the notification (a visible banner when the app is backgrounded).
The FID I'm sending is the value returned by the Installations API (Installations.installationID() on iOS), and it's exactly the prefix of the registration token, which has the shape <FID>:<APNs-suffix>. So the FID is correct and current but for some reason, FCM just won't resolve it to a deliverable iOS registration.
The Android documentation describes an opt-in for FID-based registration (an AndroidManifest.xml flag plus the onRegistered() callback on FirebaseMessagingService), but I can't find any iOS equivalent in the SDK or the docs. It looks like an iOS installation is never registered as a FID-addressable delivery target — so I want to confirm whether there's an iOS-side step I'm missing, or whether FID-based delivery is currently Android-only.
Other stuff I've ruled out:
Auth — the token-targeted send succeeds (200) with the same OAuth token, so it isn't a credential/THIRD_PARTY_AUTH_ERROR problem.
Malformed request — FCM parses the fid field and returns UNREGISTERED, not 400 INVALID_ARGUMENT, so the field is accepted and actively resolved.
Client implementation — reproduced identically on a native Swift app (FirebaseMessaging) and a React Native Firebase app.
SDK version — reproduced on firebase-ios-sdk 11.15.0 and on the latest 12.15.0, including on a freshly deleted-and-recreated installation.
Registration / APNs setup — the app registers for remote notifications and getToken() succeeds; APNs is probably configured correctly (token-targeted sends deliver a visible banner).
The migration fallback — putting the bare FID in the token field (the "token field also accepts FIDs" path) also returns UNREGISTERED.
A stale/reused installation — a brand-new installation minted by the latest SDK behaves the same.
Minimal Repro
$OAUTH is a short-lived access token minted from the service account (scope: https://www.googleapis.com/auth/firebase.messaging). The two requests are identical except for the target field!
URL="https://fcm.googleapis.com/v1/projects/my-project/messages:send"
# (A) target = fid -> FAILS
curl -s -X POST "$URL" \
-H "Authorization: Bearer $OAUTH" -H "Content-Type: application/json" \
-d '{"message":{"fid":"cAbCdEfGhIjKlMnOpQrStU","notification":{"title":"t","body":"b"}}}'
# -> 404
# {"error":{"code":404,"message":"NotRegistered","status":"NOT_FOUND",
# "details":[{"@type":"type.googleapis.com/google.firebase.fcm.v1.FcmError",
# "errorCode":"UNREGISTERED"}]}}
# (B) target = token -> DELIVERS
curl -s -X POST "$URL" \
-H "Authorization: Bearer $OAUTH" -H "Content-Type: application/json" \
-d '{"message":{"token":"cAbCdEfGhIjKlMnOpQrStU:APA91b_EXAMPLE_APNS_SUFFIX","notification":{"title":"t","body":"b"}}}'
# -> 200
# {"name":"projects/my-project/messages/1234567890"}