● New: build your backend and app together with AI. Point Claude or Cursor at AppAmbit over MCP.
On mobile?
Email yourself the setup link so you can finish when you're at your computer.
✓ Email sent! Check your inbox.
× Failed to send. Please try again.
⏱ Too many attempts. Please wait a few minutes and try again.
Flutter · Dart
One line in main. Both stores report back.
Add one package from pub.dev and call AppAmbitSdk.start() once, and your Flutter app reports sessions, device details and crashes on its own. The package carries both native sides with it, so there is no Swift or Kotlin for you to write.
import'package:flutter/material.dart';import'package:appambit_sdk_flutter/appambit_sdk_flutter.dart';voidmain() async {WidgetsFlutterBinding.ensureInitialized();// the whole integrationawait AppAmbitSdk.start(appKey: '<YOUR-APPKEY>');runApp(constMyApp());}
Sessions, device details and crashes start from that call.appambit_sdk_flutter 1.2.1
One
Package from pub.dev. It carries both native sides.
Two
Apps in AppAmbit, one codebase. iOS and Android.
Zero
Lines of native code you have to write.
3.9
Minimum Dart SDK. Flutter 3.3 and up.
Screen breadcrumbs
Your screens are widgets. Give the SDK the observer.
On a native project the SDK sees every screen the system pushes. In Flutter the routes live in your Dart code, so the native side is blind to them until you hand over an observer. AppAmbitSdk is a NavigatorObserver, so one entry in navigatorObservers is the whole of it, with nothing added inside your screens.
01
Hand it to MaterialApp
Pass navigatorObservers: [AppAmbitSdk()] where you build your app. Once is enough for the life of the app.
02
Name your routes
A breadcrumb carries the route's settings.name, so a page pushed as /cart reads as itself. An unnamed route falls back to its runtime type, which is nobody's idea of a screen name.
03
Pages only, on purpose
Only a PageRoute is recorded, so dialogs, sheets and menus stay out of it and the trail is the screens a person actually moved through.
Every crash lands inside the session that led to it, with the run-up already attached.
One codebase, two App Keys
Dart does not care which store it shipped to. AppAmbit does.
An app in AppAmbit belongs to one operating system, so a Flutter project that reaches both stores gets an iOS app and an Android app. Pick between their keys where you start the SDK and the rest of your code never has to know which one it got.
Two apps in the dashboard, each with its own App Key on its Info page and its own crash list. An Android crash never lands in the iOS app.
The same calls either way. AppAmbitSdk.trackEvent, AppAmbitSdk.logError and the rest are identical on both sides of the switch.
One place to read them. Both apps sit in the same team, so the crash you are chasing is two clicks from the one you just read.
One team, one App Key per store, and both of them on the same free tier.
The whole API
Six things to write, and you have seen all of it.
There is no client to configure, no pipeline to describe and no schema to declare. Five of these are static calls on the same class, awaited like anything else in Dart, and the sixth is an observer you hand to MaterialApp once.
AppAmbitSdk.start(appKey: key)
Turn it on
One call in main, after the binding is ready. Sessions, device details and crashes start from that line.
The SDK is a NavigatorObserver. Give one to your MaterialApp and every push, pop and replace becomes a breadcrumb, with nothing to instrument inside your screens.
The same list, for the times you have a sentence and no exception object. Properties work here too.
AppAmbitSdk.generateTestCrash()
Prove the pipeline
Force one on purpose and watch it arrive. The fastest way to know the App Key and the build are wired up.
Sessions are automatic. If you would rather draw their boundaries yourself, call AppAmbitSdk.enableManualSession() before starting the SDK and then startSession() and endSession() where they belong.
The context comes with it. A crash arrives inside the session it happened in, next to the breadcrumbs and the events that came before it, so you read the run-up rather than a bare stack.
That is the whole surface. The key that makes those calls report takes a minute to create.
Everything else in the account
The rest of AppAmbit is already pointed at this app.
All of it runs on the App Key you pasted into main and the team the app belongs to. Nothing on this row is another vendor to pick, another SDK to add or another invoice to get approved.
App Analytics
Who opened the app, on which OS version and build, and how long they stayed before they left.
Everything on this row is included, on the same App Key and the same free tier.
Build delivery
The build your tester installs is the build you read crashes from.
A Flutter release is two artifacts, and both can land here. Upload the ipa and the apk from the CI you already run, hand testers a link, and the crashes that come back are already tied to the build they came from. The build guides have the pipeline steps.
Connect the repository, and testers install from a link instead of waiting on a store.
Setup
Three steps, and none of them are native.
Create your app in the dashboard to get an App Key, then add one dependency and one call. The last step is the only place the two platforms differ, and only in which device you point the run at.
01
Add the package
One dependency, from pub.dev. Version 1.2.1 is the current release. The iOS and Android sides ship inside it, so this is the only install.
# the current releaseflutter pub add appambit_sdk_flutter
// or pin it yourself, then flutter pub getdependencies:flutter:sdk: flutterappambit_sdk_flutter: ^1.2.1
Flutter resolves the native dependency for both platforms.Dart 3.9+
02
Start it in main
After ensureInitialized() and before runApp, so the SDK is up before the first frame and the first session covers the whole launch.
The App Key is on the app's Info page in the dashboard.One call
03
Run it on a device
A hot reload will not pick up a new native dependency, so this first one has to be a full run. On iOS the Flutter tool installs the pod for you; on Android Gradle resolves it.
Terminal · iOSTerminal · Android
# pods are installed by the tool on the first runflutter run -d ios
# gradle resolves the native side on the first runflutter run -d android
The session lands while the app is still on screen.The session lands while the app is still on screen.Done
Prefer the long version? The getting started guide covers the same three steps with the dashboard screens next to them.
Step one is a free account. The other two take about five minutes.
Push notifications
One more package, not another vendor.
Push runs on the same App Key and the same install. You bring a Firebase project and its two config files, AppAmbit keeps the device tokens, and you send from the dashboard or from a Cloud Code function.
Add appambit_sdk_push_notifications next to the core package and start it after the SDK. On iOS the pods resolve on their own; Android wants the Google Services plugin and Firebase Messaging in Gradle.
Two listeners, and a handler for the killed app. setForegroundListener and setOpenedListener work on both platforms. On Android, Android.setBackgroundHandler runs a top-level function in its own isolate; on iOS that work belongs in the Notification Service Extension.
The payload is typed. PushNotificationData carries title, body, imageUrl and your own data map, plus the android and ios blocks for the fields only one platform has.
await AppAmbitSdk.start(appKey: '<YOUR-APPKEY>');PushNotificationsSdk.start();// ask when the moment makes sense, not at launchPushNotificationsSdk.requestNotificationPermission();// fires when the user taps one, in any app statePushNotificationsSdk.setOpenedListener((push) {final screen = push.data?['screen'];if (screen != null) openScreen(screen);});
Both calls go after AppAmbitSdk.start, which registers the device.Android and iOS
Your own credentials, the tokens already tied to your App Key, and no second vendor to sign with.
Questions
Answered straight.
Do I need one App Key or two?
Two. An app in AppAmbit belongs to one operating system, so a Flutter project that ships to both stores has an iOS app and an Android app, each with its own App Key and its own crash list. Pick between them where you call AppAmbitSdk.start, and the rest of your Dart code never has to know which one it got.
Do I have to write any native code?
No. The package ships the iOS and Android sides with it. You add one dependency, call AppAmbitSdk.start in main, and build as usual: the Flutter tool installs the CocoaPods dependency on iOS and Gradle picks the Android one up on its own.
What are the minimum versions?
Flutter 3.3.0 and Dart 3.9.0 for the package itself. On top of that you keep whatever iOS and Android minimums your own Flutter app already declares.
Does it work on Flutter web or desktop?
Not today. The package declares Android and iOS, which are the two platforms it ships native code for. A web or desktop build will not find an implementation.
How do I report an error I already caught?
Call AppAmbitSdk.logError with the exception and its stack trace, or with a message when there is no exception object to hand. Both take an optional properties map, so you can attach the ids you will want when you read it back.
Are the database and the CMS part of the same package?
Yes. AppAmbitDb, CloudCode and AppAmbitCms come from the same import as AppAmbitSdk and go out on the App Key you already started the SDK with. There is no second package to add and no second set of credentials to ship.
Can I read remote values without shipping a release?
Yes. Call AppAmbitSdk.enableConfig before you start the SDK, then read values with getString, getLong, getDouble and getBoolean. The values come from your dashboard, so changing one does not need a new build.
Building for the other platforms too? AppAmbit has an SDK for iOS, Android, React Native, .NET MAUI, .NET and Avalonia. Each one takes its own App Key and reports into the same dashboard, on the same team and the same bill.
The free tier is enough to point the SDK at a real build and read your own sessions.
Ready when you are
Add the package. Watch the first session land.
Create a free account, paste your App Key into main, and run the app. The first session shows up while it is still on screen, and the next crash comes back with the device and the session it happened in. Flutter 3.3 and up, no credit card.