> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appstack.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Kotlin SDK changelog

> Every release of the Appstack Kotlin SDK, newest first.

Releases of the `tech.appstack.android-sdk:appstack-android-sdk` artifact, newest first. Always integrate against the latest
stable release — [`appstack-cli review`](/tooling/cli) will tell you what you
are on.

<Card title="Kotlin integration guide" icon="book-open" href="/SDKs/kotlin">
  Install, configure, and send your first events.
</Card>

<Update label="1.8.0" description="2026-09-02" tags={["Added"]}>
  **Added**

  * Custom event parameters are encrypted on the device before being sent, so personal data such as an
    email or phone number leaves the app already protected. Parameter names that need to stay readable
    — for example `currency`, `revenue` and campaign fields — are excluded, and that list is
    controlled server-side, so no code change is required in your app. Revenue is still read out of the
    parameters before encryption, so revenue reporting is unchanged, as are purchase details and
    deeplink user data. A value that cannot be encrypted is omitted from the event, and the rest of the
    event still sends. Works down to the SDK's minimum API level 21, adds no new dependency, and grows
    the release AAR by roughly 36 KB.
</Update>

<Update label="1.7.0" description="2026-08-11" tags={["Added","Fixed"]}>
  **Added**

  * `setCustomerUserId(customerUserId: String?)` sets the customer user id after `configure()`, for
    when the id is only known once the user logs in. It applies to every event sent from that point on,
    including events already buffered but not yet delivered. Passing `null` or a blank string clears
    the id, which matters on logout — previously a stale id stayed on the device and tagged the next
    user's events. Safe to call from any thread, before or after `configure()`; the last write wins, so
    a non-blank `customerUserId` passed to a later `configure()` takes precedence over a call made
    before it. `configure()` only ever sets an id, never clears one, so passing it `null` leaves
    whatever `setCustomerUserId()` established in place. Matches the iOS SDK's `setCustomerUserId(_:)`
    in both name and null-clears behavior.

  **Fixed**

  * A `setCustomerUserId(...)` call made immediately after `configure()` is no longer overwritten by
    the value passed to `configure()`.
  * A repeat `configure()` call now logs a warning instead of silently discarding the
    `customerUserId` passed to it. A second `configure()` has always been a no-op; it now points at
    `setCustomerUserId()`.
</Update>

<Update label="1.6.0" description="2026-08-03" tags={["Added","Changed","Fixed"]}>
  **Added**

  * Attribution matching now sends additional permissionless device context to improve match accuracy:
    network availability, carrier and SIM metadata, memory and storage capacity, CPU core count, device
    uptime and the preferred-language list. Raw IP addresses and persistent telephony identifiers are
    never collected, no new runtime permission is required, and any signal that is unavailable is
    simply omitted. The full list is documented under **Data Privacy** in the README.
  * Play installs are now matched deterministically where possible: the install referrer is fetched
    before the attribution match request and sent along with it, instead of falling back to
    probabilistic matching.
  * A failed Play Store install referrer fetch is retried up to three times per launch. The install
    event is sent only once ever, so a single transient referrer-service failure on first launch could
    previously cost that install its deterministic attribution permanently.

  **Changed**

  * `sendEvent(EventType.INSTALL)` is now ignored, since the SDK already tracks installs
    automatically. Sending it by hand previously double-counted installs; such calls are now logged at
    debug level and discarded. Automatic install events are unaffected.

  **Fixed**

  * An app disabled through remote config now makes no attribution network calls at all. Previously
    only the event uploads were suppressed and the attribution match request still fired on fresh
    installs.
</Update>

<Update label="1.5.0" description="2026-07-17" tags={["Added","Changed","Deprecated","Fixed","Removed"]}>
  **Added**

  * Events sent before the SDK finishes initializing are buffered and delivered in order once it is
    ready, instead of being dropped.
  * A missing `INTERNET` permission in the consuming app is now reported explicitly through
    `InitListener.onError()` and `getLastInitError()`.

  **Changed**

  * The supported API surface is now explicit: `AppstackAttributionSdk`, `EventType`, `LogLevel`,
    `InitListener`, `HttpException` and `AuthenticationException`. Implementation classes moved to
    `com.appstack.attribution.internal.*` and are no longer visible to consumers. Code that referenced
    those implementation details directly has to move to the supported API.
  * `configure()` now takes `context`, `apiKey`, `logLevel`, `listener` and `customerUserId`.
    Deprecated overloads keep older call shapes compiling.

  **Deprecated**

  * `isDebug` and `endpointBaseUrl` on `configure()` are deprecated and now ignored. Use
    `logLevel = LogLevel.DEBUG` for on-device diagnostics (logcat tag `AppstackSdk`). The deprecated
    overloads will be removed in the next major version.

  **Fixed**

  * Events could go undelivered from minified release builds on 1.4.0 and 1.4.1: the ProGuard rules
    shipped with those versions named classes the SDK no longer had, so R8 stripped what the payloads
    needed and delivery failed silently. The rules now match the classes actually shipped. If you
    minify your release builds and are on 1.4.x, upgrade.

  **Removed**

  * `showDebugOverlay()` and the debug overlay it presented are gone. The overlay only repeated what
    `logLevel` logging already shows. The `is_debug` field is no longer sent with events.
  * WorkManager is no longer pulled into your app. The SDK dropped its periodic background refresh job
    and now declares `androidx.work` as a compile-only dependency, so consumers no longer inherit
    WorkManager, Room and SQLite transitively. Apps upgrading from an older version have the legacy job
    cancelled once, on a best-effort basis; apps that never shipped WorkManager are unaffected.
</Update>
