---
title: Migrating to v27
description: >-
  Migrate to React Native Firebase v27 - Firebase Android BoM 35, Apple SDK 13
  (SPM-only), JS SDK 13, platform floors, AI API removals, messaging
  corrections, and ML package removal.
previous: /migrating-to-v26
next: /typescript
---
> ## Documentation Index
> Fetch the complete documentation index at: https://rnfirebase.io/llms.txt
> Use this file to discover all available pages before exploring further.

Version 27 is a **native and JS SDK major** plus several earlier breaking corrections:

### Upstream SDK majors (new in this release)

| Platform | Pin                               | Floor / install change                                                     |
| -------- | --------------------------------- | -------------------------------------------------------------------------- |
| Android  | Firebase BoM **35.0.0**           | `minSdk` **24** (was 23); Kotlin Gradle plugin **≥ 2.4.0**                 |
| Apple    | Firebase iOS SDK **13.0.0** (SPM) | macOS **11.0** (was 10.15); **SPM-only** Firebase (CocoaPods path removed) |
| JS       | `firebase` **13.0.0**             | AI Logic API removals / renames (see below)                                |

- **Android** — BoM 35 requires API 24+. Update `minSdkVersion` / `sdkVersions` overrides to **24**. Raise the Kotlin Gradle plugin to **≥ 2.4.0** (`firebase-auth` 25 ships Kotlin 2.4.0 metadata). See [Platforms](/platforms).
- **Apple** — Firebase 13 is distributed only via Swift Package Manager. Remove `$RNFirebaseDisableSPM` / Expo `disableSPM`. Use `use_frameworks! :linkage => :dynamic`. See [iOS SPM Support](/ios-spm). Google Sign-In + Firebase 13 may still hit App Check resolve conflicts — see [Ecosystem compatibility tips](/migrating-to-v27#ecosystem-compatibility-tips) and [iOS SPM Support § Google Sign-In caveat](/ios-spm#google-sign-in-caveat).
- **JS / AI** — Align with Firebase JS SDK 13 / `@firebase/ai@3`: use `AgentPlatformBackend` (default location **`global`**) instead of removed `VertexAIBackend`; template `generateContent` takes a `TemplateRequest`; remove `LiveSession.sendMediaChunks` / `sendMediaStream` (use realtime senders); drop `totalBillableCharacters` and related removed fields.

### Other v27 breaks (already on this line)

- **Cloud Messaging** — four documented runtime contracts are enforced after previous accidental shapes ([#9246](https://github.com/invertase/react-native-firebase/pull/9246), [#9247](https://github.com/invertase/react-native-firebase/pull/9247), [#9252](https://github.com/invertase/react-native-firebase/pull/9252), [#9254](https://github.com/invertase/react-native-firebase/pull/9254)).
- **Imagen API removed** from `@react-native-firebase/ai` after Google shut down the Imagen models as a service on **2026-08-17**. Generate images with a Gemini image model through `getGenerativeModel()` instead.
- **App (iOS)** — `initializeApp` reads `automaticDataCollectionEnabled` as a real boolean, and public App headers no longer re-export FirebaseCore / Photos ([#9337](https://github.com/invertase/react-native-firebase/pull/9337)).
- **ML package removed** — `@react-native-firebase/ml` is discontinued and no longer published with v27.
- **FunctionsError (web/macOS)** — earlier JS SDK enrichment of `FunctionsError.message` / `customData.url` on `Platform.other` (see section below; still applies under JS 13).

If you are upgrading from v25 or earlier, complete [Migrating to v26](/migrating-to-v26) first — the namespaced API removal and New Architecture requirement still apply.

## Table of contents

- [Agent-assisted migration](/migrating-to-v27#agent-assisted-migration)
- [Upstream SDK majors](/migrating-to-v27#upstream-sdk-majors)
- [Firebase JS / FunctionsError](/migrating-to-v27#firebase-js--functionserror)
- [Cloud Messaging](/migrating-to-v27#cloud-messaging)
  - [String APNs sound → `notification.ios.sound`](/migrating-to-v27#string-apns-sound--notificationiossound)
  - [iOS `sentTime` is epoch milliseconds](/migrating-to-v27#ios-senttime-is-epoch-milliseconds)
  - [iOS badge is a string](/migrating-to-v27#ios-badge-is-a-string)
  - [`onMessageSent` receives a string message ID](/migrating-to-v27#onmessagesent-receives-a-string-message-id)
- [AI Logic breaking removals](/migrating-to-v27#ai-logic-breaking-removals)
- [Removed Imagen API](/migrating-to-v27#removed-imagen-api)
  - [Example](/migrating-to-v27#example)
- [App (iOS)](/migrating-to-v27#app-ios)
  - [`automaticDataCollectionEnabled` is a boolean](/migrating-to-v27#automaticdatacollectionenabled-is-a-boolean)
  - [Public headers no longer import FirebaseCore / Photos](/migrating-to-v27#public-headers-no-longer-import-firebasecore--photos)
- [Removed ML package](/migrating-to-v27#removed-ml-package)
- [Ecosystem compatibility tips](/migrating-to-v27#ecosystem-compatibility-tips)
  - [Kotlin ≥ 2.4.0 (supported)](/migrating-to-v27#kotlin--240-supported)
  - [Unsupported older-Kotlin workaround](/migrating-to-v27#unsupported-older-kotlin-workaround)
  - [AsyncStorage / KSP](/migrating-to-v27#asyncstorage--ksp)
  - [Google Sign-In + Firebase 13 SPM](/migrating-to-v27#google-sign-in--firebase-13-spm)
- [Automated migration checklist](/migrating-to-v27#automated-migration-checklist)

# Upstream SDK majors

### Migration actions

1. Bump all `@react-native-firebase/*` packages to v27 together.
2. Android: set `minSdkVersion` / any `react-native` `versions.android.minSdk` override to **24**; set `kotlinVersion` / the Kotlin Gradle plugin to **≥ 2.4.0**.
3. iOS: remove `$RNFirebaseDisableSPM = true` and Expo `ios.disableSPM`; ensure `use_frameworks! :linkage => :dynamic` (or Expo `useFrameworks: "dynamic"`); raise macOS deployment target to **11.0** if you ship macOS.
4. JS: ensure the app resolves `firebase@13` (RNFB pins it on `@react-native-firebase/app`).
5. AI: apply the [AI Logic breaking removals](/migrating-to-v27#ai-logic-breaking-removals) below.

# AI Logic breaking removals

These match Firebase JS SDK 13 / `@firebase/ai@3`:

| Removed / changed                                 | Replacement                                                                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `VertexAIBackend` / `BackendType.VERTEX_AI`       | `AgentPlatformBackend` / `BackendType.AGENT_PLATFORM` (default location **`global`**, was `us-central1` for Vertex) |
| `generateContent(templateId, vars, …)` positional | `generateContent({ templateId, templateVariables, toolConfig? })` (`TemplateRequest`)                               |
| `LiveSession.sendMediaChunks` / `sendMediaStream` | `sendTextRealtime` / `sendAudioRealtime` / `sendVideoRealtime`                                                      |
| `CountTokensResponse.totalBillableCharacters`     | Use `totalTokens`                                                                                                   |
| `Part` without `type`                             | Discriminated union with `type: 'text' \| 'inlineData' \| …`                                                        |

`GenerationConfig` / `LiveGenerationConfig` sampling fields (`temperature`, `topP`, `topK`, `presencePenalty`, `frequencyPenalty`) and `candidateCount` remain on the types but are **`@deprecated`** for Gemini 3.x / 4.x — omit them for those models. They are not removed in v27.

```js
import { getAI, AgentPlatformBackend, getTemplateGenerativeModel } from '@react-native-firebase/ai';

const ai = getAI(getApp(), { backend: new AgentPlatformBackend() }); // location defaults to global
const templates = getTemplateGenerativeModel(ai);
await templates.generateContent({
  templateId: 'my-template',
  templateVariables: { name: 'Ada' },
});
```

# Firebase JS / FunctionsError

## Agent-assisted migration

This guide is written to be **complete enough for an automated first pass**. We recommend feeding this document to your coding agent, then asking it to analyze your codebase against each relevant section below and produce a concrete change list (or PR) for the packages you use. The [Automated migration checklist](/migrating-to-v27#automated-migration-checklist) at the end is structured for that workflow.

**PR:** [#9218](https://github.com/invertase/react-native-firebase/pull/9218)

React Native Firebase pins **firebase-js-sdk 13.x**. On **web and macOS** (`Platform.other`), Cloud Functions uses the JS SDK callable path. That path enriches `FunctionsError` (aliased as `HttpsError` in React Native Firebase) — behavior introduced in JS SDK 12.18.0 and still present in 13:

| Change                          | Before                      | After (v27 / JS SDK 13)                                                                        | Who              |
| ------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------- | ---------------- |
| `FunctionsError.message`        | Exact server message string | Message plus a trailing ` [<httpStatus>]` suffix (for example `Invalid test requested. [400]`) | Web / macOS only |
| `FunctionsError.customData.url` | Not present                 | Request URL string on `customData`                                                             | Web / macOS only |

**Native iOS and Android** continue to surface callable failures through the native bridge as `HttpsError` **without** the HTTP status suffix. Do not assume the suffix or `customData.url` on those platforms.

### Migration actions

1. Search for exact-equality checks on `error.message` / `e.message` for callable failures.
2. On web/macOS, prefer `message.startsWith(expected)` or strip a trailing ` [digits]` before comparing.
3. If you need the HTTP status or request URL, read them from the suffix / `customData.url` on web/macOS only; keep a native fallback path for iOS/Android.

```js
// Previously (exact match — breaks on web/macOS after 12.18.0)
if (e.message === 'Invalid test requested.') {
  /* … */
}

// Now (tolerant of the optional " [status]" suffix)
const base = e.message.replace(/ \[\d+\]$/, '');
if (base === 'Invalid test requested.') {
  /* … */
}
// Optional on Platform.other:
// e.customData?.url
```

Upstream note: [firebase@12.18.0](https://github.com/firebase/firebase-js-sdk/releases/tag/firebase%4012.18.0) — “Add HTTP status code to the `message` field and add `url` to `customData`.”

# Cloud Messaging

These changes **correct runtime behavior** to match the public `RemoteMessage` / listener contracts. There is no new public TypeScript surface — consumers that worked around the old accidental shapes must update.

## String APNs sound → `notification.ios.sound`

**PR:** [#9246](https://github.com/invertase/react-native-firebase/pull/9246)

String-valued APNs sounds are serialized at the documented `message.notification.ios.sound` path. Previously, only string sounds were placed at the undocumented `message.notification.sound` path (critical-sound dictionaries already used the correct iOS nesting).

| Before (accidental)                   | After (documented)                        |
| ------------------------------------- | ----------------------------------------- |
| `message.notification.sound` (string) | `message.notification.ios.sound` (string) |

```js
// Previously
const sound = message.notification?.sound;

// Now
const sound = message.notification?.ios?.sound;
```

## iOS `sentTime` is epoch milliseconds

**PR:** [#9247](https://github.com/invertase/react-native-firebase/pull/9247)

On iOS, `RemoteMessage.sentTime` is a **number** of epoch **milliseconds**, matching Android and the public type. FCM supplies seconds (often as a string); native serialization converts those values to milliseconds.

| Before (iOS accidental)                               | After                                                       |
| ----------------------------------------------------- | ----------------------------------------------------------- |
| string epoch **seconds** (for example `"1522880044"`) | number epoch **milliseconds** (for example `1522880044000`) |

Android behavior is unchanged. Remove `parseInt` / string comparisons that assumed seconds.

```js
// Previously (iOS)
const sentMs = Number(message.sentTime) * 1000;

// Now (iOS and Android)
const sentMs = message.sentTime; // number, epoch ms
```

## iOS badge is a string

**PR:** [#9252](https://github.com/invertase/react-native-firebase/pull/9252)

iOS `aps.badge` is serialized as a **string**, matching `RemoteMessage.notification.ios.badge?: string`.

| Before (iOS accidental)  | After                      |
| ------------------------ | -------------------------- |
| number (for example `7`) | string (for example `"7"`) |

```js
// Previously
const badge = message.notification?.ios?.badge; // number on iOS

// Now
const badge = Number(message.notification?.ios?.badge ?? 0);
```

## `onMessageSent` receives a string message ID

**PR:** [#9254](https://github.com/invertase/react-native-firebase/pull/9254)

`onMessageSent` listeners receive the documented **message-ID string**. Android previously forwarded the transport wrapper `{ messageId }` to application code.

| Before (accidental)     | After (documented) |
| ----------------------- | ------------------ |
| `{ messageId: string }` | `string`           |

```js
// Previously
onMessageSent(messaging, ({ messageId }) => {
  console.log(messageId);
});

// Now
onMessageSent(messaging, messageId => {
  console.log(messageId);
});
```

# Removed Imagen API

This section covers **only Imagen API removals**. Other `@react-native-firebase/ai` breaking removals and renames (`VertexAIBackend` → `AgentPlatformBackend`, positional template `generateContent` → `TemplateRequest`, `sendMedia*` → realtime senders, and related fields) are listed in [AI Logic breaking removals](/migrating-to-v27#ai-logic-breaking-removals) — that table remains authoritative for the rest of the AI Logic API breaks.

Imagen exports and `generateImages` are gone. Use `getGenerativeModel()` / `getTemplateGenerativeModel()` with a Gemini image model (`responseModalities` + `imageConfig`) instead.

## Removed exports

{/* prettier-ignore */}
| Removed | Replacement |
| --- | --- |
| `getImagenModel` | `getGenerativeModel()` with a Gemini image model |
| `getTemplateImagenModel` | `getTemplateGenerativeModel()` with a template that uses an image model |
| `ImagenModel` | `GenerativeModel` |
| `TemplateImagenModel` | `TemplateGenerativeModel` |
| `ImagenModelParams` | `ModelParams` |
| `ImagenGenerationConfig` | `GenerationConfig` with `responseModalities` and `imageConfig` |
| `ImagenImageFormat` | No replacement — Gemini image models always return `PNG`; read `inlineData.mimeType` to confirm |
| `ImagenGenerationResponse` | `GenerateContentResult` |
| `ImagenInlineImage` | `InlineDataPart` on the response candidate |
| `ImagenGCSImage` | No replacement — Gemini image models return inline data |
| `ImagenAspectRatio` | `ImageConfigAspectRatio` |
| `ImagenSafetySettings` | `SafetySetting[]` on `getGenerativeModel()` |
| `ImagenSafetyFilterLevel` | `HarmBlockThreshold` |
| `ImagenPersonFilterLevel` | No replacement — Gemini image models allow generating people by default |

## Example

```js
// Previously (removed)
import { getApp } from '@react-native-firebase/app';
import { getAI, getImagenModel, ImagenAspectRatio } from '@react-native-firebase/ai';

const ai = getAI(getApp());
const imagenModel = getImagenModel(ai, {
  model: 'imagen-3.0-generate-002',
  generationConfig: {
    aspectRatio: ImagenAspectRatio.LANDSCAPE_16x9,
  },
});

const result = await imagenModel.generateImages('Draw a red bicycle on a beach at sunset');
console.log(result.images[0].mimeType);
```

```js
// Now
import { getApp } from '@react-native-firebase/app';
import {
  getAI,
  getGenerativeModel,
  ImageConfigAspectRatio,
  ImageConfigImageSize,
  ResponseModality,
} from '@react-native-firebase/ai';

const ai = getAI(getApp());
const model = getGenerativeModel(ai, {
  model: 'gemini-3.1-flash-image',
  generationConfig: {
    responseModalities: [ResponseModality.IMAGE],
    imageConfig: {
      aspectRatio: ImageConfigAspectRatio.LANDSCAPE_16x9,
      imageSize: ImageConfigImageSize.SIZE_1K,
    },
  },
});

const result = await model.generateContent('Draw a red bicycle on a beach at sunset');
const imagePart = result.response.inlineDataParts()?.[0];
console.log(imagePart?.inlineData.mimeType);
```

See [AI Logic usage](/ai/usage) for more image generation examples, and Google's [Imagen to Gemini migration guide](https://firebase.google.com/docs/ai-logic/imagen-models-migration) for model and prompt guidance.

# App (iOS)

**PR:** [#9337](https://github.com/invertase/react-native-firebase/pull/9337)

These changes landed with the App native Swift/Kotlin port. Most apps that only use the JavaScript API are unaffected by the header change; the data-collection fix can change runtime behavior if you passed `automaticDataCollectionEnabled: false` and previously still got collection enabled.

## `automaticDataCollectionEnabled` is a boolean

`initializeApp` / native app options now read `automaticDataCollectionEnabled` as a **boolean**. Previously the Objective-C path cast the option value to a pointer, so **any non-nil value — including JavaScript `false` — enabled** automatic data collection.

| Value                         | Before (accidental) | After        |
| ----------------------------- | ------------------- | ------------ |
| `true`                        | enabled             | enabled      |
| `false` / `0` / `null` / omit | enabled if non-nil  | **disabled** |

### Migration actions

1. Search for `automaticDataCollectionEnabled` in `initializeApp` options and native config.
2. If you passed `false` expecting collection to stay off, you are now correct — no change needed beyond verifying analytics/collection behavior.
3. If you relied on the old bug (passing a non-boolean non-nil value, or `false` while still seeing collection), set an explicit boolean for the behavior you want.

```js
import { initializeApp } from '@react-native-firebase/app';

// Now false / null / absent disable collection; only true enables it.
await initializeApp({
  // …
  automaticDataCollectionEnabled: false,
});
```

## Public headers no longer import FirebaseCore / Photos

These public App headers **no longer** import FirebaseCore or Photos. Forward declarations are used instead. Downstream **native** code that compiled only because those headers pulled the frameworks in transitively must import them at the call site.

| Header                    | No longer imports |
| ------------------------- | ----------------- |
| `RNFBSharedUtils.h`       | FirebaseCore      |
| `RCTConvert+FIRApp.h`     | FirebaseCore      |
| `RCTConvert+FIROptions.h` | FirebaseCore      |
| `RNFBUtilsModule.h`       | Photos            |

### Migration actions

1. If a native `.m` / `.mm` / `.swift` file fails to compile with unknown `FIRApp` / `FIROptions` / `PHAsset` (or similar) after upgrading, add the import next to your other Firebase / Photos imports.
2. JavaScript-only apps do not need changes for this item.

```objc
// Example — add at the call site if you used RNFB headers and relied on the old transitive import
#import <FirebaseCore/FirebaseCore.h>
#import <Photos/Photos.h>
```

# Removed ML package

`@react-native-firebase/ml` is **removed** in v27. The package had already been mostly discontinued: Firebase no longer ships the legacy ML APIs this module wrapped, and the React Native Firebase surface exposed no public APIs.

### Migration actions

1. Remove `@react-native-firebase/ml` from your dependencies (`yarn remove @react-native-firebase/ml` or equivalent).
2. Delete any imports of `@react-native-firebase/ml` (for example `getML`) — they no longer resolve.
3. For on-device ML Kit features, use [Google ML Kit](https://developers.google.com/ml-kit/) via the community [react-native-mlkit](https://www.npmjs.com/org/react-native-mlkit) modules.
4. To call Cloud Vision from your app, prefer Firebase Authentication and Cloud Functions as a managed gateway. See the [vision-annotate-images](https://github.com/firebase/functions-samples/tree/3515b7f38a3c598cdb20152a263372e81719ecda/vision-annotate-images) Functions sample.

# Ecosystem compatibility tips

Third-party native modules and host toolchain pins sometimes need small adjustments when moving to BoM 35 / Firebase Apple 13. The **supported** Android path is Kotlin **≥ 2.4.0** ([Platforms](/platforms)). The items below collect common ecosystem notes and unsupported workarounds — React Native Firebase does **not** ship these flags or property overrides for you.

## Kotlin ≥ 2.4.0 (supported)

Firebase Android BoM **35** / `firebase-auth` **25** ships Kotlin **2.4.0** metadata. Raise the Kotlin Gradle plugin to **≥ 2.4.0** so the compiler can read that metadata. This is the supported path; see [Platforms](/platforms).

## Unsupported older-Kotlin workaround

> **Unsupported.** Prefer Kotlin **≥ 2.4.0**. The `-Xskip-metadata-version-check` approach below is **not recommended**, may break if your app or another module calls Firebase Auth **Kotlin** APIs, and React Native Firebase offers **no support** for failures that follow from it. React Native Firebase does **not** ship this compiler flag.

If you must stay on an older Kotlin compiler temporarily, add the flag on the **auth** module's `KotlinCompile` tasks from the **app** `android/build.gradle` (preferred over patching `node_modules`):

```groovy
// android/build.gradle — UNSUPPORTED workaround; prefer Kotlin ≥ 2.4.0
subprojects { subproject ->
  def n = subproject.name
  if (n.contains('react-native-firebase_auth') || n.contains('@react-native-firebase_auth')) {
    subproject.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
      kotlinOptions.freeCompilerArgs += ['-Xskip-metadata-version-check']
    }
  }
}
```

Autolinking project names vary (`react-native-firebase_auth`, `@react-native-firebase_auth`). Adjust the `name` match if your Gradle project path differs. As a last resort you can drop an equivalent `tasks.withType(...KotlinCompile)` block into `node_modules/@react-native-firebase/auth/android/build.gradle` and persist it with [patch-package](https://www.npmjs.com/package/patch-package) — prefer the app-level `subprojects` pattern so you do not patch `node_modules` when avoidable.

## AsyncStorage / KSP

`@react-native-async-storage/async-storage` **3.1.1** (and similar releases) may lack a KSP mapping for Kotlin **2.4.0**. Until upstream maps 2.4.0, pin a known KSP in the app's `android/gradle.properties`:

```properties
AsyncStorage_kspVersion=2.3.12
```

Other native modules that use KSP may need analogous overrides until their maintainers publish mappings for Kotlin 2.4.0.

## Google Sign-In + Firebase 13 SPM

Google Sign-In alongside Firebase 13 can fail App Check resolution on SPM and
CocoaPods for different reasons. See
[iOS SPM Support § Google Sign-In caveat](/ios-spm#google-sign-in-caveat)
for current upstream status on each path.

# Automated migration checklist

Use this section when running scripted or agent-assisted upgrades from v26 → v27.

## 1. Upgrade dependencies

```bash
# Bump all @react-native-firebase/* packages to v27 together (monorepo versions are aligned)
yarn add @react-native-firebase/app@^27.0.0 …
cd ios && pod install
```

Confirm the lockfiles resolve **firebase** / firebase-js-sdk **13.0.0**, Android BoM **35**, and iOS SPM Firebase **13.0.0**. Confirm Android `minSdk` **24** and macOS **11.0**.

## 2. Agent-oriented search and replace

For each area you use, search the listed symbols and apply the replacements:

| Area                      | Search for                                                                             | Replace with / action                                                                                                                                                                                                                                      |
| ------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Android floor             | `minSdkVersion` / `minSdk` **23** (or lower)                                           | **24**                                                                                                                                                                                                                                                     |
| Android Kotlin            | `kotlinVersion` / Kotlin Gradle plugin below **2.4.0**                                 | **≥ 2.4.0** (BoM 35 / `firebase-auth` 25 metadata)                                                                                                                                                                                                         |
| iOS DisableSPM            | `$RNFirebaseDisableSPM`, Expo `disableSPM: true`                                       | Remove; use SPM + `use_frameworks! :linkage => :dynamic`                                                                                                                                                                                                   |
| Functions (web/macOS)     | `e.message ===`, `error.message ===` on callable failures                              | Tolerate trailing ` [<digits>]`; optionally read `customData.url` on `Platform.other` only                                                                                                                                                                 |
| Messaging sound           | `notification.sound` (string APNs sound)                                               | `notification.ios.sound`                                                                                                                                                                                                                                   |
| Messaging `sentTime`      | string/`parseInt`/`* 1000` on `sentTime` (iOS)                                         | Use numeric epoch-ms directly                                                                                                                                                                                                                              |
| Messaging badge           | numeric use of `notification.ios.badge`                                                | Parse string (`Number(...)`) when a number is required                                                                                                                                                                                                     |
| Messaging `onMessageSent` | `({ messageId })` / `.messageId` in the listener                                       | Use the string argument directly                                                                                                                                                                                                                           |
| AI backend                | `VertexAIBackend`, `BackendType.VERTEX_AI`                                             | `AgentPlatformBackend` / `AGENT_PLATFORM` (document `global` default)                                                                                                                                                                                      |
| AI templates              | positional `generateContent(templateId, vars, …)`                                      | `generateContent({ templateId, templateVariables, toolConfig? })`                                                                                                                                                                                          |
| AI live media             | `sendMediaChunks`, `sendMediaStream`                                                   | `sendTextRealtime` / `sendAudioRealtime` / `sendVideoRealtime`                                                                                                                                                                                             |
| AI tokens                 | `totalBillableCharacters`                                                              | `totalTokens`                                                                                                                                                                                                                                              |
| AI Imagen                 | `getImagenModel`, `getTemplateImagenModel`, `ImagenModel`, `Imagen*`, `generateImages` | `getGenerativeModel` / `getTemplateGenerativeModel` with `responseModalities` + `imageConfig`                                                                                                                                                              |
| App iOS data collection   | `automaticDataCollectionEnabled` in `initializeApp` options                            | Use an explicit boolean; `false` / `0` / `null` / absent now disable collection                                                                                                                                                                            |
| App iOS native headers    | compile errors for `FIRApp` / `FIROptions` / `PHAsset` after including RNFB headers    | `#import <FirebaseCore/FirebaseCore.h>` and/or `#import <Photos/Photos.h>` at the call site                                                                                                                                                                |
| ML package                | `@react-native-firebase/ml`, `getML`                                                   | Remove the dependency; use [react-native-mlkit](https://www.npmjs.com/org/react-native-mlkit) or Cloud Vision via Functions ([sample](https://github.com/firebase/functions-samples/tree/3515b7f38a3c598cdb20152a263372e81719ecda/vision-annotate-images)) |

## 3. Validate

```bash
yarn compile
# TypeScript consumers: fix compile errors from removed Imagen exports and messaging types
# Manually exercise: callable error message handling (web/macOS), FCM notification fields (iOS), onMessageSent, Gemini image generation
# Native iOS: rebuild any pods/apps that import RNFB App headers; confirm automaticDataCollectionEnabled false disables collection
```

## Related PRs (v27 breaking changes)

| Area                                                                   | PR                                                                    |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Firebase JS SDK 12.18.0 / `FunctionsError`                             | [#9218](https://github.com/invertase/react-native-firebase/pull/9218) |
| Messaging — APNs string sound path                                     | [#9246](https://github.com/invertase/react-native-firebase/pull/9246) |
| Messaging — iOS `sentTime` epoch-ms                                    | [#9247](https://github.com/invertase/react-native-firebase/pull/9247) |
| Messaging — iOS badge string                                           | [#9252](https://github.com/invertase/react-native-firebase/pull/9252) |
| Messaging — `onMessageSent` string ID                                  | [#9254](https://github.com/invertase/react-native-firebase/pull/9254) |
| AI — Imagen API removal                                                | [#9275](https://github.com/invertase/react-native-firebase/pull/9275) |
| App iOS — ADC boolean + header imports                                 | [#9337](https://github.com/invertase/react-native-firebase/pull/9337) |
| SDK majors (Android 35 / Apple 13 / JS 13), ML removal, AI Logic JS 13 | [#9372](https://github.com/invertase/react-native-firebase/pull/9372) |
