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

# Config Bundles in CI/CD

> Embed server configuration into your app build

# Config Bundles in CI/CD

A config bundle is a versioned JSON snapshot that contains everything the SDK needs to run without a network connection: onboarding flows, paywalls, in-app messages, feature flags, experiment definitions, and remote config values.

By embedding a config bundle in your app binary during CI/CD, you guarantee a fully configured experience on first launch -- even if the user has no internet connection.

***

## What is a Config Bundle?

The config bundle is a single JSON file generated server-side whenever you publish changes in the dashboard. It contains:

| Section            | Description                                                  |
| ------------------ | ------------------------------------------------------------ |
| `onboarding_flows` | Step-by-step onboarding sequences with UI configuration      |
| `paywalls`         | Paywall layouts, pricing plans, and CTA configuration        |
| `in_app_messages`  | Triggered messages with audience targeting and display rules |
| `feature_flags`    | Boolean feature flag definitions with targeting rules        |
| `remote_config`    | Key-value configuration pairs                                |
| `experiments`      | Experiment definitions with variant allocations              |

Each bundle includes a `bundle_version` number that increments on every generation, along with metadata like `generated_at` and `sdk_min_version`.

***

## API Endpoints

### Download Current Bundle

```
GET /api/v1/sdk/config-bundle
```

**Authentication:** SDK API key via `x-api-key` header.

Returns the full config bundle including all content. This is the endpoint you call in your CI/CD pipeline.

```bash theme={null}
curl -s https://api.appdna.ai/api/v1/sdk/config-bundle \
  -H "x-api-key: $APPDNA_SDK_KEY" \
  -o appdna-config.json
```

**Response:**

```json theme={null}
{
  "bundle_version": 42,
  "sdk_min_version": "1.0.0",
  "size_bytes": 15234,
  "generated_at": "2026-02-19T10:00:00Z",
  "content": {
    "onboarding_flows": { ... },
    "paywalls": { ... },
    "remote_config": { ... },
    "feature_flags": { ... },
    "in_app_messages": { ... },
    "experiments": { ... }
  }
}
```

### Check Bundle Version

```
GET /api/v1/sdk/config-bundle/version
```

**Authentication:** SDK API key via `x-api-key` header.

Lightweight version check that returns metadata without the full content payload. Useful for polling or conditional downloads in CI.

```bash theme={null}
curl -s https://api.appdna.ai/api/v1/sdk/config-bundle/version \
  -H "x-api-key: $APPDNA_SDK_KEY"
```

**Response:**

```json theme={null}
{
  "bundle_version": 42,
  "sdk_min_version": "1.0.0",
  "generated_at": "2026-02-19T10:00:00Z"
}
```

<Info>
  This endpoint returns only metadata (no `content` field), making it ideal for checking whether you need to download a new bundle before every build.
</Info>

### Force Regenerate Bundle

```
POST /api/v1/sdk/config-bundle/generate
```

**Authentication:** Firebase session token via `Authorization: Bearer` header, plus `x-tenant-id` / `x-app-id`.

Forces the server to regenerate the config bundle from the current published state of all modules. Returns the newly generated bundle.

<Note>
  The platform automatically regenerates the bundle whenever you publish changes in the dashboard. Manual regeneration is rarely needed but can be useful in CI/CD pipelines that need to ensure the bundle reflects the very latest state.
</Note>

### Bundle Version History

```
GET /api/v1/sdk/config-bundle/history
```

**Authentication:** Firebase session token via `Authorization: Bearer` header, plus `x-tenant-id` / `x-app-id`.

Returns a paginated list of previous bundle versions with metadata. Useful for auditing or rollback workflows.

| Parameter | Type     | Default | Description                            |
| --------- | -------- | ------- | -------------------------------------- |
| `limit`   | `number` | 20      | Number of versions to return (max 100) |
| `offset`  | `number` | 0       | Pagination offset                      |

***

## CI/CD Integration

Adding a config bundle download step to your build pipeline takes three steps:

<Steps>
  <Step title="Add a build step that downloads the bundle">
    Call `GET /api/v1/sdk/config-bundle` with your SDK API key and save the response to a JSON file.
  </Step>

  <Step title="Save the file to the platform-specific assets directory">
    Each platform expects the file in a specific location (see platform-specific examples below).
  </Step>

  <Step title="Build your app as normal">
    The SDK automatically detects the bundled config file and uses it as the last-resort fallback when no remote or cached config is available.
  </Step>
</Steps>

***

## Build Script Examples

<Tabs>
  <Tab title="Fastlane (iOS)">
    Add a lane or a pre-build action to your `Fastfile`:

    ```ruby theme={null}
    desc "Download AppDNA config bundle"
    lane :download_appdna_config do
      sh(
        "curl -s " \
        "-H 'x-api-key: #{ENV['APPDNA_SDK_KEY']}' " \
        "https://api.appdna.ai/api/v1/sdk/config-bundle " \
        "-o ../Resources/appdna-config.json"
      )
      UI.success("AppDNA config bundle downloaded")
    end

    desc "Build the app"
    lane :build do
      download_appdna_config
      build_app(scheme: "MyApp")
    end
    ```

    Make sure `Resources/appdna-config.json` is added to your Xcode project under **Build Phases > Copy Bundle Resources**.
  </Tab>

  <Tab title="Gradle (Android)">
    Add a custom task to your `app/build.gradle`:

    ```groovy theme={null}
    task downloadAppDNAConfig(type: Exec) {
        description = "Download AppDNA config bundle for offline fallback"
        commandLine 'curl', '-s',
            '-H', "x-api-key: ${System.env.APPDNA_SDK_KEY}",
            'https://api.appdna.ai/api/v1/sdk/config-bundle',
            '-o', 'src/main/assets/appdna-config.json'
    }

    preBuild.dependsOn downloadAppDNAConfig
    ```

    This runs automatically before every build. The file is placed in `src/main/assets/` where the SDK expects it.
  </Tab>

  <Tab title="Flutter">
    Add a shell script to your CI pipeline (or run it as a pre-build step):

    ```bash theme={null}
    #!/bin/bash
    # download-config.sh
    set -e

    echo "Downloading AppDNA config bundle..."
    curl -sf \
      -H "x-api-key: ${APPDNA_SDK_KEY}" \
      https://api.appdna.ai/api/v1/sdk/config-bundle \
      -o assets/appdna-config.json

    echo "Bundle downloaded: assets/appdna-config.json"
    ```

    Ensure the file is declared in `pubspec.yaml`:

    ```yaml theme={null}
    flutter:
      assets:
        - assets/appdna-config.json
    ```
  </Tab>

  <Tab title="React Native">
    Add a prebuild script to `package.json`:

    ```json theme={null}
    {
      "scripts": {
        "appdna:config": "curl -sf -H \"x-api-key: $APPDNA_SDK_KEY\" https://api.appdna.ai/api/v1/sdk/config-bundle -o appdna-config.json && cp appdna-config.json android/app/src/main/assets/appdna-config.json",
        "prebuild": "npm run appdna:config"
      }
    }
    ```

    For iOS, add `appdna-config.json` to your Xcode project as a bundle resource.
  </Tab>
</Tabs>

***

## Version Checking

The SDK automatically compares the local bundled version with the remote version on startup:

1. On launch, the SDK reads `bundle_version` from the embedded config file.
2. It calls `GET /api/v1/sdk/config-bundle/version` to check the latest server version.
3. If the server version is newer, the SDK downloads the full bundle and caches it locally.
4. The bundled version is only used if both the remote fetch and cache miss fail.

The dashboard warns you if the most commonly reported bundle version across your devices is more than 5 versions behind the latest published bundle.

<Warning>
  If you see a staleness warning in the dashboard, it means your CI pipeline is not running frequently enough or the config download step is failing silently. Check your build logs and ensure the `APPDNA_SDK_KEY` environment variable is set.
</Warning>

***

## Best Practices

1. **Regenerate on every deploy.** Even if you have not changed any configuration, regenerating ensures the bundle version stays current and the staleness warning stays green.

2. **Use the `x-api-key` header, not Bearer tokens.** The config bundle download endpoint accepts SDK API keys, which are scoped to your app and safe to use in CI environments.

3. **Fail the build if the download fails.** Use `curl -sf` (silent + fail on error) or equivalent so your build breaks visibly if the download fails, rather than shipping an outdated or missing bundle.

4. **Store the API key as a CI secret.** Never hardcode `APPDNA_SDK_KEY` in your build scripts. Use your CI provider's secret management (GitHub Actions secrets, Bitrise secrets, etc.).

5. **Check the file size.** A valid config bundle is always at least a few hundred bytes. If the downloaded file is 0 bytes or suspiciously small, the download likely failed silently.
