Flutter SDK (v2.0+)
The AeroSync Flutter SDK provides an interface to load Aerosync-UI in Flutter apps for iOS, Android, and Flutter Web. It allows users to securely connect their bank accounts through a fast, tokenized login — your users' banking credentials are never shared with or stored by your application.
Looking for the old (v1.3.4) API?This page documents SDK v2.1.1. If your app still depends on
aerosync_flutter_sdk: ^1.3.4, see the Flutter Plugin (Legacy v1.3.4) page for that API reference, or jump to Migrating from v1.x below to upgrade.
Create a User
The Aerosync+Aeronetwork SDKs require a user identifier, aeroPassUserUuid, to be passed to the widget on launch. Follow the guide here to create a new user and access the user's aeroPassUserUuid.
Features
- iOS & Android: Native WebView with full OAuth deeplink support
- Flutter Web — System Browser mode: Widget opens in a centered popup window; OAuth flows inside the popup also open as proper popup windows (no cross-origin restrictions)
- Flutter Web — Host mode: Widget renders inline as an iframe embed
- MFA Support: Multi-factor authentication handling
- Multi-Account Linking: Return multiple linked accounts from a single flow (v2.1.0+)
- Customizable: Theming and styling options
Requirements
- Flutter 3.44+
- Dart 3.3+
- iOS 11.0+ / Android API level 21+
Installation
1. Add the dependency to pubspec.yaml:
dependencies:
aerosync_flutter_sdk: ^2.1.12. Install dependencies:
flutter pub get3. Import the library:
import 'package:aerosync_flutter_sdk/aerosync_flutter_sdk.dart';Mobile Integration (iOS & Android)
1. Configure deep linking
OAuth authentication redirects require a URL scheme registered on each platform.
Android — add an intent-filter inside your <activity> in android/app/src/main/AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourapp" android:host="connect" />
</intent-filter>iOS — add the URL scheme to ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>2. Add the navigator observer
Add AeroSyncNavigatorObserver to your MaterialApp. This is required for iOS OAuth return to work correctly — without it, returning from the external browser pushes a spurious route that hides the widget.
const _deeplink = 'yourapp://connect';
MaterialApp(
navigatorObservers: [AeroSyncNavigatorObserver(deeplink: _deeplink)],
home: const HomePage(),
)3. Launch the widget
Show AeroSyncWidget via Navigator.push. The SDK auto-dismisses when onSuccess or onClose fires — do not call Navigator.pop inside these callbacks, it will cause a double-pop crash.
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(title: const Text('Link Your Bank')),
body: AeroSyncWidget(
token: 'your-token-here',
environment: 'sandbox', // 'sandbox' or 'production'
deeplink: 'yourapp://connect',
aeroPassUserUuid: 'user-uuid-123',
configurationId: 'your-config-id', // Optional
theme: 'light', // 'light' or 'dark'
style: {'bgColor': '#FFFFFF', 'opacity': 1.0}, // Optional
onSuccess: (data) {
// Bank linking completed — data contains account details.
// Do NOT call Navigator.pop — the SDK handles dismissal.
},
onClose: (data) {
// User closed the widget.
// Do NOT call Navigator.pop — the SDK handles dismissal.
},
onEvent: (data) {},
onError: (data) {},
onLoad: (data) {},
),
),
));MFA flow
AeroSyncWidget(
token: 'your-token-here',
environment: 'sandbox',
deeplink: 'yourapp://connect',
aeroPassUserUuid: 'user-uuid-123',
handleMFA: true,
jobId: 'your-job-id',
connectionId: 'your-connection-id',
onSuccess: (data) {},
onClose: (data) {},
onEvent: (data) {},
onError: (data) {},
onLoad: (data) {},
)Flutter Web Integration
On Flutter Web the deeplink parameter is automatically omitted from the widget URL — it would override the browser's return URL and break OAuth redirects back to your web app. Pass any value (or an empty string); it is ignored at runtime.
Two launch modes are available via the widgetLaunchType parameter.
System Browser mode — recommended (widgetLaunchType: 'systemBrowser')
widgetLaunchType: 'systemBrowser')The widget opens in a centered popup window launched from a user gesture. Because the popup runs in a top-level browsing context, OAuth bank redirects also open as proper popup windows (not tabs), avoiding Chrome's cross-origin iframe restriction.
The SDK shows a "Link Your Bank" button in your app; tapping it opens the popup. While the popup is open, a spinner is shown. The popup closes automatically when the flow completes.
AeroSyncWidget(
token: 'your-token-here',
environment: 'sandbox',
deeplink: '', // ignored on web
aeroPassUserUuid: 'user-uuid-123',
widgetLaunchType: 'systemBrowser', // opens as popup window
onSuccess: (data) {
// Do NOT call Navigator.pop — the SDK handles dismissal.
},
onClose: (data) {},
onEvent: (data) {},
onError: (data) {},
onLoad: (data) {},
)
Popup blocked?Browsers require a user gesture to open popups. Make sure the widget is launched from a button tap (not programmatically on page load). If the popup is still blocked, instruct users to allow popups for your domain.
Host mode (widgetLaunchType: 'host')
widgetLaunchType: 'host')The widget renders inline as an <iframe> embed directly in your Flutter Web page. Use this when you want the bank-link UI as part of the page layout.
Some banks use OAuth flows that Chrome opens as a new tab instead of a popup window when triggered from a cross-origin iframe.systemBrowsermode avoids this limitation entirely.
AeroSyncWidget(
token: 'your-token-here',
environment: 'sandbox',
deeplink: '', // ignored on web
aeroPassUserUuid: 'user-uuid-123',
widgetLaunchType: 'host', // inline iframe embed
onSuccess: (data) {
// Do NOT call Navigator.pop — the SDK handles dismissal.
},
onClose: (data) {},
onEvent: (data) {},
onError: (data) {},
onLoad: (data) {},
)API Reference
To generate a token, see the AeroSync integration guide.
AeroSyncWidget parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
token | String | Yes | — | Authentication token for the session |
environment | String | Yes | — | "sandbox" or "production" |
deeplink | String | Yes | — | Deep link URL for OAuth redirects (mobile only; ignored on web) |
aeroPassUserUuid | String | Yes | — | AeroPass user UUID |
widgetLaunchType | String | No | 'systemBrowser' | Web only: 'systemBrowser' (popup) or 'host' (iframe) |
configurationId | String? | No | — | Configuration ID for customization |
theme | String | No | 'light' | UI theme: "light" or "dark" |
style | Map | No | {} | Container styling — see Style properties |
handleMFA | bool? | No | — | Enable MFA flow handling |
jobId | String? | No | — | Job ID — required when handleMFA is true |
connectionId | String? | No | — | Connection ID — required when handleMFA is true |
manualLinkOnly | bool | No | false | Show only manual linking options |
Style properties
The style map controls the native container that wraps the widget — it does not affect the widget's internal appearance.
| Property | Type | Description |
|---|---|---|
bgColor | String | Background color of the container (hex, e.g. "#FFFFFF") |
opacity | double | Transparency of the container — 1.0 is fully opaque, 0.0 is fully transparent |
style: {
'bgColor': '#000000',
'opacity': 0.9,
}AeroSyncNavigatorObserver
| Parameter | Type | Required | Description |
|---|---|---|---|
deeplink | String | Yes | Must match the deeplink passed to AeroSyncWidget |
AeroSyncNavigatorObserveris mobile-only and has no effect on Flutter Web.
Callback events
| Callback | Description |
|---|---|
onSuccess | Bank connection completed successfully — receives account details |
onClose | User closed the widget |
onEvent | General widget events and page navigation |
onError | Error occurred during the process |
onLoad | Widget finished loading |
Success Response Format
The onSuccess callback receives a map with the following structure:
{
"type": "pageSuccess",
"payload": {
"connectionId": "33e1121dde934c5cb5b964b325e28728",
"aeroPassUserUuid": "b120bcb5-2f39-48d3-a654-1c437c1ec175",
"clientName": "Aeropay"
}
}| Field | Description |
|---|---|
connectionId | Unique identifier for the bank connection |
aeroPassUserUuid | AeroPass UUID for the authenticated user |
clientName | Your registered client name on the AeroSync platform |
Multi-Account Linking (v2.1.0+)
If your AeroSync configuration has multi-account linking enabled, the same onSuccess event instead carries a list of linked accounts:
{
"type": "pageSuccess",
"payload": {
"accounts": [
{ "connectionId": "33e1121dde934c5cb5b964b325e28728", "accountType": "checking", "accountNumberDisplay": "••••1234" },
{ "connectionId": "84f2232eef045d6dc6a075436f39839", "accountType": "savings", "accountNumberDisplay": "••••5678" }
],
"clientName": "Aeropay",
"aeroPassUserUuid": "b120bcb5-2f39-48d3-a654-1c437c1ec175"
}
}| Field | Description |
|---|---|
accounts | List of linked accounts (multi-account only) — each has connectionId, accountType, accountNumberDisplay |
Multi-account linking is opt-in and configured server-side on your AeroSync configuration — no extra widget parameters are required to receive it. AeroSyncWidget.onSuccess keeps its existing untyped signature either way, so adopting the typed models below is optional and non-breaking.
Use AeroSyncSuccessPayload.fromJson to parse the map and narrow with is:
onSuccess: (data) {
if (data is Map<String, dynamic>) {
final result = AeroSyncSuccessPayload.fromJson(data);
if (result is AeroSyncMultiAccountSuccessPayload) {
for (final account in result.accounts) {
print('${account.accountType}: ${account.accountNumberDisplay}');
}
} else if (result is AeroSyncSingleAccountSuccessPayload) {
print('Connected: ${result.connectionId}');
}
}
},
Distinguishing single vs. multi-account
AeroSyncSuccessPayload.fromJsonselectsAeroSyncMultiAccountSuccessPayloadwhen the payload has anaccountslist, otherwiseAeroSyncSingleAccountSuccessPayload. Useis/is!to narrow — the base type is a plainabstract class, notsealed, so exhaustiveswitchisn't available.
Platform-Specific Notes
iOS
- Deployment target: iOS 11.0+
- All dependencies support Swift Package Manager — no CocoaPods step required
Android
- Minimum SDK version: 21
- Add to
android/app/src/main/AndroidManifest.xml:
<!-- Required — app will crash immediately without this -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Required for Android 11+ — allows the SDK to open OAuth URLs in the browser -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
</intent>
</queries>Flutter Web
- No additional packages or configuration needed — the SDK detects
kIsWeband uses the appropriate path automatically AeroSyncNavigatorObserveris not needed on webdeeplinkis silently omitted from the widget URL on web
Migrating from v1.x
SDK v2.0.0 introduced several breaking changes. If you're upgrading from ^1.3.4, update your integration as follows:
| v1.3.4 | v2.1.1 | Notes |
|---|---|---|
AerosyncSDKPage | AeroSyncWidget | Widget renamed |
env | environment | Parameter renamed |
consumerId | configurationId | Parameter renamed |
| — | aeroPassUserUuid | New required parameter — must be added to every AeroSyncWidget usage. See Create a User to generate one. |
userId (MFA) | connectionId (MFA) | MFA parameter renamed |
style: {width, height, bgColor} | style: {bgColor, opacity} | width/height removed (container is sized by your layout); opacity added |
onSuccess(EventType type, dynamic data) with data as a JSON-encoded string | onSuccess(dynamic data) with data as an already-decoded Map | Two-arg callback → single-arg; drop your jsonDecode(data) call |
Success payload: {user_id, user_password, ClientName, FILoginAcctId} | Success payload: {connectionId, clientName, aeroPassUserUuid} (or {accounts: [...], clientName, aeroPassUserUuid} for multi-account) | Field names and shape changed |
env values: dev, staging, sandbox, production | environment values: sandbox, production only | dev/staging no longer supported |
Manual Navigator.pop required in some flows | SDK auto-dismisses on onSuccess/onClose | Remove any Navigator.pop calls from these callbacks — calling it yourself will cause a double-pop crash |
AeroSyncEmbeddedView | (removed) | Will be re-introduced in a future release |
| No Flutter Web popup mode | widgetLaunchType: 'systemBrowser' (default) or 'host' | New in 2.0.0 |
No AeroSyncNavigatorObserver | AeroSyncNavigatorObserver | New — required on mobile for correct iOS OAuth return routing |
See the Flutter Plugin (Legacy v1.3.4) page for the full old API reference while you migrate.
Troubleshooting
- Widget not loading: Verify your token is valid and not expired
- OAuth return drops user to home screen (mobile): Ensure
AeroSyncNavigatorObserveris added toMaterialApp.navigatorObservers - Popup blocked (web): The widget must be opened from a button tap. Allow popups for your domain in browser settings if needed
- OAuth opens as a tab instead of a popup (web): Switch to
widgetLaunchType: 'systemBrowser'—hostmode (iframe) is subject to Chrome's cross-origin popup restriction - OAuth browser never opens on Android: Ensure the
<queries>block is present inAndroidManifest.xml(see Android above). Android 11+ requires explicit intent visibility declarations for the SDK to resolve a browser app - Build errors: Run
flutter cleanandflutter pub get
Support
For technical support and questions, please contact our development team.
License
This SDK is proprietary software. Please refer to your license agreement for usage terms.
Updated about 1 month ago