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

# Migrating from 0.x

> Upgrade guide from AppDNA SDK 0.x to 1.0

# Migrating from 0.x to 1.0

Version 1.0 is a major rewrite of the AppDNA SDK with breaking changes across all platforms. This guide walks you through every change you need to make to upgrade from 0.x.

***

## Overview of Changes

| Area                | 0.x                      | 1.0                                            |
| ------------------- | ------------------------ | ---------------------------------------------- |
| Initialization      | `AppDNA.initialize()`    | `AppDNA.configure(apiKey:options:)`            |
| Method organization | Flat methods on `AppDNA` | Namespaced modules (e.g., `AppDNA.onboarding`) |
| Delegates           | Single global delegate   | Per-module delegates                           |
| Offline support     | Network-dependent        | Offline-first with config bundles              |
| API key format      | `appdna_` prefix         | `adn_live_` / `adn_test_` prefixes             |
| Identity            | `setUserId()`            | `identify(userId:traits:)`                     |
| Events              | `logEvent()`             | `track(name:properties:)`                      |

***

## 1. Initialization

The `initialize()` method has been replaced with `configure()`, which now requires an explicit API key parameter and accepts an options object.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    // 0.x
    AppDNA.initialize(config: AppDNAConfig(
        projectId: "proj-123"
    ))

    // 1.0
    AppDNA.configure(
        apiKey: "adn_live_xxx",
        environment: .production,
        options: AppDNAOptions(logLevel: .debug)
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    // 0.x
    AppDNA.initialize(this, AppDNAConfig(
        projectId = "proj-123"
    ))

    // 1.0
    AppDNA.configure(
        context = this,
        apiKey = "adn_live_xxx",
        environment = Environment.PRODUCTION,
        options = AppDNAOptions(logLevel = LogLevel.DEBUG)
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    // 0.x
    await AppDNA.initialize(config: AppDNAConfig(
      projectId: 'proj-123',
    ));

    // 1.0
    await AppDNA.configure(
      apiKey: 'adn_live_xxx',
      env: AppDNAEnvironment.production,
      options: AppDNAOptions(logLevel: AppDNALogLevel.debug),
    );
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    // 0.x
    await AppDNA.initialize({
      projectId: 'proj-123',
    });

    // 1.0
    await AppDNA.configure('adn_live_xxx', 'production', {
      logLevel: 'debug',
    });
    ```
  </Tab>
</Tabs>

<Info>
  The `projectId` is no longer needed. The API key encodes both the organization and app identifiers.
</Info>

***

## 2. Module Namespaces

In 0.x, all methods lived directly on the `AppDNA` singleton. In 1.0, methods are organized into module namespaces:

| 0.x Method                       | 1.0 Equivalent                    |
| -------------------------------- | --------------------------------- |
| `AppDNA.presentOnboarding()`     | `AppDNA.onboarding.present()`     |
| `AppDNA.showPaywall()`           | `AppDNA.paywall.present()`        |
| `AppDNA.getProducts()`           | `AppDNA.billing.getProducts()`    |
| `AppDNA.purchaseProduct()`       | `AppDNA.billing.purchase()`       |
| `AppDNA.requestPushPermission()` | `AppDNA.push.requestPermission()` |
| `AppDNA.getExperimentVariant()`  | `AppDNA.experiments.getVariant()` |
| `AppDNA.getRemoteConfig()`       | `AppDNA.remoteConfig.get()`       |
| `AppDNA.isFeatureEnabled()`      | `AppDNA.features.isEnabled()`     |
| `AppDNA.showSurvey()`            | `AppDNA.surveys.present()`        |

<Note>
  Onboarding step tracking is fully automatic in 1.0 — there is no `trackStep` method. The SDK emits step events (`onboarding_flow_started`, `step_viewed`, `step_completed`, …) for you.
</Note>

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    // 0.x
    AppDNA.showPaywall("premium")
    let variant = AppDNA.getExperimentVariant("test-1")

    // 1.0
    AppDNA.paywall.present("premium")
    let variant = AppDNA.experiments.getVariant("test-1")
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    // 0.x
    AppDNA.showPaywall("premium")
    val variant = AppDNA.getExperimentVariant("test-1")

    // 1.0
    AppDNA.paywall.present("premium")
    val variant = AppDNA.experiments.getVariant("test-1")
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    // 0.x
    AppDNA.showPaywall("premium");
    final variant = AppDNA.getExperimentVariant("test-1");

    // 1.0
    AppDNA.paywall.present("premium");
    final variant = AppDNA.experiments.getVariant("test-1");
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    // 0.x
    AppDNA.showPaywall("premium");
    const variant = AppDNA.getExperimentVariant("test-1");

    // 1.0
    AppDNA.paywall.present("premium");
    const variant = AppDNA.experiments.getVariant("test-1");
    ```
  </Tab>
</Tabs>

***

## 3. Delegates

In 0.x, there was a single `AppDNADelegate` protocol/interface that handled callbacks for all modules. In 1.0, each module has its own delegate:

| 0.x              | 1.0                          |
| ---------------- | ---------------------------- |
| `AppDNADelegate` | `AppDNAOnboardingDelegate`   |
|                  | `AppDNAPaywallDelegate`      |
|                  | `AppDNABillingDelegate`      |
|                  | `AppDNAPushDelegate`         |
|                  | `AppDNASurveyDelegate`       |
|                  | `AppDNAInAppMessageDelegate` |

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    // 0.x — single delegate
    class AppController: AppDNADelegate {
        func onboardingCompleted(flowId: String) { ... }
        func paywallDismissed(paywallId: String) { ... }
        func pushReceived(notification: AppDNANotification) { ... }
    }
    AppDNA.delegate = AppController()

    // 1.0 — per-module delegates
    class OnboardingHandler: AppDNAOnboardingDelegate {
        func onOnboardingCompleted(flowId: String, responses: [String: Any]) { ... }
    }

    class PaywallHandler: AppDNAPaywallDelegate {
        func onPaywallDismissed(paywallId: String) { ... }
    }

    AppDNA.onboarding.setDelegate(OnboardingHandler())
    AppDNA.paywall.setDelegate(PaywallHandler())
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    // 0.x — single delegate
    AppDNA.delegate = object : AppDNADelegate {
        override fun onOnboardingCompleted(flowId: String) { ... }
        override fun onPaywallDismissed(paywallId: String) { ... }
    }

    // 1.0 — per-module delegates
    AppDNA.onboarding.setDelegate(object : AppDNAOnboardingDelegate {
        override fun onOnboardingCompleted(flowId: String, responses: Map<String, Any>) { ... }
    })

    AppDNA.paywall.setDelegate(object : AppDNAPaywallDelegate {
        override fun onPaywallDismissed(paywallId: String) { ... }
    })
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    // 0.x — single delegate
    AppDNA.delegate = MyAppDNADelegate();

    // 1.0 — per-module delegates
    AppDNA.onboarding.setDelegate(MyOnboardingDelegate());
    AppDNA.paywall.setDelegate(MyPaywallDelegate());
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    // 0.x — single listener
    AppDNA.addListener('onboardingCompleted', handler);
    AppDNA.addListener('paywallDismissed', handler);

    // 1.0 — per-module delegates registered with setDelegate
    AppDNA.onboarding.setDelegate(myOnboardingDelegate);
    AppDNA.paywall.setDelegate(myPaywallDelegate);
    ```
  </Tab>
</Tabs>

***

## 4. Config Bundles (New in 1.0)

Version 1.0 introduces config bundle embedding, a key part of the offline-first architecture. You can now embed a JSON config file in your app binary during CI/CD so the SDK has a complete configuration available on first launch without any network request.

This is a new feature with no 0.x equivalent. See the [Config Bundles in CI/CD](/guides/config-bundle-cicd) guide for setup instructions.

***

## 5. API Key Format

API keys have changed format to clearly distinguish environments:

| Environment    | 0.x Format      | 1.0 Format     |
| -------------- | --------------- | -------------- |
| Production     | `appdna_pk_xxx` | `adn_live_xxx` |
| Sandbox / Test | `appdna_sk_xxx` | `adn_test_xxx` |

<Warning>
  Old `appdna_` prefixed keys are not compatible with 1.0 SDKs. Generate new API keys in **Console > Settings > SDK > API Keys**.
</Warning>

***

## 6. Identity

The `setUserId()` method has been replaced with `identify()`, which now accepts user traits for segmentation and targeting:

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    // 0.x
    AppDNA.setUserId("user-123")

    // 1.0
    AppDNA.identify(
        userId: "user-123",
        traits: [
            "plan": "premium",
            "signup_date": "2025-01-15"
        ]
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    // 0.x
    AppDNA.setUserId("user-123")

    // 1.0
    AppDNA.identify(
        userId = "user-123",
        traits = mapOf(
            "plan" to "premium",
            "signup_date" to "2025-01-15"
        )
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    // 0.x
    AppDNA.setUserId('user-123');

    // 1.0
    await AppDNA.identify('user-123', traits: {
      'plan': 'premium',
      'signup_date': '2025-01-15',
    });
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    // 0.x
    AppDNA.setUserId('user-123');

    // 1.0
    await AppDNA.identify('user-123', {
      plan: 'premium',
      signup_date: '2025-01-15',
    });
    ```
  </Tab>
</Tabs>

<Note>
  Traits are merged with previously set traits on each call. You only need to pass traits that have changed, not the full set every time.
</Note>

***

## 7. Events

The `logEvent()` method has been replaced with `track()`, which accepts structured properties:

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    // 0.x
    AppDNA.logEvent("purchase", metadata: ["price": "9.99"])

    // 1.0
    AppDNA.track(
        event: "purchase_completed",
        properties: ["price": 9.99, "currency": "USD"]
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    // 0.x
    AppDNA.logEvent("purchase", metadata = mapOf("price" to "9.99"))

    // 1.0
    AppDNA.track(
        event = "purchase_completed",
        properties = mapOf("price" to 9.99, "currency" to "USD")
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    // 0.x
    AppDNA.logEvent('purchase', metadata: {'price': '9.99'});

    // 1.0
    await AppDNA.track('purchase_completed', properties: {
      'price': 9.99,
      'currency': 'USD',
    });
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    // 0.x
    AppDNA.logEvent('purchase', { price: '9.99' });

    // 1.0
    await AppDNA.track('purchase_completed', {
      price: 9.99,
      currency: 'USD',
    });
    ```
  </Tab>
</Tabs>

<Info>
  In 1.0, event properties support typed values (numbers, booleans, strings, arrays) rather than being limited to string-only metadata. This enables richer analytics and segmentation in the dashboard.
</Info>

***

## Platform-Specific Migration Notes

### iOS

* **Minimum deployment target** raised from iOS 13 to iOS 16.
* **Swift version** requirement is now Swift 5.9+.
* **SPM package name** changed from `AppDNA` to `AppDNASDK`. Update your import statements: `import AppDNASDK`.
* **Concurrency**: Several async methods now use Swift concurrency (`async/await`) instead of completion handlers.

### Android

* **Minimum SDK** raised from API 21 to API 24 (Android 7.0).
* **Kotlin version** requirement is now 1.9+.
* **Artifact coordinates** changed from `ai.appdna:core` to `ai.appdna:sdk-android`.
* **Coroutines**: Suspend functions are now used instead of callback-based APIs.

### Flutter

* **Dart version** requirement is now Dart 3.0+.
* **Flutter version** requirement is now Flutter 3.10+.
* **Package name** changed from `appdna` to `appdna_sdk`. Update your `pubspec.yaml` and import statements.

### React Native

* **React Native version** requirement is now >=0.76.9 (New Architecture required).
* **Package name** changed from `react-native-appdna` to `@appdna-ai/react-native-sdk`. Update your `package.json` and import statements.
* **New Architecture**: Full support for the React Native New Architecture (TurboModules/Fabric).

***

## Deprecation Timeline

| Date              | Milestone                                                                   |
| ----------------- | --------------------------------------------------------------------------- |
| 1.0 GA            | 0.x SDKs enter maintenance mode. No new features.                           |
| 1.0 GA + 3 months | 0.x SDKs receive critical bug fixes only.                                   |
| 1.0 GA + 6 months | 0.x SDKs reach end-of-life. No further updates, including security patches. |

<Warning>
  We strongly recommend migrating to 1.0 as soon as possible. After the 6-month deprecation window, 0.x SDKs will no longer receive security patches and may stop functioning if server-side API changes are made.
</Warning>
