--- title: "Await SDK calls" slug: "flutter-await-sdk-calls" description: "Await Flutter SDK calls in Insider One: flutter_insider 5.5.0 methods return a Future, and loginAsync resolves to the merged Insider ID." updated: 2026-11-04T13:07:14Z published: 2026-11-04T13:07:14Z canonical: "academy.insiderone.com/flutter-await-sdk-calls" --- > ## Documentation Index > Fetch the complete documentation index at: https://academy.insiderone.com/llms.txt > Use this file to discover all available pages before exploring further. # Await SDK calls Starting with flutter_insider 5.5.0, the identity, in-app message, and App Cards tracking methods that used to be fire-and-forget return a Future. You can await a call before making the next one, so your calls run in order. Two new identity methods, loginAsync and logoutResettingInsiderIDAsync, also resolve to the merged Insider ID. The native SDK and the data it sends do not change, and existing call sites keep compiling. > [!NOTE] > login and logoutResettingInsiderID keep their void signature and the optional insiderIDResult callback. The awaitable forms are the separate methods loginAsync and logoutResettingInsiderIDAsync. This guide explains the following concepts: - [Prerequisites](/v1/docs/flutter-await-sdk-calls#prerequisites) - [Async model](/v1/docs/flutter-await-sdk-calls#async-model) - [Error handling](/v1/docs/flutter-await-sdk-calls#error-handling) - [Available methods](/v1/docs/flutter-await-sdk-calls#available-methods) - [Migration notes](/v1/docs/flutter-await-sdk-calls#migration-notes) - [Full integration example](/v1/docs/flutter-await-sdk-calls#full-integration-example) ## Prerequisites - Insider Flutter Plugin flutter_insider: 5.5.0 or later - The SDK initialized with FlutterInsider.Instance.init(...) before you call any of the methods below --- Identity methods live on the user object, App Cards tracking methods on the App Cards client, and the in-app message and deep link methods on the main SDK singleton. ```dart import 'package:flutter_insider/flutter_insider.dart'; import 'package:flutter_insider/src/identifiers.dart'; final user = FlutterInsider.Instance.getCurrentUser(); final appCards = FlutterInsider.Instance.appCards; ``` > [!NOTE] > FlutterInsiderIdentifiers is not re-exported by the main library. Import package:flutter_insider/src/identifiers.dart where you build identifiers. This is a temporary workaround until the class is exported from the main library. > [!NOTE] > getCurrentUser() returns null until init has been called. Guard it with ?. or check for null before you call an identity method. ## Async model Two kinds of methods became awaitable. | Kind | Return type | Completes when | Result | | --- | --- | --- | --- | | **Tracking and lifecycle** logout, view, click, clickButton, disableInAppMessages, enableInAppMessages, handleUniversalLink | Future | The native SDK call has returned | No value | | **Identity** loginAsync, logoutResettingInsiderIDAsync | Future | The native SDK has merged or reset the user, or timeout elapses | The Insider ID, or null | ```dart // Order two calls: the second starts after the first has reached the native SDK await FlutterInsider.Instance.disableInAppMessages(); await FlutterInsider.Instance.enableInAppMessages(); // Wait for the merged Insider ID final insiderID = await user.loginAsync(identifiers); ``` ### Timeout loginAsync and logoutResettingInsiderIDAsync take a named timeout (default 10 seconds). The native SDK answers only after a successful merge or reset. If the device is offline, a request fails, or a retry is pending, the native SDK never calls back. The Future then resolves to null once timeout elapses. - A timeout does not cancel the native call. The merge can still complete afterward, and the SDK keeps the resulting Insider ID. - timeout must be positive. Raise it per call when you expect a slow network. - After a null, FlutterInsider.Instance.getInsiderID() returns the ID the SDK holds at that moment, which can still be the pre-merge ID. To be told when the merged ID arrives, register FlutterInsider.Instance.registerInsiderIDListener(...). ```dart final insiderID = await user.loginAsync(  identifiers,  timeout: const Duration(seconds: 30), ); ``` ## Error handling None of the methods on this page throw. App Cards retrieval methods such as getCampaigns still throw InsiderAppCardsException. See [Configure app cards](/docs/flutter-configure-app-cards) for details. When a native call fails, the SDK reports the failure and the Future still completes. Future methods complete normally, and the identity methods resolve to null. The SDK also reports a failure that arrives after the timeout. Three cases resolve loginAsync and logoutResettingInsiderIDAsync to null. You cannot tell them apart from the return value: | Case | What happened | | --- | --- | | **No ID delivered** | The native SDK finished without an Insider ID. For loginAsync, this also happens when the identifier set is empty, and the call is not sent. | | **Native failure** | The native call failed, and the SDK reported the failure. | | **Timeout** | timeout elapsed before the native SDK answered. The call can still complete. | ```dart final insiderID = await user.loginAsync(identifiers); if (insiderID == null) {  // No ID, native failure, or timeout. The SDK can still merge the user later;  // read the current ID when you need it.  final currentID = await FlutterInsider.Instance.getInsiderID();  print('Insider ID after login attempt: $currentID'); } else {  print('Logged in as $insiderID'); } ``` ## Available methods ### Identity #### loginAsync Identifies the user with one or more identifiers and resolves to the merged Insider ID. This is the awaitable form of login with insiderIDResult. | Name | Type | Required | Description | | --- | --- | --- | --- | | identifiers | FlutterInsiderIdentifiers | Yes | Email, phone number, user ID, or custom identifiers. An empty set is not sent and resolves to null. | | timeout | Duration | No | How long to wait for the native SDK. Default: Duration(seconds: 10). Must be positive. | **Signature:** ```dart Future loginAsync(  FlutterInsiderIdentifiers identifiers, {  Duration timeout = const Duration(seconds: 10), }) ``` **Example:** ```dart final identifiers = FlutterInsiderIdentifiers()  ..addEmail('user@example.com')  ..addUserID('user-001'); final insiderID = await FlutterInsider.Instance.getCurrentUser()?.loginAsync(identifiers); print('Insider ID: $insiderID'); ``` > [!TIP] > Keep using login(identifiers, insiderIDResult: ...) when you want the callback style. loginAsync sends the same request as login with a callback. #### logout Logs the current user out and keeps the existing Insider ID. **Signature:** ```dart Future logout() ``` **Example:** ```dart await FlutterInsider.Instance.getCurrentUser()?.logout(); ``` #### logoutResettingInsiderIDAsync Logs the user out, resets the Insider ID, and resolves to the new one. This is the awaitable form of logoutResettingInsiderID with insiderIDResult. | Name | Type | Required | Description | | --- | --- | --- | --- | | additionalIdentifiers | List? | Yes | Identifiers attached to the new anonymous identity. Pass null for none. | | timeout | Duration | No | How long to wait for the native SDK. Default: Duration(seconds: 10). Must be positive. | **Signature:** ```dart Future logoutResettingInsiderIDAsync(  List? additionalIdentifiers, {  Duration timeout = const Duration(seconds: 10), }) ``` **Example:** ```dart final newInsiderID = await FlutterInsider.Instance    .getCurrentUser()    ?.logoutResettingInsiderIDAsync(null); print('New Insider ID: $newInsiderID'); ``` ### In-app messages and deep links #### disableInAppMessages Suppresses in-app messages until you call enableInAppMessages. **Signature:** ```dart Future disableInAppMessages() ``` **Example:** ```dart await FlutterInsider.Instance.disableInAppMessages(); ``` #### enableInAppMessages Re-enables in-app messages after a previous disableInAppMessages call. **Signature:** ```dart Future enableInAppMessages() ``` **Example:** ```dart await FlutterInsider.Instance.disableInAppMessages(); // Show your own full-screen flow, then await FlutterInsider.Instance.enableInAppMessages(); ``` #### handleUniversalLink Lets the Insider SDK process a deep link or universal link. Call it from your link handler. | Name | Type | Required | Description | | --- | --- | --- | --- | | url | String | Yes | The link to hand to the SDK. | **Signature:** ```dart Future handleUniversalLink(String url) ``` **Example:** ```dart await FlutterInsider.Instance.handleUniversalLink('https://example.com/campaign?ins=1'); ``` ### App Cards tracking The App Cards tracking methods return a Future that completes when the native SDK call has returned. See [Configure app cards](/docs/flutter-configure-app-cards) for the card model and the retrieval methods. | Method | Signature | | --- | --- | | FlutterInsiderAppCards.view | Future view(InsiderAppCard appCard) | | FlutterInsiderAppCards.click | Future click(InsiderAppCard appCard) | | FlutterInsiderAppCards.clickButton | Future clickButton(InsiderAppCardButton button) | | InsiderAppCard.view | Future view() | | InsiderAppCard.click | Future click() | | InsiderAppCardButton.click | Future click() | **Example:** ```dart final appCards = FlutterInsider.Instance.appCards; try {  final response = await appCards.getCampaigns();  for (final card in response?.appCards ?? []) {    await card.view();  } } on InsiderAppCardsException catch (e) {  print('Failed to get campaigns: ${e.error.code}'); } ``` ## Migration notes Call sites compile unchanged. A Future returned from a method you used to call as void is dropped. Two things can change in your project: - **Lint hits:** With unawaited_futures or discarded_futures enabled, the linter reports every existing call to one of these methods. Either await the call or wrap it in unawaited(...) from dart:async. - **Test doubles:** A fake or mock that overrides one of these methods with a void body, or an unstubbed mock, now has to return a Future. Return Future.value() for Future, and Future.value(null) or an ID string for Future. To keep the fire-and-forget behavior explicitly, wrap the call in unawaited: ```dart import 'dart:async'; // Keep the fire-and-forget behaviour explicitly unawaited(FlutterInsider.Instance.handleUniversalLink(url)); ``` ## Full integration example The following example signs a user in and out. It keeps in-app messages away from the sign-in screen and handles a login that returns no Insider ID. ```dart import 'package:flutter_insider/flutter_insider.dart'; import 'package:flutter_insider/src/identifiers.dart'; Future signIn(String email, String userID) async {  final user = FlutterInsider.Instance.getCurrentUser();  if (user == null) {    return;  }  // Keep in-app messages out of the way while the sign-in screen is up  await FlutterInsider.Instance.disableInAppMessages();  final identifiers = FlutterInsiderIdentifiers()    ..addEmail(email)    ..addUserID(userID);  final insiderID = await user.loginAsync(    identifiers,    timeout: const Duration(seconds: 15),  );  if (insiderID == null) {    final currentID = await FlutterInsider.Instance.getInsiderID();    print('Login not confirmed; current Insider ID: $currentID');  } else {    print('Logged in as $insiderID');  }  // Resumes only after the native call has returned  await FlutterInsider.Instance.enableInAppMessages(); } Future signOut() async {  final user = FlutterInsider.Instance.getCurrentUser();  if (user == null) {    return;  }  final newInsiderID = await user.logoutResettingInsiderIDAsync(null);  print('Anonymous Insider ID: $newInsiderID'); } ``` --- Awaiting SDK calls lets you run Flutter SDK calls in order and read the merged Insider ID when a login or logout finishes. For the individual methods, see the [user object](/docs/flutter-user-object), [block in-app messages](/docs/block-inapps-3), [handle universal links](/docs/handle-universal-links), and [configure app cards](/docs/flutter-configure-app-cards) pages.