Configure the SDK

Configure Superwall in your shared Kotlin code.

Beta

The KMP SDK is in beta and its API may change between releases.

Configure

Call Superwall.configure as early as possible in your app's lifecycle, from shared code:

import com.superwall.sdk.kmp.Superwall

Superwall.configure(apiKey = "pk_your_api_key") { result ->
    result.onFailure { println("Superwall configuration failed: $it") }
}

The signature is identical on both platforms:

Prop

Type

The call is fire-and-forget. completion reports the real outcome. An invalid API key surfaces there, not as a thrown exception.

Calling configure a second time is a no-op. The repeat call logs a warning through the delegate's handleLog, does not re-install your options or purchase controller, and invokes its completion with the first call's outcome.

There is no pre-configure call queue

This is important to understand before you write anything else.

Calls made before configure are not buffered and replayed. Almost every member throws SuperwallError.NotConfigured instead.

The deliberate exemptions, which are safe to touch at any time:

  • handleDeepLink: deep-link cold start is its whole purpose
  • subscriptionStatusFlow and customerInfoFlow: pre-seeded, common-owned flows
  • delegate: stored immediately, installed natively at configure
  • isConfigured, isInitialized, and configurationStatus

Everything else (register, identify, setUserAttributes, entitlements, and the rest) needs configuration to have happened first.

Ordering your calls

Two supported ways to sequence work behind configuration.

Await it. configureAndAwait is the suspending twin, and the sanctioned ordering tool. It resumes when the native SDK reports completion and throws SuperwallError.ConfigurationFailed on failure:

suspend fun startSuperwall() {
    Superwall.configureAndAwait(apiKey = "pk_your_api_key")

    // Safe from here on.
    Superwall.identify(userId = "abc123")
}

Gate on the flag. Superwall.isConfigured is readable at any time:

if (Superwall.isConfigured) {
    Superwall.register(placement = "campaign_trigger")
}

Superwall.configurationStatus gives you the fuller picture: PENDING, CONFIGURED, or FAILED.

Options

Pass SuperwallOptions to customize behavior. Every field has a default, so set only what you need:

import com.superwall.sdk.kmp.models.options.PaywallOptions
import com.superwall.sdk.kmp.models.options.SuperwallOptions

Superwall.configure(
    apiKey = "pk_your_api_key",
    options = SuperwallOptions(
        paywalls = PaywallOptions(
            shouldPreload = false,
            isHapticFeedbackEnabled = false,
        ),
    ),
)

Frequently used SuperwallOptions fields:

Prop

Type

Some options only apply to one platform. passIdentifiersToPlayStore and useMockReviews are Android-only; shouldBypassAppTransactionCheck and maxConfigRetryCount are iOS-only. Setting one on the other platform is harmless. It is ignored. See Platform differences.

Leave networkEnvironment alone unless the Superwall team has explicitly told you otherwise.

Logging

Set the log level at configure time, or change it later:

import com.superwall.sdk.kmp.models.options.LogLevel

Superwall.logLevel = LogLevel.WARN

Levels are DEBUG, INFO, WARN, ERROR, and NONE.

On iOS, LogLevel.NONE maps to Swift's .none. If you are reading native logs or Swift docs alongside these, do not mistake it for an absent optional.

Next, present your first paywall.

How is this guide?

On this page