> For the complete documentation index, see [llms.txt](https://docs.buildnatively.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildnatively.com/natively-platform/features/notifications/firebase-push-notifications-advanced.md).

# Firebase - Push Notifications (Advanced)

## What are Firebase Push Notifications?

Natively provides built-in support for [Firebase Cloud Messaging](https://firebase.google.com/products/cloud-messaging) (FCM) to handle push notification delivery for your app. Firebase manages device tokens and topic-based targeting through its own console, and you send notifications either directly from the Firebase console or via the Firebase Cloud Messaging API.

{% hint style="warning" %}
If you don't have a specific reason to manage Firebase yourself, consider [OneSignal - Push Notifications](/natively-platform/features/notifications/onesignal-push-notifications.md) instead, which offers a simpler dashboard-driven setup and a much easier API for sending notifications.
{% endhint %}

## Prerequisites

{% hint style="success" %}
This feature requires the **Unlimited** or **Lifetime** plan. [See all plans](/getting-started/subscription-plans.md)
{% endhint %}

* A [Firebase](https://firebase.google.com/) account.
* **iOS:**
  * An [Apple Developer](https://developer.apple.com/account) account.
  * Your iOS app is already [published](/natively-platform/app-info/ios-build.md) in the Natively Dashboard.
* **Android:**
  * Your Android app is already [published](/natively-platform/app-info/android-build.md) in the Natively Dashboard.

## Pre-Firebase Configuration (iOS only)

To send push notifications to iOS devices, Firebase requires the **Push Notifications** **App Capability** enabled on your Bundle ID and an **APNs authentication key** from your Apple Developer account.

{% stepper %}
{% step %}

#### App Capabilities Configuration

{% hint style="info" %}
App capabilities define what system-level features your app is allowed to use on iOS. Before Natively can include the **Firebase Push Notifications** feature in your build, the **Push Notifications** capability must be explicitly enabled in your Apple Developer account for your app's Bundle ID.
{% endhint %}

1. Open your [Apple Developer](https://developer.apple.com/account) account and navigate to [Certificates, IDs & Profiles > Identifiers](https://developer.apple.com/account/resources/identifiers/list).
2. Select your app's Bundle ID.
3. Scroll down the **Capabilities** list and enable **Push Notifications**.
4. Click **Save** and confirm.
   {% endstep %}

{% step %}

#### Set up APNs Authentication Key

1. Open your [Apple Developer](https://developer.apple.com/account) account and navigate to [Certificates, IDs & Profiles > Keys](https://developer.apple.com/account/resources/authkeys/list).
2. Click **+** to register a new key.
3. Enter **Key Name**.
4. Select the **Apple Push Notifications service (APNs)** checkbox and click **Configure**.
5. In the **Environment** dropdown menu, select **Sandbox & Production** and click **Save**.
6. Click **Continue**, then **Register**.
7. **Download** the generated `.p8` key.

{% hint style="warning" %}
You can only download this file once, so save it securely. If you lose it, you'll need to revoke the key and generate a new one.
{% endhint %}
{% endstep %}

{% step %}

#### Gather your credentials

Collect:

* **Key ID** - located in the row of the key you just created. Make sure it matches the downloaded `.p8` file.
* **Team ID** - located in your [Apple Developer](https://developer.apple.com/account) account under **Membership details**.

You'll need these for [Firebase iOS Platform configuration](#ios).
{% endstep %}
{% endstepper %}

## Firebase Configuration

To send push notifications through Firebase, you'll need a Firebase project and Platforms configured for your app.

{% stepper %}
{% step %}

#### Create or open your Firebase Project

1. Go to the [Firebase console](https://console.firebase.google.com/).
2. If you don’t have a project yet, click **Create a project** and complete the setup.
3. If you already have a project, **select it**.
   {% endstep %}

{% step %}

#### Confirm Firebase Cloud Messaging API v1 is enabled

While on the **Project Overview** page, select **Settings > General** from the left sidebar, then go to the **Cloud Messaging** tab.

{% hint style="success" %}
**Firebase Cloud Messaging API (V1)** is enabled by default for most projects.&#x20;
{% endhint %}

If it shows as disabled:

1. Click on the 3-dots menu.
2. Click **Manage the API in Google Cloud Console**.
3. Click **Enable** in the Google Cloud Console. Wait a few minutes for the change to reflect in Firebase.
   {% endstep %}

{% step %}

#### Configure your platform

{% tabs %}
{% tab title="Android" %}

1. While on the **Project Overview** page, click the **+ Add app** button under your project name.
2. Select **Android**.
3. In the **Register app** section:
   1. Enter the **Android package name** (Bundle ID) of the app configured in your Natively Dashboard.
   2. *(Optional)* Enter an **App nickname**; it will be used only in the Firebase Console to represent this app.
   3. Click **Register app**.
4. In the **Download and then add config file** section, click **Download google-services.json** and **save** the `google-services.json` file in a secure location.
5. Skip the SDK setup steps that follow, since Natively handles SDK integration for you, and click **Continue to console** at the end.

{% hint style="info" %}
You can access the `google-services.json` file again at any time. While on the **Project Overview** page, select **Settings > General** from the left sidebar, scroll down to **Your apps**, select your Android app, and download the file under the **SDK setup and configuration** section.
{% endhint %}
{% endtab %}

{% tab title="iOS" %}
{% stepper %}
{% step %}

### Configure iOS app

1. While on the **Project Overview** page, click the **+ Add app** button under your project name.
2. Select **iOS(Apple)**.
3. In the **Register app** section:
   1. Enter the **Apple Bundle ID** of the app configured in your Natively Dashboard.
   2. *(Optional)* Enter an **App nickname**; it will be used only in the Firebase Console to represent this app.
   3. *(Optional)* Enter an **App Store ID** (App Store App ID) of the app configured in your Natively Dashboard.
   4. Click **Register app**.
4. In the **Download and then add config file** section, click **Download google-services.json** and **save** the `GoogleService-Info.plist` file in a secure location.
5. Skip the SDK setup steps that follow, since Natively handles SDK integration for you, and click **Continue to console** at the end.

{% hint style="info" %}
You can access the `GoogleService-Info.plist` file again at any time. While on the **Project Overview** page, select **Settings > General** from the left sidebar, scroll down to **Your apps**, select your iOS app, and download the file under the **SDK setup and configuration** section.
{% endhint %}
{% endstep %}

{% step %}

### Upload your APNs Authentication Key

1. While on the **Project Overview** page, select **Settings > General** from the left sidebar, then go to the **Cloud Messaging** tab.
2. Scroll down to **Apple app configuration** and select your iOS app.
3. Under **APNs Authentication Key** in both **development** and **production** fields, provide the following and click **Upload**:
   * **APNs Auth key** - `.p8` file you downloaded in the [Set up APNs Authentication Key](#set-up-apns-authentication-key) step above.
   * **Key ID** and **Team ID** - gathered in the [Gather your credentials](#gather-your-credentials) step above.
     {% endstep %}
     {% endstepper %}
     {% endtab %}
     {% endtabs %}
     {% endstep %}
     {% endstepper %}

## Natively Dashboard Setup

Before proceeding, make sure you have completed the [Firebase Configuration](#firebase-configuration) steps above.

1. Open your Natively app dashboard and navigate to **Features** > **Notifications** > **Firebase**.
2. Toggle the feature to **Enabled**.
3. Upload the **Android Config file** (`google-services.json`) or/and the **iOS Config file** (`GoogleService-Info.plist`).
4. Enter the **Permission Description**.
5. *(Optional)* Adjust the **Automatically request push permission on app launch** checkbox.
6. Click **Save**.
7. Rebuild your app(s).

{% hint style="info" %}
The **Permission Description** is the text shown to users when the OS asks them to grant **notification** access. Explain clearly why your app needs this permission - for example: "We'll send you push notifications when your order ships."
{% endhint %}

{% hint style="info" %}
The **Automatically request push permission on app launch** is enabled by default, triggering the system permission prompt immediately after the user launches the app. Disable it if you'd rather request permission later, at a more relevant moment in your app's flow.
{% endhint %}

{% hint style="warning" %}
You must rebuild your app for these changes to take effect.
{% endhint %}

## Implementation

Choose your integration method below: **Bubble.io Plugin** (No-Code), **JavaScript SDK** (Code), or **AI Agents** (for AI-powered editors like Lovable, Base44, and Replit).

### Initialization

{% tabs %}
{% tab title="Bubble.io Plugin" %}
**Check Plugin**

Before starting, verify if the Natively plugin is already installed in your Bubble project.

1. Open your Bubble editor and navigate to the Plugins tab in the left sidebar.
2. **Check Installed Plugins:** Look through your list of installed plugins for "Natively iOS & Android app builder".
   * If it IS installed: Check the version number. If an update is available (e.g., you see a button saying "Update"), click it to ensure you have the latest features and bug fixes.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FmfnSUug82IdnxOAoBrak%252Fnatively_app_builder_bubble_plugin_update.png%3Falt%3Dmedia%26token%3Dc193f69f-b03b-4be4-b80b-f34ba37ac212&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=a89e4510&#x26;sv=2" alt=""><figcaption></figcaption></figure>

* If it is NOT installed: Click the + Add plugins button, search for "Natively", and click Install.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FC5rA42yQHcN1uGKFbzmF%252Fnatively_app_builder_bubble_plugin.png%3Falt%3Dmedia%26token%3Dd9706d9b-dbe8-459b-b9b3-5667648aa4b7&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=9aae2297&#x26;sv=2" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="JavaScript SDK" %}
**Check SDK**

Before writing any logic, ensure the Natively SDK is correctly installed and up-to-date in your codebase.

1. Open your project's main HTML file (or header settings) and look for the Natively script tag inside the `<head>` section.
2. Install/Update: If missing or outdated, add the following code. You can specify the SDK version in the URL (e.g., `@2.26.0`).

```javascript
<head>
  <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script>
</head>
```

{% hint style="info" %}
To ensure you are using the most up-to-date version, check the [Natively GitHub releases page](https://github.com/buildnatively/js-sdk/releases) for the latest version number.
{% endhint %}
{% endtab %}

{% tab title="AI Agents" %}
**Initialize the SDK**

AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features. Before implementing any feature, the Natively SDK must be initialized in your project.

Copy the line below and paste it into your AI agent to check and set up the Natively SDK in your project.

```
Check if the following Natively SDK script is present in the <head> of index.html. If missing or outdated, add it: <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script><script>function nativelyOnLoad() { window.natively.setDebug(true); console.log("✅ Natively SDK loaded successfully."); }</script> For reference: https://docs.buildnatively.com/guides/integration/how-to-get-started https://github.com/buildnatively/js-sdk/releases
```

{% endtab %}
{% endtabs %}

### &#x20;Setup logic

{% tabs %}
{% tab title="Bubble.io Plugin" %}

### \[Element] Natively - Push Notifications (Firebase)

{% hint style="warning" %}
This element must be set to **Visible on page load** to initialize correctly. It should be placed directly on the page root and not inside hidden containers, such as Popups, Floating Groups, Group Focus elements, or Repeating Groups. To hide the element from your UI, you may set its dimensions to 0x0 px.
{% endhint %}

{% hint style="info" %}
On initialization, the element automatically attempts to retrieve the current notification permission status - no need to call it on the **Page Is Loaded** event.
{% endhint %}

#### Events:

* **Firebase FMC Token Updated** - fires when the FCM token is updated.
* **Firebase APNS Token Updated** - fires when the APNs token is updated.
* **Notification permissions authorized** - fires when the user taps **Allow** on the permission alert.
* **Notification permissions denied** - fires when the user taps **Decline** on the permission alert.
* **Notification permissions status updated** - fires when permission status changes due to a user action.
* **Topic subscription status** - fires when a subscribe/unsubscribe action's status updates.

#### States:

* **Permission Status** - Yes/No.
* **Firebase FCM Token** -  the FCM token value.
* **Firebase APNS Token -** the APNs token value.
* **Topic subscription status** - `SUCCESS` if the subscribe action succeeded.
* **Topic unsubscribe status** - `SUCCESS` if the unsubscribe action succeeded.

#### Actions:

* **Request the user's push notification permission** - displays the system permission popup using your configured Permission Description.
* **Get the user's Firebase APNS Token** - reloads the user's Firebase APNS token.
* **Get the user's Firebase FCM Token** - reloads the user's Firebase FCM token.
* **Get the user's push notification permission status**
* **Subscribe to topic** - subscribes to an FCM topic:
  * **Topic ID** - the FCM topic name.
* **Unsubscribe from topic** - unsubscribes from an FCM topic:
  * **Topic ID** - the FCM topic name.
    {% endtab %}

{% tab title="JavaScript SDK" %}

```javascript
// ============================================================================
// NATIVELY NOTIFICATIONS (FIREBASE) - DOCUMENTATION & EXAMPLES
// ============================================================================

const notifications = new NativelyFirebaseNotifications();

// ============================================================================
// ALL AVAILABLE METHODS
// ============================================================================
// notifications.firebase_get_token(callback)
//   - Retrieves the device's FCM token.
//
// notifications.firebase_get_apns_token(callback)
//   - Retrieves the device's APNs token. iOS only.
//
// notifications.firebase_request_permission(callback)
//   - Prompts the native OS permission dialog.
//
// notifications.firebase_has_permission(callback)
//   - Checks the current notification permission status.
//
// notifications.firebase_subscribe_to_topic(topic, callback)
//   - Subscribes the device to an FCM topic.
//   - topic: string — the FCM topic name
//
// notifications.firebase_unsubscribe_from_topic(topic, callback)
//   - Unsubscribes the device from an FCM topic.
//   - topic: string — the FCM topic name

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_get_token
// ============================================================================
// resp.token: string | null — the device's FCM token
// Note: if Firebase throws internally, there is no structured failure response.

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_get_apns_token
// ============================================================================
// resp.token: string | null — the device's APNs token. iOS only, on success.
// resp.status: string — "FAILED" if called on Android, or if an exception occurs
// resp.message: string — "APNS token is only available on iOS" on Android,
//               or the exception message if one occurred on iOS

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_request_permission
// ============================================================================
// resp.status: boolean — true only if permission is fully authorized.
//              Any other permission state (denied, provisional, etc.) returns false.

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_has_permission
// ============================================================================
// resp.status: boolean — true if notification permission is currently granted

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_subscribe_to_topic
// ============================================================================
// resp.status: "SUCCESS" | "FAILED"
// resp.message: string — present on failure, e.g. "Exception: Topic is required"
//               if the topic parameter is missing. Other Firebase exceptions
//               also return their message here.
// Note: if the topic parameter is missing or has the wrong type entirely,
// there may be no structured failure response at all.

// ============================================================================
// CALLBACK RESPONSE FIELDS - firebase_unsubscribe_from_topic
// ============================================================================
// resp.status: "SUCCESS" | "FAILED"
// resp.message: string — present on failure, containing the Firebase exception message
// Note: if the topic parameter is missing or invalid, there may be no
// structured failure response at all.

// --- Push Notifications (Firebase). Tokens & Permission. Start ---

const fcm_token_callback = function (resp) {
  console.log(resp.token); // string, or null if no token is available
};

const apns_token_callback = function (resp) {
  if (resp.status === "FAILED") {
    console.log(resp.message); // "APNS token is only available on iOS" on Android
    return;
  }
  console.log(resp.token); // string, or null — iOS only
};

const permission_callback = function (resp) {
  console.log(resp.status); // true only if fully authorized
};

const permission_status_callback = function (resp) {
  console.log(resp.status); // true if notification permission is currently granted
};

notifications.firebase_get_token(fcm_token_callback);
notifications.firebase_get_apns_token(apns_token_callback); // iOS only
notifications.firebase_request_permission(permission_callback);
notifications.firebase_has_permission(permission_status_callback);

// --- Push Notifications (Firebase). Tokens & Permission. End ---


// --- Push Notifications (Firebase). Topic Subscription. Start ---

const topic = "your_topic_name";

const subscribe_callback = function (resp) {
  if (resp.status === "FAILED") {
    console.log(resp.message); // e.g. "Exception: Topic is required"
    return;
  }
  console.log("Subscribed to topic:", topic);
};

const unsubscribe_callback = function (resp) {
  if (resp.status === "FAILED") {
    console.log(resp.message);
    return;
  }
  console.log("Unsubscribed from topic:", topic);
};

notifications.firebase_subscribe_to_topic(topic, subscribe_callback);
notifications.firebase_unsubscribe_from_topic(topic, unsubscribe_callback);

// --- Push Notifications (Firebase). Topic Subscription. End ---
```

{% endtab %}

{% tab title="AI Agents" %}
AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features.

Copy the line below and paste it into your AI agent.

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively Push Notifications (Firebase) SDK: const notifications = new NativelyFirebaseNotifications(); notifications.firebase_get_token(callback) retrieves the device's FCM token, returning resp.token (string or null). notifications.firebase_get_apns_token(callback) retrieves the device's APNs token, iOS only, returning resp.token on success, or resp.status ("FAILED") and resp.message if called on Android or if an error occurs. notifications.firebase_request_permission(callback) prompts the native permission dialog, returning resp.status (boolean, true only if fully authorized). notifications.firebase_has_permission(callback) checks current permission status, returning resp.status (boolean). notifications.firebase_subscribe_to_topic(topic, callback) and notifications.firebase_unsubscribe_from_topic(topic, callback) manage FCM topic subscriptions, returning resp.status ("SUCCESS" or "FAILED") and resp.message on failure. For reference: https://docs.buildnatively.com/natively-platform/features/notifications/firebase-push-notifications-advanced
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Request push notification permission and save the FCM token to the user's profile on login".
{% endhint %}
{% endtab %}
{% endtabs %}

### How to use

#### Save both tokens on login - you'll need them to send notifications later

Store the FCM token (e.g. an `fcm_token` field on your user record) to send notifications on any platform. For iOS specifically, also store the APNs token (e.g. an `apns_token` field) if you send notifications directly via APNs rather than through FCM. Since tokens can change over time - after reinstalls or token refresh - retrieve and update them on every login rather than assuming a value saved once stays valid.

#### Check `resp.status` before treating permission as granted

`firebase_request_permission` only returns `true` when the user grants full authorization - any other state (denied, provisional, or not yet decided) returns `false`. Don't assume a non-true response means the request failed; it may simply mean the user hasn't fully authorized notifications.

#### Only call `firebase_get_apns_token` on iOS

This method always fails on Android with `resp.message: "APNS token is only available on iOS"`. Check the platform first with [Browser Info](/guides/integration/browser-info.md), and act upon the result.

#### Always provide a topic name

`firebase_subscribe_to_topic` and `firebase_unsubscribe_from_topic` fail with `"Exception: Topic is required"` if the topic is missing - validate the topic string before calling either method.

#### Use topics for broadcast-style targeting

Topics are best suited for sending the same notification to many users at once based on a shared interest or category (e.g. `news_updates`, `weekly_digest`) - subscribe users to relevant topics, then send a single notification to the topic instead of targeting each device individually.

## Sending Notifications

Once a device's FCM token (and APNs token, for iOS) is saved, you can send notifications directly through the **Firebase Console** or the **Cloud Messaging REST API**.

{% tabs %}
{% tab title="Firebase Console" %}
**Firebase Console** - the simplest way to send a test or one-off notification to either an individual device or a topic. See [Firebase Console Docs](https://firebase.google.com/docs/cloud-messaging/android/send-with-console).
{% endtab %}

{% tab title="Backend (REST API)" %}
**Cloud Messaging REST API** - send notifications programmatically from your backend to either an individual device or a topic. See [Cloud Messaging REST API Docs](https://firebase.google.com/docs/reference/fcm/rest).

{% hint style="info" %}
`YOUR_API_KEY` in the examples below is not a static API key - the FCM v1 API requires a short-lived OAuth2 access token, generated from your Firebase project's service account credentials. See [Authorizing send requests](https://firebase.google.com/docs/cloud-messaging/auth-server) for how to generate one.
{% endhint %}

{% hint style="info" %}
The `data.url` field is what enables deep linking - when the user taps the notification, Natively opens this URL inside your app instead of just launching to the home screen.
{% endhint %}

#### To a topic's subscribers:

```http
POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "message": {
    "notification": {
      "title": "Notification to All App Users",
      "body": "This is for all users of the app."
    },
    "data": {
      "url": "{YOUR_URL_TO_OPEN_INSIDE_THE_APP}"
    },
    "topic": "all"
  }
}
```

#### To a single user:

```http
POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "message": {
    "notification": {
      "title": "Notification to a Single App User",
      "body": "This is for a single user of the app."
    },
    "data": {
      "url": "{YOUR_URL_TO_OPEN_INSIDE_THE_APP}"
    },
    "token": "{FCM_TOKEN}"
  }
}
```

{% endtab %}
{% endtabs %}

## Troubleshooting

<details>

<summary>Notifications don't arrive at all</summary>

Go through this checklist:

* Feature is enabled, and the config file for each platform your app supports is uploaded - `google-services.json` for Android, `GoogleService-Info.plist` for iOS. If you support both platforms, make sure both files are uploaded, not just one.
* App rebuilt after configuration. Changes to this feature only take effect after a rebuild. If you configured or updated this after your last build, rebuild and test again.
* Token actually saved and targeted correctly. Confirm the FCM token used in your send request matches a token retrieved from the device you're testing on - a stale or mistyped token will silently fail to deliver.
* Permission granted on the device. Confirm `firebase_has_permission` returns `true` on the test device - if notification permission was never granted, no notification will be delivered regardless of a correct setup.
* Testing on a real build, not Preview or a browser. This is a native feature and requires a full Natively build installed on a real device.

</details>

<details>

<summary>Notifications only appear while the app is open, not in the background or when closed</summary>

This is most commonly caused by:

* **Android missing Notifications permission.** Confirm `firebase_has_permission` returns `true` - if the runtime notification permission was never granted, foreground notifications may still work (since the app can display them directly), but system-level background notifications will be silently dropped.
* **Manufacturer battery management.** Some Android manufacturers (Xiaomi, Huawei, Samsung, and others) aggressively kill background processes or restrict notification delivery for apps not explicitly exempted from battery optimization. Check the device's battery/power management settings and allow the app to run unrestricted in the background.
* **Payload structure.** If your payload only contains a `data` block with no `notification` block, some Android OEMs won't display anything unless the app is in the foreground to handle it manually - see see [Firebase Cloud Messaging message types](https://firebase.google.com/docs/cloud-messaging/customize-messages/set-message-type) for the distinction.

</details>

<details>

<summary>REST API call fails or returns an error</summary>

Confirm you're using a valid, current OAuth2 access token as the Bearer token - not a static Server Key, which is only valid for the deprecated legacy HTTP API. See the [FCM error codes reference](https://firebase.google.com/docs/reference/fcm/rest/v1/ErrorCode) to interpret the specific error returned.

</details>

<details>

<summary>Notification doesn't trigger any app behavior when tapped, or doesn't deep link correctly</summary>

Confirm the `data.url` field is included in your payload with the correct URL. If your payload only includes a `notification` block with no `data` block, the OS displays the notification but your app has nothing to act on when it's tapped - see [Firebase Cloud Messaging message types](https://firebase.google.com/docs/cloud-messaging/customize-messages/set-message-type) for the distinction.

</details>

<details>

<summary>Notifications sent from the Firebase Console arrive with a noticeable delay</summary>

This is expected behavior for messages sent as **Campaigns** through the Firebase Console UI - Firebase batches and schedules campaign delivery rather than sending immediately, which can introduce a delay of several minutes or more. For immediate, real-time delivery, send via the **Cloud Messaging HTTP v1 API** instead.

</details>

<details>

<summary>Not working in a web browser or in the Natively Preview app</summary>

This is a native feature and will not work in a standard web browser. Test on a real device using a Natively build.

</details>

[^1]: Replace this placeholder
