Send messages to multiple devices on Apple platforms
Stay organized with collectionsSave and categorize content based on your preferences.
To target a message to multiple devices, useTopic messaging. This
feature allows you to
send a message to multiple devices that have opted in to a particular topic.
This tutorial focuses on sending topic messages from your app server using theAdmin SDKorREST APIforFCM, and receiving and handling them
in an Apple app. This page lists all the steps to achieve this, from setup to
verification — so it may cover steps you already completed if you haveset up an Apple client appforFCMor worked through the steps toSend your First Message.
If you don't already have an Xcode project and just want to try out a Firebase
product, you can download one of ourquickstart samples.
Create a Firebase project
Before you can add Firebase to your Apple app, you need to create a Firebase
project to connect to your app. VisitUnderstand Firebase Projectsto learn more about
Firebase projects.
To use Firebase in your Apple app, you need to register your app with your
Firebase project. Registering your app is often called "adding" your app to your
project.
ClickDownload GoogleService-Info.plistto obtain your app's
Firebase config file (GoogleService-Info.plist).
What do you need to know about this config file?
The Firebase config file contains unique, but non-secret identifiers for
your project and app. To learn more about this config file, visitUnderstand Firebase
Projects.
Make sure the config file name is not appended with additional characters,
like(2).
Move your config file into the root of your Xcode project. If prompted,
select to add the config file to all targets.
If you have multiple bundle IDs in your project, you must associate each bundle
ID with a registered app in theFirebaseconsole so that each app can have
its ownGoogleService-Info.plistfile.
Add Firebase SDKs to your app
Use Swift Package Manager to install and manage Firebase dependencies.
In Xcode, with your app project open, navigate toFile > Add Packages.
When prompted, add the Firebase Apple platforms SDK repository:
https://github.com/firebase/firebase-ios-sdk.git
Choose theFirebase Cloud Messaginglibrary.
Add the-ObjCflag to theOther Linker Flagssection of your target's build settings.
When finished, Xcode will automatically begin resolving and downloading your
dependencies in the background.
Upload your APNs authentication key
Upload your APNs authentication key to Firebase.
If you don't already have an APNs authentication key, make sure to create one in theApple Developer Member Center.
Inside your project in theFirebaseconsole, select the
gear icon, selectProject Settings, and then select theCloud Messagingtab.
InAPNs authentication keyunderiOS app configuration,
click theUploadbutton to upload your development authentication key, or
production authentication key, or both. At least one is required.
Browse to the location where you saved your key, select it, and clickOpen. Add the key ID for the key (available in theApple Developer Member Center) and clickUpload.
Initialize Firebase in your app
You'll need to add Firebase initialization code to your application. Import
the Firebase module and configure a shared instance as shown:
Import theFirebaseCoremodule in yourUIApplicationDelegate, as well as any otherFirebase modulesyour app delegate uses.
For example, to useCloud FirestoreandAuthentication:
Configure aFirebaseAppshared instance in your app delegate'sapplication(_:didFinishLaunchingWithOptions:)method:
SwiftUI
// Use Firebase library to configure APIsFirebaseApp.configure()
Swift
// Use Firebase library to configure APIsFirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs[FIRAppconfigure];
If you're using SwiftUI, you must create an application delegate and attach it
to yourAppstruct viaUIApplicationDelegateAdaptororNSApplicationDelegateAdaptor. You must also disable app delegate swizzling. For
more information, see theSwiftUI instructions.
SwiftUI
@mainstructYourApp:App{// register app delegate for Firebase setup@UIApplicationDelegateAdaptor(AppDelegate.self)vardelegatevarbody:someScene{WindowGroup{NavigationView{ContentView()}}}}
Register for remote notifications
Either at startup, or at the desired point in your application flow,
register your app for remote notifications. CallregisterForRemoteNotificationsas shown:
Client apps can subscribe to any existing topic, or they can create a new
topic. When a client app subscribes to a new topic name (one that does
not already exist for your Firebase project), a new topic of that name is
created inFCMand any client can subsequently subscribe to it.
To subscribe to a topic, call the subscription method
from your application's main thread (FCMis not thread-safe).
If the subscription request fails initially,FCMretries automatically.
For cases where the subscription cannot be completed,
the subscription throws an error that you can catch
in a completion handler as shown:
Swift
Messaging.messaging().subscribe(toTopic:"weather"){errorinprint("Subscribed to weather topic")}
This call makes an
asynchronous request to theFCMbackend and subscribes the client to
the given topic. Before callingsubscribeToTopic:topic, make sure that the
client app instance has already received a registration token via the
callbackdidReceiveRegistrationToken.
Each time the app starts,FCMmakes sure that all requested topics have been subscribed. To
unsubscribe, callunsubscribeFromTopic:topic,
andFCMunsubscribes from the topic in the background.
Receive and handle topic messages
FCMdelivers topic messages in the same way as other downstream
messages.
funcapplication(_application:UIApplication,didReceiveRemoteNotificationuserInfo:[AnyHashable:Any])async->UIBackgroundFetchResult{// If you are receiving a notification message while your app is in the background,// this callback will not be fired till the user taps on the notification launching the application.// TODO: Handle data of notification// With swizzling disabled you must let Messaging know about the message, for Analytics// Messaging.messaging().appDidReceiveMessage(userInfo)// Print message ID.ifletmessageID=userInfo[gcmMessageIDKey]{print("Message ID:\(messageID)")}// Print full message.print(userInfo)returnUIBackgroundFetchResult.newData}
-(void)application:(UIApplication*)applicationdidReceiveRemoteNotification:(NSDictionary*)userInfofetchCompletionHandler:(void(^)(UIBackgroundFetchResult))completionHandler{// If you are receiving a notification message while your app is in the background,// this callback will not be fired till the user taps on the notification launching the application.// TODO: Handle data of notification// With swizzling disabled you must let Messaging know about the message, for Analytics// [[FIRMessaging messaging] appDidReceiveMessage:userInfo];// ...// Print full message.NSLog(@"%@",userInfo);completionHandler(UIBackgroundFetchResultNewData);}
After you have created a topic, either by subscribing client app instances to
the topic on the client side or via theserver API, you can send messages to the
topic. If this is your first time building send requests forFCM,
see the guide toyour server environment andFCMfor
important background and setup information.
In your sending logic on the backend, specify the desired topic name
as shown:
Node.js
// The topic name can be optionally prefixed with "/topics/".consttopic='highScores';constmessage={data:{score:'850',time:'2:45'},topic:topic};// Send a message to devices subscribed to the provided topic.getMessaging().send(message).then((response)=>{// Response is a message ID string.console.log('Successfully sent message:',response);}).catch((error)=>{console.log('Error sending message:',error);});
Java
// The topic name can be optionally prefixed with "/topics/".Stringtopic="highScores";// See documentation on defining a message payload.Messagemessage=Message.builder().putData("score","850").putData("time","2:45").setTopic(topic).build();// Send a message to the devices subscribed to the provided topic.Stringresponse=FirebaseMessaging.getInstance().send(message);// Response is a message ID string.System.out.println("Successfully sent message: "+response);
# The topic name can be optionally prefixed with "/topics/".topic='highScores'# See documentation on defining a message payload.message=messaging.Message(data={'score':'850','time':'2:45',},topic=topic,)# Send a message to the devices subscribed to the provided topic.response=messaging.send(message)# Response is a message ID string.print('Successfully sent message:',response)
// The topic name can be optionally prefixed with "/topics/".topic:="highScores"// See documentation on defining a message payload.message:=&messaging.Message{Data:map[string]string{"score":"850","time":"2:45",},Topic:topic,}// Send a message to the devices subscribed to the provided topic.response,err:=client.Send(ctx,message)iferr!=nil{log.Fatalln(err)}// Response is a message ID string.fmt.Println("Successfully sent message:",response)
// The topic name can be optionally prefixed with "/topics/".vartopic="highScores";// See documentation on defining a message payload.varmessage=newMessage(){Data=newDictionary<string,string>(){{"score","850"},{"time","2:45"},},Topic=topic,};// Send a message to the devices subscribed to the provided topic.stringresponse=awaitFirebaseMessaging.DefaultInstance.SendAsync(message);// Response is a message ID string.Console.WriteLine("Successfully sent message: "+response);
To send a message to acombinationof topics,
specify acondition, which is a boolean expression that specifies the
target topics. For example, the following condition will send messages to
devices that are subscribed toTopicAand eitherTopicBorTopicC:
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
FCMfirst evaluates any conditions in parentheses, and then evaluates
the expression from left to right. In the above expression, a user subscribed to
any single topic does not receive the message. Likewise, a user who does not
subscribe toTopicAdoes not receive the message. These combinations do
receive it:
TopicAandTopicB
TopicAandTopicC
You can include up to five topics in your conditional expression.
To send to a condition:
Node.js
// Define a condition which will send to devices which are subscribed// to either the Google stock or the tech industry topics.constcondition='\'stock-GOOG\' in topics || \'industry-tech\' in topics';// See documentation on defining a message payload.constmessage={notification:{title:'$FooCorp up 1.43% on the day',body:'$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'},condition:condition};// Send a message to devices subscribed to the combination of topics// specified by the provided condition.getMessaging().send(message).then((response)=>{// Response is a message ID string.console.log('Successfully sent message:',response);}).catch((error)=>{console.log('Error sending message:',error);});
Java
// Define a condition which will send to devices which are subscribed// to either the Google stock or the tech industry topics.Stringcondition="'stock-GOOG' in topics || 'industry-tech' in topics";// See documentation on defining a message payload.Messagemessage=Message.builder().setNotification(Notification.builder().setTitle("$GOOG up 1.43% on the day").setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.").build()).setCondition(condition).build();// Send a message to devices subscribed to the combination of topics// specified by the provided condition.Stringresponse=FirebaseMessaging.getInstance().send(message);// Response is a message ID string.System.out.println("Successfully sent message: "+response);
# Define a condition which will send to devices which are subscribed# to either the Google stock or the tech industry topics.condition="'stock-GOOG' in topics || 'industry-tech' in topics"# See documentation on defining a message payload.message=messaging.Message(notification=messaging.Notification(title='$GOOG up 1.43% on the day',body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',),condition=condition,)# Send a message to devices subscribed to the combination of topics# specified by the provided condition.response=messaging.send(message)# Response is a message ID string.print('Successfully sent message:',response)
// Define a condition which will send to devices which are subscribed// to either the Google stock or the tech industry topics.condition:="'stock-GOOG' in topics || 'industry-tech' in topics"// See documentation on defining a message payload.message:=&messaging.Message{Data:map[string]string{"score":"850","time":"2:45",},Condition:condition,}// Send a message to devices subscribed to the combination of topics// specified by the provided condition.response,err:=client.Send(ctx,message)iferr!=nil{log.Fatalln(err)}// Response is a message ID string.fmt.Println("Successfully sent message:",response)
// Define a condition which will send to devices which are subscribed// to either the Google stock or the tech industry topics.varcondition="'stock-GOOG' in topics || 'industry-tech' in topics";// See documentation on defining a message payload.varmessage=newMessage(){Notification=newNotification(){Title="$GOOG up 1.43% on the day",Body="$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",},Condition=condition,};// Send a message to devices subscribed to the combination of topics// specified by the provided condition.stringresponse=awaitFirebaseMessaging.DefaultInstance.SendAsync(message);// Response is a message ID string.Console.WriteLine("Successfully sent message: "+response);
REST
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"condition": "'dogs' in topics || 'cats' in topics",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
}
}
}
cURL command:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"notification": {
"title": "FCM Message",
"body": "This is a Firebase Cloud Messaging Topic Message!",
},
"condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-09 UTC."],[],[],null,[]]