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.1

2. Install dependencies:

flutter pub get

3. 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')

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')

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. systemBrowser mode 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

ParameterTypeRequiredDefaultDescription
tokenStringYes—Authentication token for the session
environmentStringYes—"sandbox" or "production"
deeplinkStringYes—Deep link URL for OAuth redirects (mobile only; ignored on web)
aeroPassUserUuidStringYes—AeroPass user UUID
widgetLaunchTypeStringNo'systemBrowser'Web only: 'systemBrowser' (popup) or 'host' (iframe)
configurationIdString?No—Configuration ID for customization
themeStringNo'light'UI theme: "light" or "dark"
styleMapNo{}Container styling — see Style properties
handleMFAbool?No—Enable MFA flow handling
jobIdString?No—Job ID — required when handleMFA is true
connectionIdString?No—Connection ID — required when handleMFA is true
manualLinkOnlyboolNofalseShow 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.

PropertyTypeDescription
bgColorStringBackground color of the container (hex, e.g. "#FFFFFF")
opacitydoubleTransparency of the container — 1.0 is fully opaque, 0.0 is fully transparent
style: {
  'bgColor': '#000000',
  'opacity': 0.9,
}

AeroSyncNavigatorObserver

ParameterTypeRequiredDescription
deeplinkStringYesMust match the deeplink passed to AeroSyncWidget
📘

AeroSyncNavigatorObserver is mobile-only and has no effect on Flutter Web.

Callback events

CallbackDescription
onSuccessBank connection completed successfully — receives account details
onCloseUser closed the widget
onEventGeneral widget events and page navigation
onErrorError occurred during the process
onLoadWidget 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"
  }
}
FieldDescription
connectionIdUnique identifier for the bank connection
aeroPassUserUuidAeroPass UUID for the authenticated user
clientNameYour 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"
  }
}
FieldDescription
accountsList 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.fromJson selects AeroSyncMultiAccountSuccessPayload when the payload has an accounts list, otherwise AeroSyncSingleAccountSuccessPayload. Use is/is! to narrow — the base type is a plain abstract class, not sealed, so exhaustive switch isn'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 kIsWeb and uses the appropriate path automatically
  • AeroSyncNavigatorObserver is not needed on web
  • deeplink is 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.4v2.1.1Notes
AerosyncSDKPageAeroSyncWidgetWidget renamed
envenvironmentParameter renamed
consumerIdconfigurationIdParameter renamed
—aeroPassUserUuidNew 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 stringonSuccess(dynamic data) with data as an already-decoded MapTwo-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, productionenvironment values: sandbox, production onlydev/staging no longer supported
Manual Navigator.pop required in some flowsSDK auto-dismisses on onSuccess/onCloseRemove 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 modewidgetLaunchType: 'systemBrowser' (default) or 'host'New in 2.0.0
No AeroSyncNavigatorObserverAeroSyncNavigatorObserverNew — 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

  1. Widget not loading: Verify your token is valid and not expired
  2. OAuth return drops user to home screen (mobile): Ensure AeroSyncNavigatorObserver is added to MaterialApp.navigatorObservers
  3. Popup blocked (web): The widget must be opened from a button tap. Allow popups for your domain in browser settings if needed
  4. OAuth opens as a tab instead of a popup (web): Switch to widgetLaunchType: 'systemBrowser' — host mode (iframe) is subject to Chrome's cross-origin popup restriction
  5. OAuth browser never opens on Android: Ensure the <queries> block is present in AndroidManifest.xml (see Android above). Android 11+ requires explicit intent visibility declarations for the SDK to resolve a browser app
  6. Build errors: Run flutter clean and flutter 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.


Did this page help you?