InAppify

Customer identity, logIn and logOut

Mobile login/logout with stable identifiers, retained Anonymous identities and Web authentication with tickets or OTP.

Authenticate the host account first, then identify the same stable account to the SDK. A customer ID does not replace a password, session or server authorization. Convert numeric IDs to strings; avoid raw email/phone as account identifiers.

Mobile login and account changes

import 'package:inappify_sdk/inappify_sdk.dart';

Future<bool> identifyCustomer(String authenticatedUserId) async {
  final result = await InappifySdk.logInResult(authenticatedUserId);
  return result.isSuccess;
}

Future<bool> signOutCustomer() async {
  final result = await InappifySdk.logOutResult();
  return result.isSuccess;
}
import com.inappify.sdk.*

suspend fun identifyCustomer(client: InappifyV2Client, userId: String) =
    client.logIn(userId)

suspend fun signOutCustomer(client: InappifyV2Client) = client.logOut()

Flutter also provides bool convenience logIn(id)/logOut(). Kotlin uses InappifyResult. Login takes only the identifier; the API key was supplied during configure. Disable purchasing during transitions and discard predecessor account UI.

Mobile custom IDs contain 1–100 code points, with no controls, edge whitespace, malformed Unicode or reserved Anonymous prefix. Send only the actual current host account identity.

Anonymous and logout

Omitted configure identity can restore a previous identity; it is not logout. Use SDK/server-generated anonymous identifiers. Do not rewrite the new $INAAnonymousID: prefix or supported legacy identities in host code.

logOut establishes the appropriate anonymous session; it does not refund, discard paid work or close the client. Do not turn a mid-logout network failure into definitive success or expose old data to the next account. Unfinished purchases retain their original owner; switching accounts does not authorize manual reassignment.

Flutter Web login

logInResult('customer_123') is unsupported on Web. For an authenticated host user, let the host's trusted backend issue a fresh short-lived, single-use ticket:

import 'package:inappify_sdk/inappify_sdk.dart';

Future<bool> authenticateWeb({
  required String publicWebKey,
  required String hostUserId,
  required Future<String> Function() fetchFreshTicket,
}) async {
  final result = await InappifySdk.configureAuthenticatedWebSessionResult(
    apiKey: publicWebKey,
    expectedCustomerIdentifier: hostUserId,
    identityTicketProvider: fetchFreshTicket,
    country: 'IR',
    appVersion: '2.0.0',
  );
  return result.isSuccess;
}

The helper requests tickets when needed and checks the expected identity. Do not mint tickets in the browser or blindly replay one after uncertainty. For explicit login after configure, call either loginWithIdentityTicketResult(identityTicket: ...) or its alias exchangeIdentityTicketResult(...), never both with the same ticket.

JavaScript login and OTP

import type { InAppify } from '@inappifylabs/web-sdk';

export async function loginWithTicket(client: InAppify, freshTicket: string) {
  return client.logIn({ identityTicket: freshTicket });
}

export async function loginWithOtp(client: InAppify, challengeId: string, code: string) {
  return client.logIn({ challengeId, code });
}

For OTP, call requestOtp({phone, captchaKey?, captchaAnswer?}), using createOtpCaptcha() when required, and render the returned challenge. Verify its challengeId and the user-entered code. Flutter equivalents are requestOtpResult, createOtpCaptchaResult and verifyOtpResult(challengeId:, code:). SMS must follow user action, not live automated testing.

Use client logOut() in JS and logOutResult() in Flutter. Temporary network/storage unavailability alone is not logout; inspect session state, snapshots and sessionStateChanges.

Load offerings · Web guide