---
name: intercom-flutter-apns-token-ios
description: |
  Fix silent iOS push notification failure when integrating Intercom Flutter SDK
  with firebase_messaging. Use when: (1) Intercom messenger pushes arrive on
  Android but never on iOS despite zero errors, (2) `sendTokenToIntercom()` is
  called with `FirebaseMessaging.getToken()` on both platforms, (3) your own
  backend's FCM-based push delivery works on iOS but Intercom's doesn't,
  (4) wiring Intercom into a Flutter app that already uses firebase_messaging
  for direct FCM push, (5) all standard checks pass (push permissions granted,
  Xcode Push Notifications + Background Modes capabilities enabled, APNs cert
  uploaded to Intercom dashboard) yet iOS pushes still don't arrive. Root cause:
  Intercom requires the raw APNS device token on iOS, NOT the FCM token —
  Firebase internally translates FCM→APNS for your direct FCM use, but
  Intercom's backend doesn't use that translation layer.
author: Claude Code
version: 1.0.0
date: 2026-05-14
---

# Intercom Flutter SDK Requires APNS Token (Not FCM Token) on iOS

## Problem

When integrating `intercom_flutter` push notifications alongside
`firebase_messaging`, iOS push notifications from Intercom silently fail to
deliver — while Android works fine, and your own backend's FCM-based push
delivery to the same iOS devices also works fine.

The trap: the code uses `FirebaseMessaging.instance.getToken()` for both
platforms and forwards that token to `Intercom.sendTokenToIntercom()`. On iOS,
`getToken()` returns Firebase's FCM token. Intercom's backend doesn't speak
FCM — it needs the raw APNS device token.

Your own backend probably works fine on iOS using the same FCM token because
Firebase internally translates FCM→APNS for direct FCM-driven pushes.
Intercom doesn't go through that translation layer; it talks directly to
APNs using the device token you hand it.

## Trigger Conditions

All of:

- iOS Intercom messenger notifications never arrive
- Push permissions are granted on iOS
- No errors logged anywhere (Intercom SDK swallows token format issues)
- Push Notifications + Background Modes (Remote notifications) capabilities
  are enabled in Xcode for the Runner target
- APNs cert/key is uploaded to Intercom dashboard → Settings → Channels →
  Mobile Push → iOS
- Android Intercom pushes work fine
- Your own backend's FCM push delivery to the same iOS devices works fine
- Code does effectively:
  ```dart
  Intercom.instance.sendTokenToIntercom(
    await FirebaseMessaging.instance.getToken(),
  );
  ```
  on both platforms (no `Platform.isIOS` branch)

## Solution

On iOS, fetch the APNS token specifically and send THAT to Intercom. On
Android, keep using the FCM token.

```dart
import 'dart:io' show Platform;
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:intercom_flutter/intercom_flutter.dart';

Future<void> registerPushWithIntercom() async {
  final fm = FirebaseMessaging.instance;
  final intercomToken = Platform.isIOS
      ? await fm.getAPNSToken()  // raw APNS device token (64-hex)
      : await fm.getToken();     // FCM token

  if (intercomToken != null) {
    await Intercom.instance.sendTokenToIntercom(intercomToken);
  }
}
```

Important notes:

- Keep using `FirebaseMessaging.getToken()` (FCM) when registering with
  YOUR backend — that's correct on both platforms.
- The platform split applies ONLY to Intercom's
  `sendTokenToIntercom()` call.
- `getAPNSToken()` may return `null` briefly right after app launch if
  APNS hasn't finished registering. Either retry, or call this after
  `onTokenRefresh` fires the first time, or simply call again on next
  app foreground.
- Call the same function from `FirebaseMessaging.onTokenRefresh` so token
  rotations also reach Intercom.

## Verification

1. Build and run on a **physical iOS device** (push does not work on
   simulator regardless of token format)
2. Log in to identify the user to Intercom
3. From Intercom dashboard → Outbound → send a test push targeting the
   logged-in user (or trigger a real conversation reply from a teammate)
4. The push should arrive within seconds
5. If still no delivery: Intercom dashboard → People → find the user →
   inspect their device tokens. The iOS token should look like a raw APNS
   token (64 hex chars, no colons or underscores), NOT an FCM token
   (typically ~163 chars with colons, underscores, dashes)

## Why This Is Sneaky

- Intercom's Flutter package docs DO call this out, but only in a small
  code snippet near the bottom of the push notifications section. Trivial
  to miss when scanning setup steps.
- Most Flutter push tutorials use `getToken()` uniformly — that's correct
  advice for direct FCM use, just wrong for Intercom.
- The failure is silent: no exceptions, no error logs. Intercom accepts
  the FCM token via its API, stores it, then never delivers to it.
- Half your traffic (Android) works perfectly, hiding the bug.
- If your iOS QA pass uses the simulator, you'll miss it entirely.
- If your test push comes from your own backend (FCM-driven), it WILL
  arrive on iOS — falsely suggesting the iOS push pipeline is healthy.

## Related Pitfalls in the Same Integration

A few other gotchas commonly missed alongside this one:

1. **Missing custom Android `Application` class**. Intercom docs require
   initializing the Android SDK in `Application.onCreate()`, not just
   Dart `main()`, for reliable cold-start push delivery:

   ```kotlin
   // android/app/src/main/kotlin/.../MyApp.kt
   class MyApp : Application() {
     override fun onCreate() {
       super.onCreate()
       IntercomFlutterPlugin.initSdk(this, appId = "...", androidApiKey = "...")
     }
   }
   ```

   Then `android:name=".MyApp"` in `AndroidManifest.xml`'s `<application>`
   tag. Without this, a push tapped while the app is fully terminated may
   arrive at the OS before Flutter is up, and Intercom won't have
   registered the user identity yet.

2. **iOS Info.plist permissions**. Required: `NSPhotoLibraryUsageDescription`
   (photo attachments). Camera attachment requires `NSCameraUsageDescription`
   — if you already have one for another feature (e.g., barcode scanning),
   broaden its wording to cover support-chat photo capture too, or Apple
   may flag it during review.

3. **OAuth Client ID/Secret are NOT mobile SDK keys**. Don't paste OAuth
   credentials from Intercom's Developer Hub into your Flutter app. The
   SDK needs App ID + iOS API key (`ios_sdk-...`) + Android API key
   (`android_sdk-...`), all from Settings → Installation, not from
   Developer Hub.

## References

- Intercom Flutter package (pub.dev): push notifications section
  describing the iOS APNS / Android FCM token split
- Firebase Messaging Flutter — `getAPNSToken()` method docs
- Intercom: "Set up iOS push notifications" (uploading APNs key)
