> ## 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.

# Testing

> Test your AppDNA integration in sandbox mode

# Testing

AppDNA provides a fully isolated sandbox environment for testing your SDK integration before going to production. Sandbox and production environments are completely separate -- different API endpoints, different API keys, different data stores.

***

## Sandbox vs Production

|                  | Sandbox                       | Production                      |
| ---------------- | ----------------------------- | ------------------------------- |
| **API endpoint** | `https://api.appdna.ai`       | `https://api.appdna.ai`         |
| **Key prefix**   | `adn_test_`                   | `adn_live_`                     |
| **Data**         | Isolated, periodically purged | Permanent, production analytics |
| **Webhooks**     | Fully functional, isolated    | Fully functional                |
| **Experiments**  | Independent from production   | Independent from sandbox        |
| **Rate limits**  | Same as production            | Standard limits                 |

Both environments share the same host, `https://api.appdna.ai`. There is no separate sandbox host — the backend routes a request to the sandbox or production environment based on the API-key prefix (`adn_test_` vs `adn_live_`).

<Warning>
  Never ship an app to the App Store or Play Store with a sandbox API key. Sandbox data is periodically purged and is not included in production analytics or reporting.
</Warning>

***

## Setup

<Steps>
  <Step title="Create a sandbox API key">
    Go to **Console > Settings > SDK > API Keys** and click **Create Key**. Select the **Sandbox** environment. The generated key will have the `adn_test_` prefix.
  </Step>

  <Step title="Configure the SDK with the sandbox key">
    Pass the sandbox key to `AppDNA.configure()`. The SDK sends all requests to `https://api.appdna.ai`; the backend routes them to the sandbox environment based on the `adn_test_` key prefix.
  </Step>

  <Step title="Verify events in the Event Debugger">
    Open **Console > Events > Debugger**, select your app and the **Sandbox** environment, and confirm events are arriving.
  </Step>
</Steps>

***

## SDK Configuration for Sandbox

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    import AppDNASDK

    AppDNA.configure(
        apiKey: "adn_test_xxx",
        environment: .sandbox,
        options: AppDNAOptions(logLevel: .debug)
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    import ai.appdna.sdk.AppDNA
    import ai.appdna.sdk.Environment
    import ai.appdna.sdk.AppDNAOptions
    import ai.appdna.sdk.LogLevel

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

  <Tab title="Flutter">
    ```dart theme={null}
    import 'package:appdna_sdk/appdna_sdk.dart';

    // Flutter's AppDNAEnvironment has no `sandbox` value — it is `production` or
    // `staging`. Sandbox is selected by the `adn_test_` key prefix, not the enum.
    await AppDNA.configure(
      apiKey: 'adn_test_xxx',
      env: AppDNAEnvironment.production,
      options: AppDNAOptions(logLevel: AppDNALogLevel.debug),
    );
    ```
  </Tab>

  <Tab title="React Native">
    ```javascript theme={null}
    import { AppDNA } from '@appdna-ai/react-native-sdk';

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

<Info>
  Setting `logLevel` to `debug` during testing enables verbose SDK console output. You will see every event being queued, every config fetch, and every experiment assignment logged to the console.
</Info>

***

## Event Debugger

The Event Debugger is a real-time event viewer in the AppDNA Console that lets you verify your SDK integration is working correctly.

### Using the Event Debugger

1. Navigate to **Console > Events > Debugger**.
2. Select your app and the **Sandbox** environment.
3. Trigger actions in your app (launch, identify, track events).
4. Events appear in the debugger within seconds, showing the full payload including event name, properties, user ID, device info, and timestamps.

The Event Debugger is particularly useful for verifying:

* Events are arriving with the correct names and properties
* User identification is linking events to the correct user ID
* Automatic events (session start, app open, etc.) are being tracked
* Custom event properties have the expected types and values

<Note>
  The Event Debugger shows events in real-time with a latency of approximately 1-2 seconds. If events are not appearing, check that your SDK is configured with a sandbox key and that the correct environment is selected in the debugger filter.
</Note>

***

## Webhook Testing

Sandbox webhooks are fully functional and completely isolated from production. This means you can test your webhook endpoint implementation without affecting production data or triggering production workflows.

<Steps>
  <Step title="Create a sandbox webhook endpoint">
    In **Console > Settings > Webhooks**, create a new endpoint. Ensure you are in the **Sandbox** environment (toggle at the top of the page).
  </Step>

  <Step title="Subscribe to event types">
    Select the event types you want to test (e.g., `payment.completed`, `onboarding.completed`).
  </Step>

  <Step title="Trigger events from your test app">
    Use the SDK configured with a sandbox key to trigger the events. The webhook payloads will be delivered to your endpoint.
  </Step>

  <Step title="Inspect delivery logs">
    View delivery status, response codes, and payload contents in **Console > Settings > Webhooks > \[Your Endpoint] > Deliveries**.
  </Step>
</Steps>

<Info>
  During local development, use a tunneling tool like [ngrok](https://ngrok.com) to expose your local server to the internet. Point your sandbox webhook endpoint to the ngrok URL.
</Info>

***

## Experiment Testing

Sandbox experiments run independently from production experiments. You can create, run, and analyze experiments in sandbox without any impact on production users or data.

### Tips for testing experiments

* **Use deterministic user IDs.** Since experiment assignment is a deterministic hash of the user and experiment identifiers, using consistent test user IDs ensures you always land in the same variant.
* **Test both variants.** Create multiple test users and verify that each variant renders correctly. You can use the dashboard to preview which variant a given user ID will be assigned to.
* **Verify exposure tracking.** Check the Event Debugger to confirm that `experiment_exposure` events are being tracked when `getVariant()` is called.

***

## Pre-Launch Checklist

Before switching from sandbox to production, verify each item:

<Steps>
  <Step title="Events appearing in Event Debugger">
    Open the Event Debugger and confirm that all expected events (both automatic and custom) are arriving with correct names, properties, and user associations.
  </Step>

  <Step title="User identification working">
    Call `identify()` with a test user ID and verify in the Event Debugger that subsequent events are attributed to that user. Confirm that traits are being set correctly.
  </Step>

  <Step title="Onboarding flows rendering correctly">
    Trigger your onboarding flows and verify that all steps display correctly, navigation works, and completion events are tracked.
  </Step>

  <Step title="Paywall presentations triggering">
    Present your paywalls and verify the layout, pricing, and CTA buttons render correctly. Confirm that impression events (`paywall_view`) appear in the Event Debugger.
  </Step>

  <Step title="Push notification tokens registered">
    Request push permission and verify in the dashboard that the device token appears under the test user. Send a test push notification and confirm delivery.
  </Step>

  <Step title="Switch to production API key">
    Replace your `adn_test_` key with the corresponding `adn_live_` production key. Update the environment parameter to `.production` / `Environment.PRODUCTION` / `'production'`.
  </Step>
</Steps>

<Warning>
  Do not skip the checklist. Issues that are easy to catch in sandbox (wrong event names, missing properties, broken flows) become much harder to diagnose in production.
</Warning>

***

## Common Testing Scenarios

### Testing offline behavior

1. Configure the SDK with a sandbox key and let it fetch the config successfully.
2. Enable airplane mode on the device.
3. Trigger actions in your app and verify that:
   * Onboarding flows still render (from cache).
   * Paywalls still render (from cache).
   * Experiment variants still resolve (from cache).
   * Events are queued without errors.
4. Disable airplane mode and verify that queued events flush to the server (visible in Event Debugger).

### Testing config bundle fallback

1. Embed an `appdna-config.json` bundle in your app (see [Config Bundles in CI/CD](/guides/config-bundle-cicd)).
2. Install the app on a device with no internet connection.
3. Launch the app and verify that onboarding flows, paywalls, and experiments work from the bundled config.

### Testing webhook signature verification

1. Create a sandbox webhook endpoint pointed at your server.
2. Trigger an event and capture the raw request.
3. Verify the `x-appdna-signature` header matches the expected HMAC-SHA256 of the request body using your signing secret.
4. Test with an invalid signature to confirm your server rejects it with a 401.

<Note>
  The sandbox environment has the same rate limits as production. If you are running automated tests that generate high event volumes, be mindful of the limits to avoid throttling.
</Note>
