# Flutter Recipe

Register a Flutter app's APNs and FCM tokens with Native Notify universal push using firebase_messaging — then send to devices or subscribers.

Flutter apps register their Firebase Messaging tokens with one HTTP call — no plugin required.

## Setup

1. Add `firebase_core` + `firebase_messaging` to `pubspec.yaml` and run `flutterfire configure` (this generates `firebase_options.dart` for Android and iOS).
2. On iOS, enable the APNs capability in Xcode and upload your APNs `.p8` key in the Firebase console (Firebase needs it to reach iOS devices).
3. Save the same Firebase project's **service-account JSON** and your **Apple `.p8`** as the app's credentials in Native Notify — [Push Credentials](/docs/universal-push/credentials).

## Get the tokens

```dart
import 'package:firebase_messaging/firebase_messaging.dart';

final messaging = FirebaseMessaging.instance;

// Ask once; on iOS this also enables APNs registration.
await messaging.requestPermission();

// FCM registration token — Android (and iOS when APNs is wired through Firebase).
final fcmToken = await messaging.getToken();

// iOS: the raw APNs token (null until APNs has delivered it).
final apnsToken = await messaging.getAPNSToken();
```

Tokens rotate: listen to `FirebaseMessaging.instance.onTokenRefresh` and re-register whenever either token changes.

## Register

```dart
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<void> registerUniversalDevice({
  required int appId,
  required String appToken,
  required String deviceId,
  String? subscriberId,
}) async {
  final messaging = FirebaseMessaging.instance;
  final tokens = Platform.isIOS
      ? {'apnsToken': await messaging.getAPNSToken()}
      : {'fcmToken': await messaging.getToken()};

  final res = await http.post(
    Uri.parse('https://app.nativenotify.com/api/universal/device/register'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({
      'appId': appId,
      'appToken': appToken,
      'deviceId': deviceId, // persist per install (e.g. shared_preferences)
      'platform': Platform.isIOS ? 'ios' : 'android',
      if (subscriberId != null) 'subscriberId': subscriberId,
      'tokens': tokens,
    }),
  );
  print(res.body); // {"ok":true,"device":{...},"tokens":{...}}
}
```

Call it on launch (after `Firebase.initializeApp`) and from the token-refresh listener. It is an idempotent upsert, so calling it every launch is correct.

## Send

```bash
curl -X POST https://app.nativenotify.com/api/universal/notifications/send \
  -H "Content-Type: application/json" \
  -d '{"appId":123,"appToken":"yourAppToken","title":"Hello Flutter","message":"Sent through APNs/FCM.","audience":{"type":"all"}}'
```

## Next steps

- [Device Registration](/docs/universal-push/registration) — full field rules (`deviceId`, `subscriberId`, token shapes).
- [Verify Delivery](/docs/universal-push/verification) — test-send and health counts.
- [Segments](/docs/segments) — let users subscribe to topic-like groups from the app.
