Authorize send requests

Requests sent to FCM from your app server or trusted environment must be authorized. Note these important differences between legacy HTTP and HTTP v1 API authorization:

  • The FCM HTTP v1 API uses a short-lived OAuth 2.0 access token generated for a service account associated with your Firebase project.
  • The legacy protocols use long-lived API keys retrieved from the Firebase console.

In both cases, you must add the required credential to each message request sent to FCM. Always make sure to use the right kind of credential; an API key will only work to authorize requests to the legacy API, and an access token will only work with the HTTP v1 API.

Authorize HTTP v1 send requests

Every Firebase project has a default service account. You can use this account to call Firebase server APIs from your app server or trusted environment. If you use a different service account, make sure it has Editor or Owner permissions.

To authenticate the service account and authorize it to access Firebase services, you must generate a private key file in JSON format, then use this key to retrieve a short-lived OAuth 2.0 access token. After you have a valid access token, you can add it in your server requests as required by various Firebase services, such as Firebase Remote Config, Firebase Cloud Messaging, or Firebase Hosting.

To generate a private key file for your service account:

  1. In the Firebase console, open Settings > Service Accounts.

  2. Click Generate New Private Key, then confirm by clicking Generate Key.

  3. Securely store the JSON file containing the key. You'll need this JSON file to complete the next step.

To retrieve an access token:

To retrieve the access token, you can use the Google API Client Library for your preferred language, referencing the private key JSON file as shown:


 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    var key = require('./service-account.json');
    var jwtClient = new google.auth.JWT(
    jwtClient.authorize(function(err, tokens) {
      if (err) {


def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      'service-account.json', SCOPES)
  access_token_info = credentials.get_access_token()
  return access_token_info.access_token


private static String getAccessToken() throws IOException {
  GoogleCredential googleCredential = GoogleCredential
      .fromStream(new FileInputStream("service-account.json"))
  return googleCredential.getAccessToken();

After your access token expires, the token refresh method is called automatically to retrieve an updated access token.

To authorize access to FCM, request the scope

To add the access token to an HTTP request header:

Add the token as the value of the Authorization header in the format Authorization: Bearer <access_token>:


headers: {
  'Authorization': 'Bearer ' + accessToken


headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',


HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

Authorize legacy protocol send requests

With the HTTP legacy protocol, each request must contain the server key from the Cloud Messaging tab of the Firebase console Settings pane. For XMPP, you must use the same server key to establish a connection.

Authorize HTTP requests

A message request consists of two parts: the HTTP header and the HTTP body. The HTTP header must contain the following headers:

  • Authorization: key=YOUR_SERVER_KEY
    Make sure this is the server key, whose value is available in the Cloud Messaging tab of the Firebase console Settings pane. Android, iOS, and browser keys are rejected by FCM.
  • Content-Type: application/json for JSON; application/x-www-form-urlencoded;charset=UTF-8 for plain text.
    If Content-Type is omitted, the format is assumed to be plain text.

For example:


  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
  "data" : {

See Build Send Requests for full detail on creating send requests. The Legacy HTTP Protocol Reference provides a list of all the parameters your message can contain.

Checking the validity of a server key

If you receive authentication errors when sending messages, check the validity of your Server key. For example, on Android, run the following command:


# curl --header "Authorization: key=$api_key" \
       --header Content-Type:"application/json" \ \
       -d "{\"registration_ids\":[\"ABC\"]}"

If you receive a 401 HTTP status code, your Server key is not valid.

Authorize an XMPP connection

With XMPP, you can maintain a persistent, asynchronous, bidirectional connection to FCM servers. The connection can be used to send and receive messages between your server and your users' FCM-connected devices.

You can use most XMPP libraries to manage a long-lived connection to FCM. XMPP endpoint runs at When testing functionality with non-production users, you should instead connect to the pre-production server at (note the different port).

Regular testing on pre-production (a smaller environment where the latest FCM builds run) is beneficial for isolating real users from test code. Test devices and test code connecting to should use a different FCM sender ID to avoid any risks of sending test messages to production users or sending upstream messages from production traffic over test connections.

The connection has two important requirements:

  • You must initiate a Transport Layer Security (TLS) connection. Note that FCM doesn't currently support the STARTTLS extension.
  • FCM requires a SASL PLAIN authentication mechanism using <your_FCM_Sender_Id> (FCM sender ID) and the Server key as the password. These values are available in the Cloud Messaging tab of the Firebase console Settings pane.

If at any point the connection fails, you should immediately reconnect. There is no need to back off after a disconnect that happens after authentication. For each sender ID, FCM allows 1000 connections in parallel.

The following snippets illustrate how to perform authentication and authorization for an XMPP connection to FCM.

XMPP server

The XMPP server requests a connection to FCM

<stream:stream to=""
        version="1.0" xmlns="jabber:client"


FCM opens the connection and requests an auth mechanism, including the PLAIN method.

  <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">

XMPP server

The XMPP server must respond using the PLAIN auth method, providing the server key from the Cloud Messaging tab of the Firebase console Settings pane.

<auth mechanism="PLAIN"


<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

XMPP server

<stream:stream to=""
        version="1.0" xmlns="jabber:client"


  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>

XMPP server

<iq type="set">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></bind>


<iq type="result">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">

Note: FCM does not use the bound resource while routing messages.

See Build Send Requests for full detail on creating send requests. The Legacy XMPP Protocol Reference provides a list of all the parameters your message can contain.

Send feedback about...

Need help? Visit our support page.