Add in-app notifications, push notifications, and notification preferences to your Flutter app with prebuilt widgets and Dart APIs.
The Courier Flutter SDK provides prebuilt widgets and APIs for building notification experiences in Dart. It handles authentication, token management, and real-time message delivery across iOS and Android from a single codebase.
Inbox — prebuilt notification center widget with theming and custom rendering
Push Notifications — automatic token syncing and delivery tracking for APNS and FCM
Preferences — prebuilt widget for users to manage their notification settings
The SDK’s intl dependency (>=0.19.0 <1.0.0) is incompatible with Flutter 3.32+ (Dart 3.7+), which ships intl 1.0. If you encounter dependency resolution errors on newer Flutter versions, pin intl: ^0.19.0 in your app’s pubspec.yaml or wait for an SDK update that widens the constraint.
All SDK features (Inbox, Push, Preferences) require a signed-in user. Authentication is JWT-based; your backend generates a token and the SDK manages credentials across app sessions.
Pass the JWT to the SDK where you manage user state. Credentials persist across app sessions. If the token expires, generate a new one from your backend and call signIn again; the SDK does not handle token refresh automatically.
Courier Inbox provides a prebuilt notification center widget. It supports theming, custom renderers, and real-time updates. The widget automatically adapts to your app’s Flutter Theme unless you provide a custom CourierInboxTheme.
Inbox requires the Courier Inbox provider to be enabled in your workspace. If using JWT authentication, enable JWT support in the provider settings.
Open your iOS project and bump the minimum deployment target to iOS 15.0+, then re-install pods:
cd ios && pod update
2
Extend CourierFlutterDelegate
In ios/Runner/AppDelegate.swift, import the SDK and inherit from CourierFlutterDelegate. This automatically syncs APNS tokens to Courier and forwards delivery / click events to Dart.
In Xcode: select your target > Signing & Capabilities > add Push Notifications.
4
Add a Notification Service Extension (recommended)
Required for tracking delivery when the app is not running. See the iOS SDK push setup for the full steps; the same template applies to Flutter. After adding the extension, in your project settings move Embedded Foundation Extensions above Run Scripts and below Link Binary With Libraries.
Firebase is now a separate dependency. Starting with Courier Flutter 5.x (built on Courier Android 6.x), the SDK no longer bundles Firebase Messaging as a transitive dependency. Your app must add its own Firebase BoM and firebase-messaging artifact so you can subclass FirebaseMessagingService.
1
Add Firebase to your app
Register your app in Firebase, download google-services.json, and place it in android/app/.In android/app/build.gradle:
Update your MainActivity (Kotlin) to extend CourierFlutterActivity (or CourierFlutterFragmentActivity if you use a FragmentActivity). This lets the SDK forward push delivery and click events into Flutter.
Subclass Firebase’s FirebaseMessagingService directly and forward both callbacks to Courier. The SDK caches the FCM token, uploads it to Courier when a user is signed in, and broadcasts delivery events through its event bus.
import com.courier.android.Courierimport com.courier.android.notifications.CourierPushNotificationIntentimport com.courier.android.notifications.presentNotificationimport com.google.firebase.messaging.FirebaseMessagingServiceimport com.google.firebase.messaging.RemoteMessageclass YourNotificationService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) { super.onMessageReceived(message) // Build the PendingIntent that opens MainActivity and carries the original payload val notificationIntent = CourierPushNotificationIntent( context = this, target = MainActivity::class.java, payload = message ) // Show the notification. Prefer data-only FCM so this service runs even when the app is killed. notificationIntent.presentNotification( title = message.data["title"] ?: message.notification?.title, body = message.data["body"] ?: message.notification?.body ) // Tell the Courier SDK that a push was delivered Courier.onMessageReceived(message.data) } override fun onNewToken(token: String) { super.onNewToken(token) // Register/refresh the FCM token with Courier Courier.onNewToken(token) }}
Once you’ve completed the setup above, send a test push using the Send API with push as the routing channel. See the APNS sending guide or FCM sending guide for complete examples.
Pass a CourierPreferencesTheme to customize fonts, colors, toggle styles, and section headers. Light and dark themes are both supported, and Courier Studio branding is automatically applied when a brandId is provided.
For advanced use cases, CourierClient is a low-level wrapper around the Courier API. Each client holds its own credentials, so you can spin up as many as you need.
final client = CourierClient( jwt: "...", // Optional. Required for most authenticated calls clientKey: "...", // Optional. Used only for Inbox client-key auth userId: "your_user_id", connectionId: "...", // Optional. Used for the inbox websocket tenantId: "...", // Optional. Scopes the client to a tenant showLogs: true, // Optional. Defaults to kDebugMode);final options = client.options;