Apps using the deprecated FCM legacy APIs for HTTP and XMPP should migrate to the HTTP v1 API at the earliest opportunity. Sending messages (including upstream messages) with those APIs was deprecated on June 20, 2023, and shutdown begins on July 22, 2024.
Source: https://firebase.google.com/docs/cloud-messaging/migrate-v1
I am currently using .NET (C#), but the process will be similar for other technologies as well. Here’s how I migrated from legacy FCM APIs to HTTP v1:
Update the server Endpoint
from
https://fcm.googleapis.com/fcm/send
to
https://fcm.googleapis.com/v1/projects/<your-project-id>/messages:send
Update authorization of send requests
Previously, we had to pass the ServerKey as Authorization, but in this new version, that is no longer required. Instead, we will use a short-lived OAuth 2.0 access token, which will be generated for each request. Below is the code for both the old and new versions.
Old version:
public async Task<bool> SendPushNotifcationAsync(object body)
{
using (HttpClient client = new HttpClient())
{
string fcmEndpoint = "https://fcm.googleapis.com/fcm/send";
string serverKey = "THE_SERVER_KEY";
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"key={serverKey}");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
string jsonBody = JsonConvert.SerializeObject(body);
HttpContent content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(fcmEndpoint, content);
return response.IsSuccessStatusCode;
}
}
New version:
# New function to get access token
private async Task<string> GetAccessTokenAsync()
{
# firebase-config.json is the file downloaded from
#Firebase Console > Project Settings > Service Accounts > Generate new Private Key
string serviceAccountKeyPath = "./firebase-config.json";
var credential = GoogleCredential.FromFile(serviceAccountKeyPath)
.CreateScoped("https://www.googleapis.com/auth/firebase.messaging");
var token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
return token;
}
public async Task<bool> SendPushNotifcationAsync(object body)
{
using (HttpClient client = new HttpClient())
{
string fcmEndpoint = "https://fcm.googleapis.com/v1/projects/<your-project-id>/messages:send";
string accessToken = await GetAccessTokenAsync();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string jsonBody = JsonConvert.SerializeObject(body);
HttpContent content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(fcmEndpoint, content);
return response.IsSuccessStatusCode;
}
}
- Update the payload of send requests
There are also some changes in the payload that we need to modify. Similar to section #2, I will provide the code for both old and new versions below.
Old version:
var message = new
{
to = <device_token>,
notification = new
{
title = <title>,
body = <body>,
sound = "Tri-tone"
},
data = <your_data>
};
New version:
var message = new
{
message = new
{
token = <device_token>,
notification = new
{
title = <title>,
body = <body>
},
android = new
{
notification = new
{
sound = "default"
}
},
apns = new
{
payload = new
{
aps = new
{
sound = "default"
}
}
},
data = <your_data>
}
};
Note: Unlike the legacy messaging API, the HTTP v1 API does not support nested JSON values in the
data
field. A conversion from JSON to string is required.Example:
Old version:
var message = new { message = new { # ...others data = new { route = "/home", arguments = new { userId = "userA" time = "today" } } } };
New version:
var message = new { message = new { # ...others data = new { route = "/home", arguments = JsonConvert.SerializeObject(new { userId = "userA" time = "today" }) } } };
That’s how I migrated from the legacy FCM APIs to HTTP v1.
Happy coding, and good luck with your migration!