> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brudcast.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Firebase for push notifications

> Create a Firebase service account key, add it as an app in Brudcast, and send a test notification to a real device.

export const DemoVideo = ({id, title, embedUrl, src, poster, duration}) => {
  if (embedUrl) {
    return <figure className="brd-media" data-media-id={id}>
        <iframe className="brd-media-frame w-full aspect-video" src={embedUrl} title={title} allow="accelerometer; autoplay; clipboard-write; encrypted-media; picture-in-picture" allowFullScreen />
      </figure>;
  }
  if (src) {
    return <figure className="brd-media" data-media-id={id}>
        <video className="brd-media-frame w-full aspect-video" src={src} poster={poster} controls playsInline preload="metadata" />
      </figure>;
  }
  const label = duration ? `Video walkthrough coming soon · ${duration}` : "Video walkthrough coming soon";
  return <Placeholder id={id} kind="video" label={label} description={title} ratio="16 / 9" icon={<PlayIcon />} />;
};

export const Loop = ({id, src, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="loop" label="Animation coming soon" description={alt} icon={<PlayIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <video className="brd-media-frame" src={src} autoPlay muted loop playsInline aria-label={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

export const Screenshot = ({id, src, srcDark, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="screenshot" label="Screenshot coming soon" description={alt} icon={<ImageIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <img className="brd-media-frame block dark:hidden" src={src} alt={alt} />
      <img className="brd-media-frame hidden dark:block" src={srcDark || src} alt={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

Brudcast sends push notifications through Firebase Cloud Messaging, using your own Firebase project.
All it needs from you is a service account key for that project. Your app keeps using the Firebase
SDK as it does today. There is no Brudcast SDK to add.

By the end of this page you'll have an active app in Brudcast that can send notifications through
your Firebase project, and you'll have seen one arrive on a device.

<Screenshot id="ss-push-connect-firebase-hero-apps-list" alt="The Apps tab listing one app with status Active, its Firebase project ID, platforms Android and iOS, and its active device count" />

<Info>
  **Before you start**, you need:

  * A Push subscription. See [Plans and subscriptions](/billing/plans-and-subscriptions).
  * A Firebase project that contains your app, and permission to create service accounts for it in
    the Google Cloud console.
  * For the last step, a device token from a test device running your app.
</Info>

<Accordion title="Watch the walkthrough" icon="circle-play">
  <DemoVideo id="V18" title="Connect Firebase for push notifications" duration="3 min" />
</Accordion>

## Which devices Firebase reaches

| Platform | Reachable when                                                                                  |
| -------- | ----------------------------------------------------------------------------------------------- |
| Android  | Your app receives messages through Firebase Cloud Messaging                                     |
| iOS      | Your app uses the Firebase SDK, and your Firebase project is set up to deliver to Apple devices |
| Web      | Your site uses the Firebase JavaScript SDK                                                      |

Firebase Cloud Messaging is the only provider you can connect, so an iOS app or a website has to use
the Firebase SDK to be reachable.

## One Brudcast app per Firebase project

A device token only works with the Firebase project that issued it. Brudcast therefore ties every
token to the app it was registered through, and each app in Brudcast is exactly one Firebase
project.

* If your Android app, iOS app and website share one Firebase project, add one app in Brudcast.
* If they use separate projects, for example one for production and one for testing, add one app
  per project, each with its own key.

## Create a service account key

Every Firebase project is also a Google Cloud project with the same project ID, so you create the
service account in the Google Cloud console.

<Steps>
  <Step title="Open service accounts">
    Sign in to the Google Cloud console, select your Firebase project, and go to
    **IAM & Admin > Service accounts**.
  </Step>

  <Step title="Create the account">
    Select **Create service account** and give it a name you'll recognize later, for example
    `brudcast-push`.
  </Step>

  <Step title="Grant the role">
    Give the account the **Firebase Cloud Messaging API Admin** role and nothing else. That role
    lets it send messages through Firebase Cloud Messaging, which is all Brudcast needs.

    <Screenshot id="ss-push-connect-firebase-01-service-account-role" alt="A new Google Cloud service account being granted the Firebase Cloud Messaging API Admin role" />
  </Step>

  <Step title="Download a JSON key">
    Open the new account, go to **Keys**, and select **Add key > Create new key**. Choose **JSON**
    and select **Create**. Your browser downloads the key file.
  </Step>
</Steps>

<Note>
  The Firebase console has a shortcut: **Project settings > Service accounts > Generate new private
  key**. That key works too, but it belongs to the Firebase Admin SDK account, which can do far more
  in your project than send notifications. A dedicated account with only the Firebase Cloud
  Messaging API Admin role limits the damage if the key ever leaks.
</Note>

### What's in the key file

The key file is JSON. Brudcast reads three fields from it and ignores the rest. Upload the file
exactly as it was downloaded.

```json theme={"system"}
{
  "type": "service_account",
  "project_id": "acme-prod-1234",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "brudcast-push@acme-prod-1234.iam.gserviceaccount.com"
}
```

| Field          | Used for                                                                          |
| -------------- | --------------------------------------------------------------------------------- |
| `project_id`   | The Firebase project. It must match the app's **Firebase project ID** in Brudcast |
| `client_email` | The service account Brudcast signs in as                                          |
| `private_key`  | Signing Brudcast's requests to Firebase                                           |

## Add the app in Brudcast

<Steps>
  <Step title="Open the Add App dialog">
    Go to **Channels > Push**, open the **Apps** tab, and select **Add App**. The first step on the
    **Setup** tab, **Connect your app for push**, opens the same dialog.

    <Screenshot id="ss-push-connect-firebase-02-add-app" alt="The Add App dialog with the Name, Provider, Service account key, Firebase project ID and Platforms fields" />
  </Step>

  <Step title="Fill in the app details">
    | Field                         | What to enter                                                                                                                                                                                                    |
    | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | **Name**                      | A name you'll recognize, such as `Acme Android`. Up to 120 characters                                                                                                                                            |
    | **Provider**                  | **Firebase Cloud Messaging**                                                                                                                                                                                     |
    | **Service account key**       | Drop in the `.json` file. Brudcast checks that it's a service account key and shows the service account's email address                                                                                          |
    | **Firebase project ID**       | Filled in from the key file. It has to match the `project_id` in the file, or Brudcast refuses the app                                                                                                           |
    | **Platforms**                 | The platforms this Firebase project serves: **Android**, **iOS**, **Web**. Android and iOS are ticked to start with. Pick at least one. This is for your reference and doesn't change how notifications are sent |
    | **Make this the default app** | Optional                                                                                                                                                                                                         |

    Select **Add App**. Brudcast confirms that the app was added and starts validating its key.
  </Step>

  <Step title="Wait for validation">
    The app starts as **Validating** while Brudcast checks the key with Firebase, without sending
    anything to a device. This usually takes a few seconds. Then it becomes **Active**, or
    **Credential invalid** with Firebase's reason shown under the status. No review by Brudcast is
    involved.

    If the key was rejected, fix the problem in Google Cloud, then open the app's **More actions**
    menu and select **Replace credential**. To re-run the check on the same key, select
    **Validate again**.

    <Loop id="lp-push-connect-firebase-validate" alt="An app's status changing from Validating to Active in the Apps table" />
  </Step>

  <Step title="Choose a default app (optional)">
    In the app's **More actions** menu, select **Set as default**. Only an active app can be the
    default. The app gets a **Default** badge in the list.
  </Step>

  <Step title="Send a test">
    On the app's row, select **Send a test** (the paper-plane icon). It's only there while the app
    is active.

    Paste a **Device token** from your test device, keep or change the **Title** and **Body**, and
    select **Send Test**. The token isn't saved to any contact. The test is sent in the background,
    and the result appears in the dialog once Firebase has answered.

    <Screenshot id="ss-push-connect-firebase-06-test-result" alt="The Send a Test dialog showing Accepted by the provider under the device token, title and body fields" />

    **Accepted by the provider** means Firebase took the notification for delivery. Firebase doesn't
    confirm that it reached the device, so check the device itself. **Test failed** shows the reason.
  </Step>
</Steps>

## What happens next

* Register the device tokens your app collects on your contacts. See
  [Register device tokens](/channels/push/register-device-tokens).
* Add Push to a campaign. See [Write the notification](/channels/push/send-your-first-push#write-the-notification).
* If Firebase later rejects the key, including partway through a campaign, the app becomes
  **Credential invalid** and stops sending. Brudcast tells you with a notification in the dashboard
  and an email.

## Keep the key safe

Anyone holding the key file can send notifications to your users.

* Upload it to Brudcast, then delete your downloaded copy or move it into your secrets manager.
* Brudcast stores the key securely and never shows it again, in the dashboard or through the API.
  The **Apps** table shows the Firebase project ID instead.
* To rotate it, create a new key on the same service account, select **Replace credential** on the
  app in Brudcast, then delete the old key in Google Cloud.
* If you delete a key that Brudcast is still using, the app turns **Credential invalid** the next
  time Brudcast uses it.

## Manage an app

| Action                 | Where                 | What it does                                                                                                   |
| ---------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Send a test**        | The paper-plane icon  | Sends one notification to a device token you enter. Only for **Active** apps                                   |
| **Edit**               | The pencil icon       | Change the name or the platforms. The key can't be changed here                                                |
| **Replace credential** | **More actions** menu | Upload a new key. The app goes back to **Validating** and doesn't send until Firebase accepts the new key      |
| **Validate again**     | **More actions** menu | Check the current key with Firebase again, for example after you fix the service account's role                |
| **Set as default**     | **More actions** menu | Make this the default app. Only for **Active** apps                                                            |
| **Disable**            | **More actions** menu | Stop the app and delete its key. Its devices can't be reached, and campaigns that name it fail the send checks |

## Troubleshooting

<AccordionGroup>
  <Accordion title="This file is not valid JSON. Download the service account key again from the Firebase console." icon="circle-alert">
    **Why:** the file isn't the JSON key Google Cloud generated, or it was changed after download.

    **Fix:** create a new key for the service account and upload the new file without opening or
    editing it.
  </Accordion>

  <Accordion title="This file is not a Firebase service account key." icon="circle-alert">
    **Why:** the file is valid JSON but not a service account key. A common mix-up is uploading the
    app's Firebase config file instead.

    **Fix:** use the service account key file. It contains `project_id`, `client_email` and
    `private_key`.
  </Accordion>

  <Accordion title="This must match the project_id in the service account file" icon="circle-alert">
    **Why:** the **Firebase project ID** field doesn't match the key file you uploaded.

    **Fix:** clear the field and upload the key again so it fills in, or upload the key for the
    project you meant.
  </Accordion>

  <Accordion title="The app shows Credential invalid" icon="circle-alert">
    **Why:** Firebase rejected the key. The reason from Firebase is shown under the status. The usual
    causes are a service account without the **Firebase Cloud Messaging API Admin** role, a key that
    was deleted in Google Cloud, or the **Firebase Cloud Messaging API** being turned off for the
    project.

    **Fix:** check the role, and check that the **Firebase Cloud Messaging API** is enabled under
    **APIs & Services** in the Google Cloud console. Then select **Validate again**, or use
    **Replace credential** with a new key. More fixes in
    [Push troubleshooting](/channels/push/send-your-first-push#troubleshooting).
  </Accordion>

  <Accordion title="Subscribe to Push" icon="circle-alert">
    **Why:** your organization doesn't have a Push subscription, so apps can't be added.

    **Fix:** pick a Push plan in **Billing & Plans**. See
    [Plans and subscriptions](/billing/plans-and-subscriptions).
  </Accordion>
</AccordionGroup>

## Related

<Columns cols={2}>
  <Card title="Register device tokens" icon="smartphone" href="/channels/push/register-device-tokens">
    Store tokens on contacts through the API.
  </Card>

  <Card title="Push overview" icon="bell" href="/channels/push/overview">
    How apps, devices and campaigns fit together.
  </Card>

  <Card title="Push troubleshooting" icon="wrench" href="/channels/push/send-your-first-push#troubleshooting">
    Credentials, devices and tokens.
  </Card>
</Columns>
