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

# Boxo SDK

<Tabs>
  <Tab title="iOS SDK">
    ## iOS SDK

    <AccordionGroup>
      <Accordion title="Compatibility">
        Your project must target iOS 10 or later. Swift projects should use Swift 4.2 or later, and CocoaPods 1.8.1 or later is required.
      </Accordion>

      <Accordion title="Installation">
        <Tabs>
          <Tab title="Swift Package Manager installation">
            Add a package by selecting File → Add Packages… in Xcode's menu bar.

            Search for the BoxoSDK using the repo's URL:

            ```sh theme={"system"}
            https://github.com/Appboxo/boxo-ios-spm.git
            ```

            Next, set the **Dependency Rule** to be Up to Next Major Version.

            Then, select **Add Package**.
          </Tab>

          <Tab title="CocoaPods installation">
            Using [CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started) to create a Podfile if you don't already have one.

            ```sh theme={"system"}
            cd your-project-directory
            pod init
            ```

            Add the Boxo pod to your Podfile

            ```sh theme={"system"}
            pod 'BoxoSDK'
            ```

            Install the pods, then open your .xcworkspace file to see the project in Xcode:

            ```sh theme={"system"}
            pod install
            open your-project.xcworkspace
            ```
          </Tab>
        </Tabs>
      </Accordion>

      <Accordion title="Launch miniapp">
        Import Boxo SDK in your ViewController:

        ```swift theme={"system"}
        import BoxoSDK 
        ```

        Initialize Boxo in your app by configuring a Boxo shared instance. Remember to replace `client_id` field with your `client_id`.

        ```swift theme={"system"}
        let config = Config(clientId: "client_id")
        Boxo.shared.setConfig(config: config)
        ```

        To launch the miniapp, you will need a UIViewController:

        #### UIKit

        To open miniapp write this code in your UIViewController:

        ```swift theme={"system"}
        let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
        miniapp.open(viewController: self)
        ```

        #### SwiftUI

        If you are using SwiftUI, you need to access the current UIViewController. There are many ways to obtain a UIViewController. Here is one of them:

        ```swift theme={"system"}
        struct ViewControllerFinder: UIViewControllerRepresentable {
            var onViewControllerFound: (UIViewController) -> Void

            func makeUIViewController(context: Context) -> UIViewController {
                let viewController = UIViewController()
                DispatchQueue.main.async {
                    self.onViewControllerFound(viewController)
                }
                return viewController
            }

            func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
        }
        ...
        struct ContentView: View {
            @State private var currentViewController: UIViewController?
            
            var body: some View {
                ViewControllerFinder { viewController in
                    currentViewController = viewController
                }
                Button(action: {
                    guard let currentViewController = currentViewController else { return }

                    let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
                    miniapp.open(viewController: currentViewController)
                }) {
                    Text("Open miniapp")
                }
            }
        }
        ```
      </Accordion>

      <Accordion title="SDK Configurations">
        Configure BoxoSDK with these settings to customize behavior, language, and UI elements.

        #### Language Configuration

        Use it to provide language to miniapp.  Default: 'en'

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.language = "en"
        Boxo.shared.setConfig(config: config)
        ```

        #### Consent Management

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.setUserId(id: "HOST_APP_USER_ID") //will be used for the consent screen
        Boxo.shared.setConfig(config: config)
        ```

        #### Miniapp Menu Customization

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.permissionsPage = false    // Hide "Settings"
        config.showClearCache = false   // Hide "Clear Cache"
        config.showAboutPage = false    // Show "About"
        Boxo.shared.setConfig(config: config)
        ```

        | **Parameter**     | **Description**         | **Default** |
        | :---------------- | :---------------------- | :---------- |
        | `permissionsPage` | Setting menu item       | `true`      |
        | `showClearCache`  | Clear Cache menu item   | `true`      |
        | `showAboutPage`   | About Miniapp menu item | `true`      |

        #### Sandbox Mode Configuration

        Control which miniapps are available in your development environment using the sandbox mode flag:

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.sandboxMode = true
        Boxo.shared.setConfig(config: config)
        ```

        Behavior: [Retrieve Miniapp List](/host-apps/BoxoSDK#retrieve-miniapp-list) will return miniapps with the statuses listed below.

        | **Sandbox Mode** | **Available Miniapp**  **Statuses** | **Use Case**                                                  |
        | :--------------- | :---------------------------------- | :------------------------------------------------------------ |
        | `true`           | `Approved` + `InTesting`            | Development environment - access to miniapps still in testing |
        | `false`          | `Approved` only                     | Production environment - only fully approved miniapps         |

        #### Theme Configuration

        Configure native component theming to match your app's design system or respect user preferences. The SDK provides comprehensive theme support for:

        * Splash screens
        * Native UI components
        * System dialogs and alerts

        **Theme Options**:

        | **Option** | **Description**                    |
        | :--------- | :--------------------------------- |
        | `SYSTEM`   | Automatically matches device theme |
        | `LIGHT`    | Forces light theme                 |
        | `DARK`     | Forces dark theme                  |

        Control theme behavior at both global and per-miniapp levels for maximum flexibility.

        **Global Theme (Affects all miniapps)**

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.theme = .System
        Boxo.shared.setConfig(config: config)
        ```

        **Per-Miniapp Theme Override**

        ```swift theme={"system"}
        // Override theme for specific miniapp
        miniapp.setConfig(config: MiniappConfig(theme: .Dark))
        ```
      </Accordion>

      <Accordion title="Miniapp Auth Flow">
        Handle authentication between your host app and miniapps:

        ```swift theme={"system"}
        miniapp.delegate = self
        ...
        extension ViewController : MiniappDelegate {
          func onAuth(miniapp: Miniapp) {
            // 1. Fetch auth code from your backend
            val authCode = fetchAuthCodeFromBackend()

            // 2. Provide code to Miniapp
            miniapp.setAuthCode(authCode: authCode)
          }
        }
        ```
      </Accordion>

      <Accordion title="User Logout & Data Clearing">
        When users log out of your host app, you must completely clear all miniapp session data

        ```swift theme={"system"}
        Boxo.shared.logout()
        ```
      </Accordion>

      <Accordion title="Miniapp URL Change Listener">
        To listen for any URL change events:

        ```swift theme={"system"}
        miniapp.delegate = self
        ...
        extension ViewController: MiniappDelegate {
            func didChangeUrlEvent(miniapp: Miniapp, url: URL) {
                // Listen for search URL
                if url.path.components(separatedBy: "/").contains("search") {
                    print("Search url: \(url)")
                }
            }
        }
        ```
      </Accordion>

      <Accordion title="Custom URL Parameters">
        Append additional query parameters to miniapp's initial URL for passing contextual data. This enables:

        * User-specific data injection
        * Campaign tracking
        * Contextual deep linking
        * A/B testing configuration

        ```swift theme={"system"}
        let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
        let miniappConfig = MiniappConfig()
        miniappConfig.setExtraParams(extraParams: ["user_id" : "u_12345", "campaign" : "summer_sale"])
        miniapp.setConfig(config: miniappConfig)
        ```

        Parameters will be automatically URL-encoded and appended as query parameters:

        ```
        https://miniapp.example.com?user_id=u_12345&campaign=summer_sale
        ```
      </Accordion>

      <Accordion title="Custom Event Handling">
        Establish two-way communication between your hostapp and miniapps using custom events. This system enables:

        * Real-time data exchange
        * User interaction tracking
        * Miniapp to host app callbacks
        * Dynamic content updates

        ```swift theme={"system"}
        miniapp.delegate = self
        ...
        func didReceiveCustomEvent(miniapp: Miniapp, customEvent: CustomEvent) {
            customEvent.payload = [
                "status" : "success",
                "code" : 200
            ]

            // Send response back to miniapp
            miniapp.sendCustomEvent(customEvent: customEvent)
        }
        ```
      </Accordion>

      <Accordion title="Adding Custom Action Menu">
        You can extend the miniapp’s native menu by adding your own custom action item by defining `.setCustomActionMenuItemImage`

        ```swift theme={"system"}
        let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
        let miniappConfig = MiniappConfig()
        miniappConfig.setCustomActionMenuItemImage(image: UIImage(named: "ic_custom_action_button"))
        miniapp.setConfig(config: miniappConfig)
        miniapp.delegate = self
        ...
        extension ViewController : MiniappDelegate {
            func didSelectCustomActionMenuItemEvent(miniapp: Miniapp) {
                // do something
            }
        }
        ```

        **Control Visibility:**

        ```
        // Hide the item
        miniapp.hideCustomActionMenuItem()

        // Show when needed
        miniapp.showCustomActionMenuItem()
        ```
      </Accordion>

      <Accordion title="Retrieve Miniapp List">
        Fetch the complete catalog of available miniapps with detailed metadata. This operation returns:

        * Basic miniapp information (id, name, description)
        * Logo
        * Category

        ```swift theme={"system"}
        Boxo.shared.getMiniapps { miniapps, error in
            miniapps.forEach { data in
                print(data.appId)
                print(data.name)
                print(data.longDescription)
                print(data.logo)
                print(data.category)
            }
        }
        ```
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background Colors

        Use the `splashBackgroundColors` property to configure splash background colors:

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.splashBackgroundColors = SplashBackgroundColors(light: UIColor.white, dark: UIColor.black)
        Boxo.shared.setConfig(config: config)
        ```

        ### Progress Bar Colors

        Use the `progressBarColors` property to configure progress bar colors:

        ```swift theme={"system"}
        let config = Config(clientId: "CLIENT_ID")
        config.progressBarColors = ProgressBarColors(lightIndicator: UIColor.red, lightTrack: UIColor.yellow, darkIndicator: UIColor.green, darkTrack: UIColor.orange)
        Boxo.shared.setConfig(config: config)
        ```

        ### Splash Behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        You can control this behavior using `MiniappConfig`. For example, to disable the splash screen entirely:

        ```swift theme={"system"}
        let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
                    
        let miniappConfig = MiniappConfig()
        miniappConfig.enableSplash(isSplashEnabled: false)
        miniapp.setConfig(config: miniappConfig)

        miniapp.open(viewController: self)
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects to enhance the user experience by setting the appropriate page transition animation when opening a miniapp.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP`- The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect. You can easily change the animation to any of the other available options based on the user experience you want to provide.

        ```swift theme={"system"}
        let config = MiniappConfig()
        config.pageAnimation = PageAnimation.RIGHT_TO_LEFT

        let miniapp = Boxo.shared.getMiniapp(appId: "app_id")
        miniapp.setConfig(config: config)
        miniapp.open(viewController: self)
        ```
      </Accordion>

      <Accordion title="Miniapp lifecycle events">
        Miniapp lifecycle events allow you to monitor key activities, such as `onLaunch`, `onResume`, `onPause`, `onClose`, `onError`, and `onUserInteraction`. These events help track the miniapp's behavior throughout its usage lifecycle.

        ```swift theme={"system"}
        miniapp.delegate = self
        ...
        extension ViewController: MiniappDelegate {
            func onLaunch(miniapp: Miniapp) {
                print("onLaunchMiniapp: \(miniapp.appId)")
            }

            func onResume(miniapp: Miniapp) {
                print("onResumeMiniapp: \(miniapp.appId)")
            }

            func onPause(miniapp: Miniapp) {
                print("onPauseMiniapp: \(miniapp.appId)")
            }

            func onClose(miniapp: Miniapp) {
                print("onCloseMiniapp: \(miniapp.appId)")
            }

            func onError(miniapp: Miniapp, message: String) {
                print("onErrorMiniapp: \(miniapp.appId) message: \(message)")
            }

            func onUserInteraction(miniapp: Miniapp) {
                print("onUserInteractionMiniapp: \(miniapp.appId)")
            }
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Android SDK">
    ## Android SDK

    Please see our [sample Android app](https://github.com/Appboxo/sample-android-hostapp) to learn more.

    <AccordionGroup>
      <Accordion title="Compatibility">
        Your project must target at least Android 5.0 (API level 21) or higher.

        The host Activity must extend `FragmentActivity` (for example, `AppCompatActivity`). A plain `Activity` without fragment support is not supported.
      </Accordion>

      <Accordion title="Installation">
        Latest version: ![Maven Central Version](https://img.shields.io/maven-central/v/io.boxo.sdk/boxo-android)

        To install Boxo SDK, add `io.boxo.sdk:boxo-android` to the `dependencies` block of your [app/build.gradle](https://developer.android.com/studio/build/dependencies) file:

        ```kotlin app/build.gradle.kts theme={"system"}
        ...
        dependencies {
        	implementation("io.boxo.sdk:boxo-android:1.x.x")
        }
        ```
      </Accordion>

      <Accordion title="Launch miniapp">
        1. Add to your existing `Application` class or create a new one if you don't have an `Application` class yet.

           ```kotlin MyApplication.kt theme={"system"}
           import android.app.Application
           import io.boxo.sdk.Boxo
           import io.boxo.sdk.Config

           class MyApplication : Application() {
               override fun onCreate() {
                   super.onCreate()
                   Boxo.init(this)
                       .setConfig(
                           Config.Builder()
                               .setClientId("client_id")
                               .build()
                       )
               }
           }
           ```
        2. Then register it in AndroidManifest.xml:

           ```AndroidManifest.xml theme={"system"}
           <application
           	android:name=".MyApplication"
           	...>
           ```
        3. Open miniapp

           ```kotlin theme={"system"}
           val miniapp = Boxo.getMiniapp(appId)
           miniapp.open()
           ```

        ```kotlin MainActivity.kt [expandable] theme={"system"}
        package io.boxo.launchminiapp

        import android.os.Bundle
        import androidx.fragment.app.FragmentActivity
        import androidx.activity.compose.setContent
        import androidx.activity.enableEdgeToEdge
        import androidx.compose.foundation.layout.Arrangement
        import androidx.compose.foundation.layout.Column
        import androidx.compose.foundation.layout.Spacer
        import androidx.compose.foundation.layout.fillMaxSize
        import androidx.compose.foundation.layout.fillMaxWidth
        import androidx.compose.foundation.layout.height
        import androidx.compose.foundation.layout.padding
        import androidx.compose.material3.Button
        import androidx.compose.material3.MaterialTheme.typography
        import androidx.compose.material3.Text
        import androidx.compose.runtime.Composable
        import androidx.compose.ui.Alignment
        import androidx.compose.ui.Modifier
        import androidx.compose.ui.tooling.preview.Preview
        import androidx.compose.ui.unit.dp
        import io.boxo.launchminiapp.ui.theme.LaunchminiappTheme
        import io.boxo.sdk.Boxo

        class MainActivity : FragmentActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                enableEdgeToEdge()
                setContent {
                    LaunchminiappTheme {
                        WelcomeScreen(
                            onOpenMiniappClick = {
                                Boxo.getMiniapp("appId").open()
                            }
                        )
                    }
                }
            }
        }

        @Composable
        fun WelcomeScreen(
            onOpenMiniappClick: () -> Unit,
            modifier: Modifier = Modifier
        ) {
            Column(
                modifier = modifier
                    .fillMaxSize()
                    .padding(24.dp),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                Text(
                    text = "Welcome",
                    style = typography.headlineMedium,
                    modifier = Modifier.padding(bottom = 16.dp)
                )
                Spacer(modifier = modifier.height(64.dp))
                Button(
                    onClick = onOpenMiniappClick,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(52.dp)
                ) {
                    Text("Open Miniapp")
                }
            }
        }

        @Preview(showBackground = true)
        @Composable
        fun WelcomeScreenPreview() {
            LaunchminiappTheme {
                WelcomeScreen(
                    onOpenMiniappClick = {}
                )
            }
        }
        ```
      </Accordion>

      <Accordion title="SDK Configurations">
        Configure BoxoSDK with these settings to customize behavior, language, and UI elements.

        #### Language Configuration

        Use it to provide language to miniapp.  Default: 'en'

        ```
        Boxo.init(this)
            .setConfig(
                Config.Builder()
                    .setLanguage("en")
                    .build()
            )
        ```

        #### System Behavior

        ```
        Boxo.setConfig(
            Config.Builder()
                .debug(BuildConfig.DEBUG)
                .build()
            )
        ```

        | **Parameter** | **Type** | **Description**                             | **Default** |
        | :------------ | :------- | :------------------------------------------ | :---------- |
        | `debug`       | Boolean  | Enables WebView debugging (Chrome DevTools) | `false`     |

        #### Miniapp Menu Customization

        ```
        Boxo.setConfig(
            Config.Builder()
                .permissionsPage(false)  // Hide "Settings"
                .showClearCache(false)   // Hide "Clear Cache"
                .showAboutPage(true)    // Show "About"
                .build()
            )
        ```

        | **Parameter**     | **Description**         | **Default** |
        | :---------------- | :---------------------- | :---------- |
        | `permissionsPage` | Setting menu item       | `true`      |
        | `showClearCache`  | Clear Cache menu item   | `true`      |
        | `showAboutPage`   | About Miniapp menu item | `true`      |

        #### Sandbox Mode Configuration

        Control which miniapps are available in your development environment using the sandbox mode flag:

        ```kotlin theme={"system"}
        Boxo.setConfig(
            Config.Builder()
                .sandboxMode(true)  // Enable sandbox mode
                .build()
        )
        ```

        Behavior: [Retrieve Miniapp List](/host-apps/BoxoSDK#retrieve-miniapp-list) will return miniapps with the statuses listed below.

        | **Sandbox Mode** | **Available Miniapp**  **Statuses** | **Use Case**                                                  |
        | :--------------- | :---------------------------------- | :------------------------------------------------------------ |
        | `true`           | `Approved` + `InTesting`            | Development environment - access to miniapps still in testing |
        | `false`          | `Approved` only                     | Production environment - only fully approved miniapps         |

        #### Theme Configuration

        Configure native component theming to match your app's design system or respect user preferences. The SDK provides comprehensive theme support for:

        * Splash screens
        * Native UI components
        * System dialogs and alerts

        **Theme Options**:

        | **Option** | **Description**                    |
        | :--------- | :--------------------------------- |
        | `SYSTEM`   | Automatically matches device theme |
        | `LIGHT`    | Forces light theme                 |
        | `DARK`     | Forces dark theme                  |

        Control theme behavior at both global and per-miniapp levels for maximum flexibility.

        **Global Theme (Affects all miniapps)**

        ```kotlin theme={"system"}
        Boxo.setConfig(Config.Builder()
            ...
        	.setTheme(Config.Theme.SYSTEM)  // DEFAULT: Follows system setting
            .build())
        ```

        **Per-Miniapp Theme Override**

        ```kotlin theme={"system"}
        // Override theme for specific miniapp
        Boxo.getMiniapp(appId)
            .setConfig(MiniappConfig.Builder()
                .setTheme(Config.Theme.LIGHT)  // Overrides global theme
                .build())
            .open()
        ```
      </Accordion>

      <Accordion title="Miniapp Auth Flow">
        Handle authentication between your host app and miniapps:

        ```kotlin theme={"system"}
        miniapp.setAuthListener { _, miniapp, requiredFields ->
            // requiredFields - list of user data fields requested by the miniapp,
            // e.g. ["email", "phone"]. Empty if the miniapp doesn't require any.

            // 1. Fetch auth code from your backend
            val authCode = fetchAuthCodeFromBackend(requiredFields)

            // 2. Provide code to Miniapp
            miniapp.setAuthCode(authCode)
        }
        ```

        If you don't need `requiredFields`, the shorter overload is still available:

        ```kotlin theme={"system"}
        miniapp.setAuthListener { _, miniapp ->
            miniapp.setAuthCode(fetchAuthCodeFromBackend())
        }
        ```

        <Note>
          The `requiredFields` parameter is available starting from Android SDK `1.43.0`.
        </Note>
      </Accordion>

      <Accordion title="User Logout & Data Clearing">
        When users log out of your host app, you must completely clear all miniapp session data

        ```kotlin theme={"system"}
        Boxo.logout()
        ```
      </Accordion>

      <Accordion title="Miniapp URL Change Listener">
        To listen for any URL change events use .setUrlChangeListener:

        ```kotlin theme={"system"}
        Boxo.getMiniapp(appId)
            .setUrlChangeListener { _, miniapp, uri ->
                Log.e("URL Path", uri.path)
                uri.queryParameterNames.forEach {
                    Log.e("URL params", "$it = ${uri.getQueryParameter(it)}")
                }
            }
            .open()
        ```
      </Accordion>

      <Accordion title="Custom URL Parameters">
        Append additional query parameters to miniapp's initial URL for passing contextual data. This enables:

        * User-specific data injection
        * Campaign tracking
        * Contextual deep linking
        * A/B testing configuration

        **Basic Implementation**

        ```kotlin theme={"system"}
        Boxo.getMiniapp(appId)
            .setConfig(
                MiniappConfig.Builder()
                    .setExtraUrlParams(
                        mapOf(
                            "user_id" to "u_12345",
                            "campaign" to "summer_sale"
                        )
                    )
                    .build()
            )
            .open()
        ```

        Parameters will be automatically URL-encoded and appended as query parameters:

        ```
        https://miniapp.example.com?user_id=u_12345&campaign=summer_sale
        ```
      </Accordion>

      <Accordion title="Custom Event Handling">
        Establish two-way communication between your hostapp and miniapps using custom events. This system enables:

        * Real-time data exchange
        * User interaction tracking
        * Miniapp to host app callbacks
        * Dynamic content updates

        ```kotlin theme={"system"}
        miniapp.setCustomEventListener { _, miniapp, event ->
            when (event.name) {
                "userAction" -> handleUserAction(event.payload)
                "requestData" -> sendResponseData(miniapp, event)
                else -> Log.w("CustomEvent", "Unhandled event: ${event.name}")
            }
        }

        // Send response back to miniapp
        private fun sendResponseData(miniapp: Miniapp, event: CustomEvent) {
            event.payload = mapOf(
                "status" to "success",
                "code" to 200
            )
            miniapp.sendEvent(event)
        }
        ```
      </Accordion>

      <Accordion title="Adding Custom Action Menu">
        You can extend the miniapp's native menu by adding your own custom action item. This is achieved through two simple steps:

        1. **Define the Menu Item**\
           Use `.setCustomActionMenuItem()` to specify your custom button's appearance
        2. **Handle User Interactions**\
           Implement `.setCustomActionMenuItemClickListener()` to respond when users tap your button

        ```kotlin theme={"system"}
        Boxo.getMiniapp(appId)
            .setConfig(
                MiniappConfig.Builder()
                    .setCustomActionMenuItem(R.drawable.ic_custom_menu)
                    .build()
            )
            .setCustomActionMenuItemClickListener { _, miniapp ->
                // do something
            }
            .open()
        ```

        **Control Visibility:**

        ```
        // Hide the item
        miniapp.hideCustomActionMenuItem()

        // Show when needed
        miniapp.showCustomActionMenuItem()
        ```
      </Accordion>

      <Accordion title="Retrieve Miniapp List">
        Fetch the complete catalog of available miniapps with detailed metadata. This asynchronous operation returns:

        * Basic miniapp information (id, name, description)
        * Logo
        * Category

        ```kotlin theme={"system"}
        Boxo.getMiniapps(object: MiniappListCallback{
                    override fun onFailure(e: Exception) {
                       Log.e("MiniappList", "Failed to load miniapps")
                    }

                    override fun onSuccess(miniapps: List<MiniappData>) {
                        miniapps.forEach { data->
                          print(data.appId)
                          print(data.name)
                          print(data.description)
                          print(data.logo)
                          print(data.category)
                        }
                    }
                })
        ```
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background Colors

        Use the `setSplashBackgroundColors` method in `Config.Builder` to configure splash background colors:

        ```kotlin theme={"system"}
        Boxo.init(this)
            .setConfig(
                Config.Builder()
                    .setSplashBackgroundColors(
                        light = "#6A22C9".toColorInt(),
                        dark  = "#C495FF".toColorInt()
                    )
                    .build()
            )
        ```

        ### Progress Bar Colors

        Use the `setProgressBarColors` method in `Config.Builder` to configure progress bar colors:

        ```kotlin theme={"system"}
        Boxo.init(this)
            .setConfig(
                Config.Builder()
                    .setProgressBarColors(
                        lightIndicator = "#000000".toColorInt(),
                        lightTrack     = "#DAD5D5".toColorInt(),
                        darkIndicator  = "#006DD1".toColorInt(),
                        darkTrack      = "#FFFFFF".toColorInt()
                    )
                    .build()
            )
        ```

        ### Splash Behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        You can control this behavior using `MiniappConfig`. For example, to disable the splash screen entirely:

        ```kotlin theme={"system"}
        Boxo.getMiniapp(appId)
            .setConfig(
                MiniappConfig.Builder()
                    .enableSplash(false) // Disable splash screen
                    .build()
            )
            .open()
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects to enhance the user experience by setting the appropriate page transition animation when opening a miniapp.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP`- The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect. You can easily change the animation to any of the other available options based on the user experience you want to provide.

        ```
        Boxo.getMiniapp(appId)
            .setConfig(
                MiniappConfig.Builder()
                    ...
        			// Set the page animation to slide from right to left
                    .pageAnimation(PageAnimation.RIGHT_TO_LEFT)
                    .build()
            )
            .open()
        ```
      </Accordion>

      <Accordion title="Miniapp Lifecycle Events">
        Track key moments in a miniapp's execution by implementing the `LifecycleListener`. The callbacks `onLaunch`, `onResume`, `onPause`, `onClose`, `onError`, and `onUserInteraction` let you monitor the miniapp lifecycle and user touches.

        ```kotlin theme={"system"}
        miniapp.setLifecycleListener(object : Miniapp.LifecycleListener {
            override fun onLaunch(miniapp: Miniapp) {
        		// Triggers when miniapp begins launching via miniapp.open()
                // Ideal for analytics tracking and initial setup
            }

            override fun onResume(miniapp: Miniapp) {
        		// Called when miniapp returns to foreground
                // Use to resume paused operations
            }

            override fun onPause(miniapp: Miniapp) {
        		// Called when miniapp loses foreground focus
                // Pause ongoing operations
            }

            override fun onClose(miniapp: Miniapp) {
                // Triggers when:
                // - User taps close button
                // - Miniapp activity is destroyed
                // Clean up resources and finalize analytics
            }

            override fun onError(miniapp: Miniapp, message: String) {
                // Called when miniapp fails to launch due to internet connection issues
            }

            override fun onUserInteraction(miniapp: Miniapp) {
                // Called whenever a touch event is dispatched to the miniapp page
                // Useful for custom idle timeouts
            }
        })
        ```
      </Accordion>

      <Accordion title="Obfuscation Rules">
        To protect intellectual property, deter reverse engineering, and enhance code security

        ```js theme={"system"}
        -keepclassmembers class io.boxo.js.jsInterfaces.BoxoJsInterface{
            public *; 
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Flutter">
    ## Flutter

    A [Flutter plugin](https://pub.dev/packages/appboxo_sdk) to integrate Boxo for iOS and Android. Please see our [sample Flutter app](https://github.com/Appboxo/sample-flutter-app) to learn more.

    <AccordionGroup>
      <Accordion title="Installation">
        ![Pub Version](https://img.shields.io/pub/v/appboxo_sdk)

        Run this command:
        With Flutter:

        ```bash theme={"system"}
        flutter pub add appboxo_sdk
        ```

        This will add a line like this to your package's pubspec.yaml (and run an implicit <code>flutter pub get</code>):

        dependencies:
        appboxo\_sdk: ^0.8.0

        Add this line to android/gradle.properties

        ```
          android.enableJetifier=true
        ```
      </Accordion>

      <Accordion title="Launch Miniapp">
        ```
        import 'package:appboxo_sdk/boxo.dart';
        ```

        ```
        Boxo.setConfig( clientId: '[client_id]');
        ```

        ```
        Boxo.openMiniapp( appId );
        ```
      </Accordion>

      <Accordion title="Set Config">
        ```dart theme={"system"}
        import 'package:appboxo_sdk/boxo.dart';

        Boxo.setConfig(
            clientId: '[client_id]', // your Boxo client_id
            userId: '[hostapp_user_id]',// will be used for the consent screen
            language: 'en', // use it to provide language to miniapp. by default 'en'
            sandboxMode: false, // sandbox mode. By default 'false'
            theme: 'dark', // (optional) miniapp theme "dark" | "light" (by default is system theme),
            isDebug: true,  // by default 'false', enables webview debugging
            showClearCache: true,  // use it to hide "Clear cache" from Miniapp menu, by default 'true'
            showPermissionsPage: true, // use it to hide "Settings" from Miniapp menu, by default 'true'
            showAboutPage: true,  // show/hide "About page" on Miniapp menu, by default 'true'
            splashScreenOptions: {  // (optional) to customize the splash screen background and the loading progress indicator
                  'light_progress_indicator': '#000000',
                  'light_progress_track': '#FFFFFF',
                  'light_background': '#FFFFF',
                  'dark_progress_indicator': '#FFFFFF',
                  'dark_progress_track': '#000000',
                  'dark_background': '#000000'
                }
        );

        Boxo.openMiniapp(
            "[miniapp_id]", // your miniapp id
            data: {'key': 'value'}, // (optional) data as Map that is sent to miniapp
            theme: 'dark', // (optional) miniapp theme "dark" | "light" (by default is system theme)
            enableSplash:  false // (optional) to skip splash screen. if enabled, the splash screen will be hidden when 50% of web content is loaded. Otherwise, when the web page starts loading. By default is enabled.
        );

        Boxo.hideMiniapps(); //use it to close all miniapp screens

        Boxo.logout(); //On logout from your app, call it to clear all miniapps data.
        ```
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background and progress colors

        Pass `splashScreenOptions` to `Boxo.setConfig`. Keys use snake case and hex color strings:

        | Key                        | Description                           |
        | :------------------------- | :------------------------------------ |
        | `light_background`         | Splash background in light appearance |
        | `dark_background`          | Splash background in dark appearance  |
        | `light_progress_indicator` | Progress indicator color (light)      |
        | `light_progress_track`     | Progress track color (light)          |
        | `dark_progress_indicator`  | Progress indicator color (dark)       |
        | `dark_progress_track`      | Progress track color (dark)           |

        ```dart theme={"system"}
        Boxo.setConfig(
          clientId: '[client_id]',
          splashScreenOptions: {
            'light_background': '#FFFFFF',
            'dark_background': '#000000',
            'light_progress_indicator': '#000000',
            'light_progress_track': '#FFFFFF',
            'dark_progress_indicator': '#FFFFFF',
            'dark_progress_track': '#000000',
          },
        );
        ```

        ### Splash behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        Pass `enableSplash` to `Boxo.openMiniapp` to control it for a single launch (for example, to turn it off):

        ```dart theme={"system"}
        Boxo.openMiniapp(
          '[miniapp_id]',
          enableSplash: false,
        );
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects when opening a miniapp by passing `pageAnimation` to `Boxo.openMiniapp`.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP` - The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect.

        ```dart theme={"system"}
        Boxo.openMiniapp(
          '[miniapp_id]',
          pageAnimation: 'RIGHT_TO_LEFT',
        );
        ```
      </Accordion>

      <Accordion title="Sandbox mode">
        sandboxMode: it should open miniapps in "Approved" and "InTesting" statuses [List of miniapps](/host-apps/BoxoSDK#get-list-of-miniapps-3) returns:

        * when true, miniapps in "Approved" and "InTesting" statuses
        * when false, miniapps only in "Approved" status
      </Accordion>

      <Accordion title="Get list of miniapps">
        ```dart theme={"system"}
        Boxo.miniapps().listen((result) {
          result.miniapps?.forEach((data) {
            print(data.appId);
            print(data.name);
            print(data.description);
            print(data.logo);
            print(data.category);
          });
          print('error - ${result.error}');
        });

        Boxo.getMiniapps();
        ```
      </Accordion>

      <Accordion title="To listen miniapp lifecycle events">
        ```dart theme={"system"}
        import 'package:flutter/material.dart';
        import 'package:appboxo_sdk/boxo.dart';

        void main() => runApp(MyApp());

        class MyApp extends StatefulWidget {
          @override
          _MyAppState createState() => _MyAppState();
        }

        class _MyAppState extends State<MyApp> {
          Future<void> Function() subscription;

          @override
          void dispose() {
            subscription();
            super.dispose();
          }

          @override
          void initState() {
            super.initState();
            subscription = Boxo.lifecycleHooksListener(
              onAuth: (appId) { // called when authorization flow starts
                //sample
                http.get(Uri.parse('get_auth_code_url'))
                        .then((response) {
                  if (response.statusCode >= 400) {
                    print('Error fetching auth code: ${response.body}');
                    Boxo.setAuthCode(appId, "");
                  } else {
                    Boxo.setAuthCode(appId, json.decode(response.body)["auth_code"]);
                  }
                });
              },
              onLaunch: (appId) {
                print(appId);
                print('onLaunch');
              },
              onResume: (appId) {
                print(appId);
                print('onResume');
              },
              onPause: (appId) {
                print(appId);
                print('onPause');
              },
              onClose: (appId) {
                print(appId);
                print('onClose');
              },
              onError: (appId, error) {
                print(appId);
                print(error);
                print('onError');
              },
              onUserInteraction: (appId) {
                print(appId);
                print('onUserInteraction');
              },
            );
          }

          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              home: Scaffold(
                appBar: AppBar(
                  title: const Text('Boxo SDK Test'),
                ),
                body: Center(
                  child: MaterialButton(
                    onPressed: () {
                      Boxo.openMiniapp("[miniapp_id]"); //launch miniapp by id
                    },
                    padding: const EdgeInsets.all(16),
                    color: Colors.blue,
                    child: const Text(
                      'Run miniapp',
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 16,
                      ),
                    ),
                  ),
                ),
              ),
            );
          }
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="React Native">
    ## React Native

    A react native wrapper over Boxo SDK for iOS and Android.

    <AccordionGroup>
      <Accordion title="Installation">
        ```
        yarn add @appboxo/react-native-sdk
        ```

        or

        ```
        npm install @appboxo/react-native-sdk
        ```

        Please make sure the "@appboxo/react-native-sdk" dependency is linked, if not please run:

        ```
        react-native link @appboxo/react-native-sdk
        ```

        Add this line to android/gradle.properties

        ```
          android.enableJetifier=true
        ```

        Next for iOS:

        ```
        cd ios && pod install
        ```
      </Accordion>

      <Accordion title="Launch Miniapp">
        ```
        import Boxo from '@appboxo/react-native-sdk';
        ```

        ```
        Boxo.setConfig( clientId );
        ```

        ```
        Boxo.openMiniapp( appId );
        ```
      </Accordion>

      <Accordion title="Usage">
        ```clike theme={"system"}
        import React from 'react';
        import Boxo from '@appboxo/react-native-sdk';
        import { StyleSheet, View, Button } from 'react-native';

        export default function App() {

          React.useEffect(() => {
            Boxo.setConfig(
              '[client_id]', { // your Boxo client_id
                userId: [hostapp_user_id], // will be used for the consent screen
                language: 'en', // to provide language to miniapp. by default 'en'
                sandboxMode: false, // sandbox mode. By default 'false'
                theme: 'light', // (optional) miniapp theme "dark" | "light" (by default is "system")
                isDebug: true,  // by default 'false', enables webview debugging
                showClearCache: true,  // use it to hide "Clear cache" from Miniapp menu, by default 'true'     
                showPermissionsPage: true, // use it to hide "Settings" from Miniapp menu, by default 'true'
                showAboutPage: true,  // show/hide "About page" on Miniapp menu, by default 'true'
                splashScreenOptions: {  // (optional) to customize the splash screen background and the loading progress indicator
                   lightProgressIndicator: "#000000",
                   lightProgressTrack: "#FFFFFF",
                   darkProgressIndicator: "#FFFFFF",
                   darkProgressTrack: "#000000",
                   lightBackground:"#FFFFFF",
                   darkBackground:"#000000"
                }
              }
            );
          }, [])

          const handleOpenMiniapp = () => {
            const options = {
              data: {'key': 'value'},           // (optional) data as {[key: string]: any} that is passed to miniapp in `.getInitData` call
              theme: 'dark',                    // (optional) miniapp theme "dark" | "light" | "system" (by default is value of "theme" argument in setConfig function)
              extraUrlParams: {param: 'test'},  // (optional) extra query params to append to miniapp URL (like: http://miniapp-url.com/?param=test)
              pageAnimation: 'RIGHT_TO_LEFT',   // (optional) launch transition, see Page Animation Configuration below
            }
            Boxo.openMiniapp(
              '[miniapp_id]',           // miniapp ID to be launched
              options                   // (optional) options
            );
          }

          return (
            <View style={styles.container}>
              <Button
                color="#841584"
                title="Launch miniapp"
                onPress={handleOpenMiniapp}
                accessibilityLabel="Launch miniapp"
            />
            </View>
          );
        }

        const styles = StyleSheet.create({
          container: {
            flex: 1,
            alignItems: 'center',
            backgroundColor: '#fff',
            justifyContent: 'center',
          },
        });
        ```
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background and progress colors

        Use `splashScreenOptions` in the second argument of `Boxo.setConfig`:

        | Property                 | Description                           |
        | :----------------------- | :------------------------------------ |
        | `lightBackground`        | Splash background in light appearance |
        | `darkBackground`         | Splash background in dark appearance  |
        | `lightProgressIndicator` | Progress indicator color (light)      |
        | `lightProgressTrack`     | Progress track color (light)          |
        | `darkProgressIndicator`  | Progress indicator color (dark)       |
        | `darkProgressTrack`      | Progress track color (dark)           |

        ```clike theme={"system"}
        Boxo.setConfig('[client_id]', {
          splashScreenOptions: {
            lightBackground: '#FFFFFF',
            darkBackground: '#000000',
            lightProgressIndicator: '#000000',
            lightProgressTrack: '#FFFFFF',
            darkProgressIndicator: '#FFFFFF',
            darkProgressTrack: '#000000',
          },
        });
        ```

        ### Splash behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        Set `enableSplash` in the options object passed to `Boxo.openMiniapp` (for example, `false` to disable the splash for that launch):

        ```clike theme={"system"}
        Boxo.openMiniapp('[miniapp_id]', {
          enableSplash: false,
        });
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects when opening a miniapp by setting `pageAnimation` in the second argument of `Boxo.openMiniapp`.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP` - The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect.

        ```clike theme={"system"}
        Boxo.openMiniapp('[miniapp_id]', {
          pageAnimation: 'RIGHT_TO_LEFT',
        });
        ```
      </Accordion>

      <Accordion title="Miniapp lifecycle events">
        <Tip>
          **Important**
          Miniapp lifecycle events available in 1.0.8+ versions
        </Tip>

        ```clike theme={"system"}
        import React from 'react';
        import Boxo from '@appboxo/react-native-sdk';
        import { StyleSheet, View, Button } from 'react-native';

        export default function App() {

          React.useEffect(() => {
            Boxo.setConfig('[client_id]', false); //set your Boxo client id
            
            const subscription = Boxo.lifecycleHooksListener({
              onLaunch: (appId: string) => console.log('onLaunch', appId),  // called when the miniapp will launch with openMiniapp(...)
              onResume: (appId: string) => console.log('onResume', appId),  // called when the miniapp will start interacting with the user
              onPause: (appId: string) => console.log('onPause', appId),    // called when clicked close button in miniapp
              onClose: (appId: string) => console.log('onClose', appId),    // called when the miniapp loses foreground state
              onAuth: (appId: string) => console.log('onAuth', appId),    // called when authorization flow starts
              onError: (appId: string, error: string) => console.log('onError', appId, error),  // handle error
              onUserInteraction: (appId: string) => console.log('onUserInteraction', appId),  // called on touch events in the miniapp (e.g. custom idle timeouts)
            });

            return () => subscription();
          }, [])

          const handleOpenMiniapp = () => {
            Boxo.openMiniapp('[miniapp_id]');           // miniapp ID to be launched
          }

          return (
            <View style={styles.container}>
              <Button
                color="#841584"
                title="Launch miniapp"
                onPress={handleOpenMiniapp}
                accessibilityLabel="Launch miniapp"
            />
            </View>
          );
        }

        const styles = StyleSheet.create({
          container: {
            flex: 1,
            alignItems: 'center',
            backgroundColor: '#fff',
            justifyContent: 'center',
          },
        });
        ```
      </Accordion>

      <Accordion title="Append custom params to miniapp URL">
        <Tip>
          **Important**
          Custom params available in 1.0.26+ versions
        </Tip>

        To append any custom data as URL param to miniapp's URL use extraUrlParams:

        ```clike theme={"system"}
        const options = {
          extraUrlParams: {param: 'test'}  // (optional) extra query params to append to miniapp URL (like: http://miniapp-url.com/?param=test)
        }
        Boxo.openMiniapp(
          '[miniapp_id]',           // miniapp ID to be launched
          options                   // (optional) options
        );
        ```
      </Accordion>

      <Accordion title="Sandbox mode">
        sandboxMode: it should open miniapps in "Approved" and "InTesting" statuses [List of miniapps](/host-apps/BoxoSDK#get-list-of-miniapps-4) returns:

        * when true, miniapps in "Approved" and "InTesting" statuses
        * when false, miniapps only in "Approved" status
      </Accordion>

      <Accordion title="Get list of miniapps">
        ```clike theme={"system"}
        React.useEffect(() => {
            const miniappListSubscription = Boxo.miniapps.subscribe((miniapps: MiniappData[]) => {
                    setMiniapps(miniapps);
                }, (error) => {
                    console.log(error)
                },
                );
            Boxo.getMiniapps();
            return () => miniappListSubscription();
          }, [])
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Capacitor">
    ## Capacitor

    <AccordionGroup>
      <Accordion title="Installation">
        ```bash theme={"system"}
        npm install @appboxo/capacitor-boxo-sdk
        ```

        ```bash theme={"system"}
        npx cap sync
        ```
      </Accordion>

      <Accordion title="Launch Miniapp">
        ```
        import { Boxo } from 'capacitor-boxo-sdk';
        ```

        ```
        Boxo.setConfig({  clientId: clientId });
        ```

        ```
        Boxo.openMiniapp({ appId: appId });
        ```

        Example:

        ```index.html [expandable] theme={"system"}
        <!DOCTYPE html>
        <html lang="en" dir="ltr" class="hydrated">
          <head>
            <meta charset="UTF-8" />
            <title>Example Capacitor App</title>
            <meta
              name="viewport"
              content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
            />
            <meta name="format-detection" content="telephone=no" />
          </head>
          <body>
            <main>
              <h1>Capacitor Test App</h1>
              <p>Click to button to open Demo Miniapp</p>
              <button onclick="openMiniapp()">Open miniapp</button>
            </main>
            <script src="./js/example.js" type="module"></script>
          </body>
        </html>
        ```

        ```javascript js/example.js [expandable] theme={"system"}
        import { Boxo } from 'capacitor-boxo-sdk';

        const clientId = '';
        const appId = '';

        Boxo.setConfig({
          clientId: clientId
        });

        window.openMiniapp = () => {
          Boxo.openMiniapp({ appId: appId});
        };
        ```

        ### Set Config

        ```typescript theme={"system"}
        setConfig(options: ConfigOptions) => Promise<void>
        ```
      </Accordion>

      <Accordion title="Set Config">
        **Config Options**

        | Prop                          | Type                                       | Description                                                              |
        | ----------------------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
        | clientId                      | <code>string</code>                        | your client id from dashboard                                            |
        | userId                        | <code>string</code>                        | (optional) hostapp userId, will be used for the Consent Management       |
        | language                      | <code>string</code>                        | language value will be passed to the miniapp                             |
        | sandboxMode                   | <code>boolean</code>                       | switch to sandbox mode                                                   |
        | theme                         | <code>'light' \| 'dark' \| 'system'</code> | theme for splash screen and other native components used inside miniapp. |
        | isDebug                       | <code>boolean</code>                       | enables webview debugging                                                |
        | showPermissionsPage           | <code>boolean</code>                       | use it to hide "Settings" from Miniapp menu                              |
        | showClearCache                | <code>boolean</code>                       | use it to hide "Clear cache" from Miniapp menu                           |
        | showAboutPage                 | <code>boolean</code>                       | use it to hide "About Page" from Miniapp menu                            |
        | miniappSettingsExpirationTime | <code>number</code>                        | use it to change miniapp settings cache time in sec. Default:  60 sec    |
        | splashScreenOptions           | <code>SplashScreenOptions</code>           | (optional) setup splash screen configs                                   |

        **SplashScreenOptions**

        | Prop                   | Type                |
        | ---------------------- | ------------------- |
        | lightBackground        | <code>string</code> |
        | darkBackground         | <code>string</code> |
        | lightProgressIndicator | <code>string</code> |
        | lightProgressTrack     | <code>string</code> |
        | darkProgressIndicator  | <code>string</code> |
        | darkProgressTrack      | <code>string</code> |
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background and progress colors

        Call `Boxo.setConfig` with `splashScreenOptions` (hex strings). The same fields are listed in the Set Config section above.

        ```typescript theme={"system"}
        await Boxo.setConfig({
          clientId: clientId,
          splashScreenOptions: {
            lightBackground: '#FFFFFF',
            darkBackground: '#000000',
            lightProgressIndicator: '#000000',
            lightProgressTrack: '#FFFFFF',
            darkProgressIndicator: '#FFFFFF',
            darkProgressTrack: '#000000',
          },
        });
        ```

        ### Splash behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        Pass `enableSplash` in `openMiniapp` to control splash for that launch (`false` disables it):

        ```typescript theme={"system"}
        await Boxo.openMiniapp({
          appId: appId,
          enableSplash: false,
        });
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects when opening a miniapp by setting `pageAnimation` in `openMiniapp` options.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP` - The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect.

        ```typescript theme={"system"}
        await Boxo.openMiniapp({
          appId: appId,
          pageAnimation: 'RIGHT_TO_LEFT',
        });
        ```
      </Accordion>

      <Accordion title="Miniapp Control">
        #### Open

        ```typescript theme={"system"}
        openMiniapp(options: OpenMiniappOptions) => Promise<void>
        ```

        Open miniapp with options

        **OpenMiniappOptions**

        | Prop           | Type                                                                                                        | Description                                                                                                                             |
        | -------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
        | appId          | <code>string</code>                                                                                         | miniapp id                                                                                                                              |
        | data           | <code>object</code>                                                                                         | (optional) data as Map that is sent to miniapp                                                                                          |
        | theme          | <code>'light' \| 'dark' \| 'system'</code>                                                                  | (optional) miniapp theme "dark" \| "light" (by default is system theme)                                                                 |
        | extraUrlParams | <code>object</code>                                                                                         | (optional) extra query params to append to miniapp URL (like: [http://miniapp-url.com/?param=test](http://miniapp-url.com/?param=test)) |
        | urlSuffix      | <code>string</code>                                                                                         | (optional) suffix to append to miniapp URL (like: [http://miniapp-url.com/?param=test](http://miniapp-url.com/?param=test))             |
        | colors         | <code><a href="#coloroptions">ColorOptions</a></code>                                                       | (optional) provide colors to miniapp if miniapp supports                                                                                |
        | enableSplash   | <code>boolean</code>                                                                                        | (optional) use to skip miniapp splash screen                                                                                            |
        | saveState      | <code>boolean</code>                                                                                        | (optional) use to save state on close miniapp                                                                                           |
        | pageAnimation  | <code>'BOTTOM\_TO\_TOP' \| 'TOP\_TO\_BOTTOM' \| 'LEFT\_TO\_RIGHT' \| 'RIGHT\_TO\_LEFT' \| 'FADE\_IN'</code> | (optional) use to change launch animation for miniapp                                                                                   |

        **ColorOptions**

        | Prop           | Type                |
        | -------------- | ------------------- |
        | primaryColor   | <code>string</code> |
        | secondaryColor | <code>string</code> |
        | tertiaryColor  | <code>string</code> |

        #### Close

        ```typescript theme={"system"}
        closeMiniapp(options: { appId: string; }) => Promise<void>
        ```

        close miniapp by appId

        #### Hide

        ```typescript theme={"system"}
        hideMiniapps() => Promise<void>
        ```

        Miniapp opens on a native screen. To show payment processing page need to hide miniapp screen.
      </Accordion>

      <Accordion title="Miniapp Auth Flow">
        Handle authentication between your host app and miniapps:

        ```typescript theme={"system"}
         setAuthCode(options: { appId: string; authCode: string; }) => Promise<void>
        ```
      </Accordion>

      <Accordion title="User Logout & Data Clearing">
        When users log out of your host app, you must completely clear all miniapp session data

        ```typescript theme={"system"}
        logout() => Promise<void>
        ```
      </Accordion>

      <Accordion title="Retrieve Miniapp List">
        ```typescript theme={"system"}
        getMiniapps() => Promise<MiniappListResult>
        ```

        Get list of miniapps

        **MiniappListResult**

        | Prop     | Type                        |
        | -------- | --------------------------- |
        | miniapps | <code>\[MiniappData]</code> |
        | error    | <code>string</code>         |

        **MiniappData**

        | Prop        | Type                |
        | ----------- | ------------------- |
        | appId       | <code>string</code> |
        | name        | <code>string</code> |
        | category    | <code>string</code> |
        | description | <code>string</code> |
        | logo        | <code>string</code> |
      </Accordion>

      <Accordion title="Miniapp Custom Events">
        ```typescript theme={"system"}
        addListener(eventName: 'custom_event', listenerFunc: (customEvent: CustomEvent) => void) => Promise<PluginListenerHandle>
        ```

        When host app user logs out, it is highly important to clear all miniapp storage data.

        | Param        | Type                                                                       |
        | ------------ | -------------------------------------------------------------------------- |
        | eventName    | <code>'custom\_event'</code>                                               |
        | listenerFunc | <code>(customEvent: <a href="#customevent">CustomEvent</a>) => void</code> |

        ```typescript theme={"system"}
        sendCustomEvent(customEvent: CustomEvent) => Promise<void>
        ```

        send custom event data to miniapp

        | Prop      | Type                |
        | --------- | ------------------- |
        | appId     | <code>string</code> |
        | requestId | <code>number</code> |
        | type      | <code>string</code> |
        | errorType | <code>string</code> |
        | payload   | <code>object</code> |
      </Accordion>

      <Accordion title="Miniapp Payment Events">
        ```typescript theme={"system"}
        addListener(eventName: 'payment_event', listenerFunc: (paymentEvent: PaymentEvent) => void) => Promise<PluginListenerHandle>
        ```

        | Param        | Type                                                                          |
        | ------------ | ----------------------------------------------------------------------------- |
        | eventName    | <code>'payment\_event'</code>                                                 |
        | listenerFunc | <code>(paymentEvent: <a href="#paymentevent">PaymentEvent</a>) => void</code> |

        ```typescript theme={"system"}
        sendPaymentEvent(paymentEvent: PaymentEvent) => Promise<void>
        ```

        send payment data to miniapp

        | Prop           | Type                |
        | -------------- | ------------------- |
        | appId          | <code>string</code> |
        | orderPaymentId | <code>string</code> |
        | miniappOrderId | <code>string</code> |
        | amount         | <code>number</code> |
        | currency       | <code>string</code> |
        | status         | <code>string</code> |
        | hostappOrderId | <code>string</code> |
        | extraParams    | <code>object</code> |
      </Accordion>

      <Accordion title="Miniapp Lifecycle Events">
        ```typescript theme={"system"}
        addListener(eventName: 'miniapp_lifecycle', listenerFunc: (lifecycle: LifecycleEvent) => void) => Promise<PluginListenerHandle>
        ```

        | Param        | Type                                                                           |
        | ------------ | ------------------------------------------------------------------------------ |
        | eventName    | <code>'miniapp\_lifecycle'</code>                                              |
        | listenerFunc | <code>(lifecycle: <a href="#lifecycleevent">LifecycleEvent</a>) => void</code> |

        **LifecycleEvent**

        | Prop      | Type                |
        | --------- | ------------------- |
        | appId     | <code>string</code> |
        | lifecycle | <code>string</code> |
        | error     | <code>string</code> |

        onLaunch - Called when the miniapp will launch with Boxo.open(...)
        onResume - Called when the miniapp will start interacting with the user
        onPause - Called when the miniapp loses foreground state
        onClose - Called when clicked close button in miniapp or when destroyed miniapp page
        onError - Called when miniapp fails to launch due to internet connection issues
        onUserInteraction - Called whenever a touch event is dispatched to the miniapp page
        onAuth - Called when the miniapp starts login and user allows it
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Expo">
    ## Expo

    [Expo plugin](https://www.npmjs.com/package/@appboxo/expo-boxo-sdk) to integrate Boxo for iOS and Android. Please see our [sample Expo app](https://github.com/Appboxo/expo-boxo-sdk/tree/main/example) to learn more.

    <AccordionGroup>
      <Accordion title="Installation">
        ```bash theme={"system"}
        npm install @appboxo/expo-boxo-sdk
        ```

        Configuration in app.json/app.config.js

        ```json theme={"system"}
        {
          "expo": {
            "plugins": [
              ["@appboxo/expo-boxo-sdk"]
            ]
          }
        }
        ```
      </Accordion>

      <Accordion title="Launch Miniapp">
        ```
        import * as Boxo from 'expo-boxo-sdk';
        ```

        ```
        Boxo.setConfig({  clientId: clientId });
        ```

        ```
        Boxo.openMiniapp({ appId: appId });
        ```
      </Accordion>

      <Accordion title="Set Config">
        ```typescript theme={"system"}
        setConfig(options: ConfigOptions)
        ```

        **ConfigOptions**

        | Prop                          | Type                                       | Description                                                              |
        | ----------------------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
        | clientId                      | <code>string</code>                        | your client id from dashboard                                            |
        | userId                        | <code>string</code>                        | (optional) hostapp userId, will be used for the Consent Management       |
        | language                      | <code>string</code>                        | language value will be passed to the miniapp                             |
        | sandboxMode                   | <code>boolean</code>                       | switch to sandbox mode                                                   |
        | theme                         | <code>'light' \| 'dark' \| 'system'</code> | theme for splash screen and other native components used inside miniapp. |
        | isDebug                       | <code>boolean</code>                       | enables webview debugging                                                |
        | showPermissionsPage           | <code>boolean</code>                       | use it to hide "Settings" from Miniapp menu                              |
        | showClearCache                | <code>boolean</code>                       | use it to hide "Clear cache" from Miniapp menu                           |
        | showAboutPage                 | <code>boolean</code>                       | use it to hide "About Page" from Miniapp menu                            |
        | miniappSettingsExpirationTime | <code>number</code>                        | use it to change miniapp settings cache time in sec. Default:  60 sec    |
        | splashScreenOptions           | <code>SplashScreenOptions</code>           | (optional) setup splash screen configs                                   |

        **SplashScreenOptions**

        | Prop                   | Type                |
        | ---------------------- | ------------------- |
        | lightBackground        | <code>string</code> |
        | darkBackground         | <code>string</code> |
        | lightProgressIndicator | <code>string</code> |
        | lightProgressTrack     | <code>string</code> |
        | darkProgressIndicator  | <code>string</code> |
        | darkProgressTrack      | <code>string</code> |
      </Accordion>

      <Accordion title="Splash Screen Configuration">
        When a miniapp is launched, Boxo displays a splash screen while the content is loading.
        You can customize the splash screen background color and the loading progress indicator for both **light** and **dark** themes.

        ### Background and progress colors

        Call `Boxo.setConfig` with `splashScreenOptions` (hex strings). The same fields are listed in the Set Config section above.

        ```typescript theme={"system"}
        Boxo.setConfig({
          clientId: clientId,
          splashScreenOptions: {
            lightBackground: '#FFFFFF',
            darkBackground: '#000000',
            lightProgressIndicator: '#000000',
            lightProgressTrack: '#FFFFFF',
            darkProgressIndicator: '#FFFFFF',
            darkProgressTrack: '#000000',
          },
        });
        ```

        ### Splash behavior

        By default, the splash screen is shown automatically and hides when approximately 50% of the web content has loaded.

        Pass `enableSplash` in `openMiniapp` to control splash for that launch (`false` disables it):

        ```typescript theme={"system"}
        Boxo.openMiniapp({
          appId: appId,
          enableSplash: false,
        });
        ```
      </Accordion>

      <Accordion title="Page Animation Configuration">
        Customize the animation effects when opening a miniapp by setting `pageAnimation` in `openMiniapp` options.

        You can choose from the following page animations:

        * `LEFT_TO_RIGHT` - The miniapp slides in from the left side of the screen to the right.
        * `RIGHT_TO_LEFT` - The miniapp slides in from the right side of the screen to the left.
        * `BOTTOM_TO_TOP` - The miniapp slides in from the bottom of the screen to the top.
        * `TOP_TO_BOTTOM` - The miniapp slides in from the top of the screen to the bottom.
        * `FADE_IN` - The miniapp fades in gradually from completely transparent to opaque.

        The `BOTTOM_TO_TOP` animation is the default page transition effect.

        ```typescript theme={"system"}
        Boxo.openMiniapp({
          appId: appId,
          pageAnimation: 'RIGHT_TO_LEFT',
        });
        ```
      </Accordion>

      <Accordion title="Miniapp Control">
        #### Open

        ```typescript theme={"system"}
        openMiniapp(options: MiniappOptions)
        ```

        Open miniapp with options

        **MiniappOptions**

        | Prop           | Type                                                                                                        | Description                                                                                                                             |
        | -------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
        | appId          | <code>string</code>                                                                                         | miniapp id                                                                                                                              |
        | data           | <code>object</code>                                                                                         | (optional) data as Map that is sent to miniapp                                                                                          |
        | theme          | <code>'light' \| 'dark' \| 'system'</code>                                                                  | (optional) miniapp theme "dark" \| "light" (by default is system theme)                                                                 |
        | extraUrlParams | <code>object</code>                                                                                         | (optional) extra query params to append to miniapp URL (like: [http://miniapp-url.com/?param=test](http://miniapp-url.com/?param=test)) |
        | urlSuffix      | <code>string</code>                                                                                         | (optional) suffix to append to miniapp URL (like: [http://miniapp-url.com/?param=test](http://miniapp-url.com/?param=test))             |
        | colors         | <code><a href="#coloroptions">ColorOptions</a></code>                                                       | (optional) provide colors to miniapp if miniapp supports                                                                                |
        | enableSplash   | <code>boolean</code>                                                                                        | (optional) use to skip miniapp splash screen                                                                                            |
        | saveState      | <code>boolean</code>                                                                                        | (optional) use to save state on close miniapp                                                                                           |
        | pageAnimation  | <code>'BOTTOM\_TO\_TOP' \| 'TOP\_TO\_BOTTOM' \| 'LEFT\_TO\_RIGHT' \| 'RIGHT\_TO\_LEFT' \| 'FADE\_IN'</code> | (optional) use to change launch animation for miniapp                                                                                   |

        **ColorOptions**

        | Prop           | Type                |
        | -------------- | ------------------- |
        | primaryColor   | <code>string</code> |
        | secondaryColor | <code>string</code> |
        | tertiaryColor  | <code>string</code> |

        #### Close

        ```typescript theme={"system"}
        closeMiniapp(appId: string)
        ```

        close miniapp by appId

        #### Hide

        ```typescript theme={"system"}
        hideMiniapps()
        ```

        Miniapp opens on a native screen. To show payment processing page need to hide miniapp screen.
      </Accordion>

      <Accordion title="Miniapp Auth Flow">
        Handle authentication between your host app and miniapps:

        ```typescript theme={"system"}
        Boxo.addAuthListener((authEvent) => {
            Boxo.setAuthCode(authEvent.appId, authCode)
        });
        ```
      </Accordion>

      <Accordion title="User Logout & Data Clearing">
        When users log out of your host app, you must completely clear all miniapp session data

        ```typescript theme={"system"}
        logout()
        ```
      </Accordion>

      <Accordion title="Retrieve Miniapp List">
        ```typescript theme={"system"}
        Boxo.addMiniappListListener((result) => {
          console.log(result.miniapps);
        });
        ```

        Get list of miniapps

        **MiniappListResult**

        | Prop     | Type                        |
        | -------- | --------------------------- |
        | miniapps | <code>\[MiniappData]</code> |
        | error    | <code>string</code>         |

        **MiniappData**

        | Prop        | Type                |
        | ----------- | ------------------- |
        | appId       | <code>string</code> |
        | name        | <code>string</code> |
        | category    | <code>string</code> |
        | description | <code>string</code> |
        | logo        | <code>string</code> |
      </Accordion>

      <Accordion title="Miniapp Custom Events">
        ```typescript theme={"system"}
        Boxo.addCustomEventListener((customEvent) => {
          ..handle custom event
          Boxo.sendCustomEvent(customEvent);
        });
        ```

        Send custom event data to miniapp

        | Prop      | Type                |
        | --------- | ------------------- |
        | appId     | <code>string</code> |
        | requestId | <code>number</code> |
        | type      | <code>string</code> |
        | errorType | <code>string</code> |
        | payload   | <code>object</code> |
      </Accordion>

      <Accordion title="Miniapp Payment Events">
        ```typescript theme={"system"}
        Boxo.addPaymentEventListener((paymentData) => {
          Boxo.hideMiniapps();
          .. show payment page
          paymentData.status = "success";
          ..confirm payment
          Boxo.sendPaymentEvent(paymentData);
          Boxo.openMiniapp({ appId: paymentData.appId })
        });
        ```

        send payment data to miniapp

        | Prop           | Type                |
        | -------------- | ------------------- |
        | appId          | <code>string</code> |
        | orderPaymentId | <code>string</code> |
        | miniappOrderId | <code>string</code> |
        | amount         | <code>number</code> |
        | currency       | <code>string</code> |
        | status         | <code>string</code> |
        | hostappOrderId | <code>string</code> |
        | extraParams    | <code>object</code> |
      </Accordion>

      <Accordion title="Miniapp Lifecycle Events">
        ```typescript theme={"system"}
        Boxo.addMiniappLifecycleListener((lifecycleData) => {
          console.log(lifecycleData);
        });
        ```

        **LifecycleEvent**

        | Prop      | Type                |
        | --------- | ------------------- |
        | appId     | <code>string</code> |
        | lifecycle | <code>string</code> |
        | error     | <code>string</code> |

        onLaunch - Called when the miniapp will launch with Boxo.open(...)
        onResume - Called when the miniapp will start interacting with the user
        onPause - Called when the miniapp loses foreground state
        onClose - Called when clicked close button in miniapp or when destroyed miniapp page
        onError - Called when miniapp fails to launch due to internet connection issues
        onUserInteraction - Called whenever a touch event is dispatched to the miniapp page
        onAuth - Called when the miniapp starts login and user allows it
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Web SDK">
    ## Web SDK

    A JavaScript SDK for embedding miniapps into desktop web applications using iframe communication. Please see our [sample web app](https://github.com/Appboxo/sample-web-hostapp) to learn more.

    <AccordionGroup>
      <Accordion title="Installation">
        ```bash theme={"system"}
        npm install @appboxo/web-sdk
        ```

        or

        ```bash theme={"system"}
        pnpm install @appboxo/web-sdk
        ```
      </Accordion>

      <Accordion title="Launch Miniapp">
        ```typescript theme={"system"}
        import { AppboxoWebSDK } from "@appboxo/web-sdk";

        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id"
        });

        // Mount miniapp
        await sdk.mount({
          container: document.getElementById("miniapp")
        });
        ```
      </Accordion>

      <Accordion title="Configuration">
        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: string;      // Required
          appId: string;         // Required
          userId?: string;       // Optional, user reference identifier
          baseUrl?: string;      // Optional, default: "https://dashboard.boxo.io/api/v1"
          sandboxMode?: boolean;  // Optional, default: false
          debug?: boolean;       // Optional, default: false. When true, enables all console logs for debugging
          locale?: string;       // Optional, locale/language code (e.g., 'en', 'en-US', 'ru', 'zh-CN')
          theme?: 'dark' | 'light' | 'system'; // Optional, theme/color scheme preference (default: 'system')
          allowedOrigins?: string[]; // Optional, restrict message events to specific origins. Empty array allows all origins
          onGetAuthCode?: () => Promise<string>; // Optional, for automatic auth code retrieval
          onGetAuthTokens?: () => Promise<LoginResponse>; // Optional, for direct auth tokens
          onPaymentRequest?: (params: PaymentRequest) => Promise<PaymentResponse>; // Optional, for handling payment requests
        });
        ```

        #### Locale/Language

        Set the locale/language code to pass to the miniapp. The locale will be included in the InitData response.

        ```typescript theme={"system"}
        // Set locale during initialization
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          locale: "en-US"  // or 'ru', 'zh-CN', etc.
        });

        // Or set locale dynamically
        sdk.setLocale("ru");
        ```

        The locale is passed to the miniapp via `InitData.data.locale` on the next `AppBoxoWebAppGetInitData` request.

        **Important Notes:**

        * If you call `setLocale()` after the miniapp has already loaded, the locale will be included in the next InitData request. The miniapp may need to reload or request InitData again to receive the updated locale.
        * To ensure the locale is available immediately, set it during SDK initialization or before calling `mount()`.

        #### Debug Mode

        Control console logging for debugging:

        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          debug: true  // Enable debug mode
        });
        ```

        **About `debug` mode:**

        * `debug: false` (default): No console logs are output. Suitable for production.
        * `debug: true`: All SDK operations are logged to console. Useful for development and troubleshooting.
        * The `debug` option does not affect SDK functionality - it only controls console logging.

        #### Allowed Origins

        Control which origins can send messages to the SDK for security:

        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          allowedOrigins: ["https://miniapp.example.com"]  // Restrict to specific origins
        });
        ```

        **Important Notes:**

        * Empty array `[]` (default): Allows all origins (flexible for different deployment URLs)
        * Set specific origins: Only messages from listed origins will be accepted
        * `allowedOrigins` should be the miniapp's origin (where iframe loads from), NOT `window.location.origin`
      </Accordion>

      <Accordion title="Miniapp Auth Flow">
        Handle authentication between your host app and miniapps. The SDK supports multiple authentication methods:

        **OAuth flow (using auth code):**

        ```typescript theme={"system"}
        // Set auth code explicitly
        const authCode = await fetch('/api/auth-code').then(r => r.json());
        sdk.setAuthCode(authCode);
        ```

        Or provide a callback:

        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          onGetAuthCode: async () => {
            const res = await fetch('/api/generate-auth-code');
            return (await res.json()).auth_code;
          }
        });
        ```

        **Direct auth flow (using tokens):**

        ```typescript theme={"system"}
        // Set tokens directly
        const tokens = await getTokensFromBackend();
        sdk.setAuthTokens(tokens.access_token, tokens.refresh_token);
        ```

        Or use callback:

        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          onGetAuthTokens: async () => {
            const res = await fetch('/api/get-miniapp-tokens');
            const result = await res.json();
            return {
              token: result.access_token,
              refresh_token: result.refresh_token
            };
          }
        });
        ```

        Or register an auth listener:

        ```typescript theme={"system"}
        sdk.onAuth(async () => {
          const response = await fetch('/api/get-miniapp-tokens');
          const tokens = await response.json();
          sdk.setAuthTokens(tokens.access_token, tokens.refresh_token);
        });
        ```

        The SDK will try these in order:

        1. Pre-set tokens (`setAuthTokens`)
        2. Direct auth callback (`onGetAuthTokens`)
        3. OAuth auth code (`setAuthCode` or `onGetAuthCode` callback)
      </Accordion>

      <Accordion title="Payment Processing">
        When a miniapp calls `appboxo.pay()`, the SDK will call your `onPaymentRequest` callback. Process the payment and return the result.

        Payment status values: `'success'`, `'failed'`, or `'cancelled'`.

        ```typescript theme={"system"}
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          onPaymentRequest: async (paymentData) => {
            // Process payment with your backend
            const response = await fetch('/api/payments/process', {
              method: 'POST',
              body: JSON.stringify(paymentData)
            });
            const result = await response.json();
            
            return {
              ...paymentData,
              status: result.status, // 'success', 'failed', or 'cancelled'
              hostappOrderId: result.orderId,
              transactionId: result.transactionId, // optional
            };
          },
        });

        // Optional: listen for payment completion
        sdk.onPaymentComplete((success, data) => {
          if (success) {
            console.log('Payment succeeded:', data);
          }
        });
        ```

        **Important Notes:**

        * When `onPaymentRequest` is set, the SDK automatically tells the miniapp it supports `AppBoxoWebAppPay`, so it can call `appboxo.pay()`.
        * **If `onPaymentRequest` is not configured**, payment requests will fail. Enable `debug: true` to see error messages.
      </Accordion>

      <Accordion title="Dark mode">
        Controls miniapp theming to match your host app's design system or respect user preferences. The theme preference is passed to the miniapp via InitData and the miniapp is automatically notified when the theme changes.

        ```typescript theme={"system"}
        // Set theme during initialization
        const sdk = new AppboxoWebSDK({
          clientId: "your-client-id",
          appId: "your-app-id",
          theme: "dark"  // or 'light', 'system'
        });

        // Or set theme dynamically
        sdk.setTheme("light");
        ```

        **Theme values:**

        * `'dark'`: Force dark mode
        * `'light'`: Force light mode
        * `'system'`: Use system preference (default)

        The theme is passed to the miniapp via `InitData.data.theme` on the next `AppBoxoWebAppGetInitData` request. If you call `setTheme()` after the miniapp has already loaded, the SDK will automatically notify the miniapp about the theme change via `postMessage`, allowing the miniapp to respond immediately without waiting for the next InitData request.

        **Important Notes:**

        * To ensure the theme is available immediately, set it during SDK initialization or before calling `mount()`.
        * The miniapp must implement theme handling logic to receive and apply the theme from `InitData.data.theme`.
      </Accordion>

      <Accordion title="User Logout & Data Clearing">
        When users log out of your host app, you must completely clear all miniapp session data.

        ```typescript theme={"system"}
        sdk.logout();
        ```

        This clears the host app's `localStorage`, `sessionStorage`, and SDK's internal `authCode` and `authTokens`.
      </Accordion>

      <Accordion title="Mount Miniapp">
        The SDK provides a helper method to mount miniapps. The miniapp URL will be automatically fetched from the API:

        ```typescript theme={"system"}
        await sdk.mount({
          container: '#miniapp-container',
          className: 'miniapp-iframe'
        });
        ```

        Or manually set iframe:

        ```typescript theme={"system"}
        const iframe = document.createElement('iframe');
        iframe.src = await sdk.getMiniappUrl();
        document.getElementById('miniapp').appendChild(iframe);

        sdk.setIframe(iframe);
        sdk.initialize();
        ```

        **Styling:**

        When using the `mount` helper, styling is handled via CSS:

        ```css theme={"system"}
        .miniapp-container {
          width: 100%;
          height: 500px;
        }

        .miniapp-iframe {
          width: 100%;
          height: 100%;
          border: none;
        }
        ```
      </Accordion>

      <Accordion title="Retrieve Miniapp List">
        Fetch the complete catalog of available miniapps with detailed metadata.

        ```typescript theme={"system"}
        // Note: This feature may require additional API integration
        // Check SDK documentation for latest implementation
        ```
      </Accordion>

      <Accordion title="Custom Events">
        Establish two-way communication between your host app and miniapps using custom events.

        ```typescript theme={"system"}
        sdk.onEvent('custom_event', (event) => {
          // Handle custom event from miniapp
          console.log('Custom event received:', event);
          
          // Send response back to miniapp if needed
          // (implementation depends on SDK version)
        });
        ```
      </Accordion>

      <Accordion title="Methods">
        | Method                                | Description                                                                 |
        | ------------------------------------- | --------------------------------------------------------------------------- |
        | `setAuthCode(code)`                   | Set authentication code                                                     |
        | `setAuthTokens(token, refreshToken?)` | Set authentication tokens directly                                          |
        | `setLocale(locale)`                   | Set locale/language code (e.g., 'en', 'en-US', 'ru', 'zh-CN')               |
        | `setTheme(theme)`                     | Set theme/color scheme preference ('dark' \| 'light' \| 'system')           |
        | `onAuth(callback)`                    | Register callback for authentication events                                 |
        | `mount(config)`                       | Create iframe and initialize SDK                                            |
        | `getMiniappUrl()`                     | Fetch miniapp URL from API settings endpoint                                |
        | `setIframe(iframe)`                   | Set iframe element manually                                                 |
        | `initialize()`                        | Start listening for events                                                  |
        | `onEvent(type, handler)`              | Register custom event handler                                               |
        | `onLoginComplete(callback)`           | Login completion callback                                                   |
        | `onPaymentComplete(callback)`         | Payment completion callback                                                 |
        | `logout()`                            | Clear host app's localStorage, sessionStorage, and SDK's internal auth data |
        | `destroy()`                           | Clean up resources                                                          |
      </Accordion>

      <Accordion title="Events">
        SDK handles these miniapp events:

        * `AppBoxoWebAppLogin` - User authentication
        * `AppBoxoWebAppPay` - Payment processing
        * `AppBoxoWebAppGetInitData` - Initial data request
        * `AppBoxoWebAppCustomEvent` - Custom events
      </Accordion>

      <Accordion title="Lifecycle Events">
        Track key moments in a miniapp's execution:

        ```typescript theme={"system"}
        // Login completion
        sdk.onLoginComplete((success, data) => {
          if (success) {
            console.log('Login succeeded:', data);
          } else {
            console.log('Login failed:', data);
          }
        });

        // Payment completion
        sdk.onPaymentComplete((success, data) => {
          if (success) {
            console.log('Payment succeeded:', data);
          } else {
            console.log('Payment failed:', data);
          }
        });
        ```
      </Accordion>

      <Accordion title="React Examples">
        ### OAuth Flow Example

        ```tsx theme={"system"}
        import { useEffect, useRef, useState } from "react";
        import { AppboxoWebSDK } from "@appboxo/web-sdk";
        import type { PaymentRequest, PaymentResponse } from "@appboxo/web-sdk";

        function OAuthExample() {
          const containerRef = useRef<HTMLDivElement>(null);
          const sdkRef = useRef<AppboxoWebSDK | null>(null);
          const [isMounted, setIsMounted] = useState(false);

          useEffect(() => {
            const sdk = new AppboxoWebSDK({
              clientId: "your-client-id",
              appId: "your-app-id",
              debug: false,
              allowedOrigins: [], // Empty array allows all origins
              onPaymentRequest: async (paymentData: PaymentRequest): Promise<PaymentResponse> => {
                const response = await fetch('/api/payments/process', {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify(paymentData)
                });
                const result = await response.json();
                
                return {
                  ...paymentData,
                  status: result.status,
                  hostappOrderId: result.hostappOrderId,
                };
              },
            });

            // Set auth code (OAuth flow)
            sdk.setAuthCode("your-auth-code");

            sdk.onLoginComplete((success, data) => {
              console.log('Login:', success ? 'success' : 'failed', data);
            });

            sdk.onPaymentComplete((success, data) => {
              console.log('Payment:', success ? 'success' : 'failed', data);
            });

            sdkRef.current = sdk;

            const mountMiniapp = async () => {
              if (containerRef.current) {
                try {
                  await sdk.mount({
                    container: containerRef.current,
                    className: "miniapp-iframe"
                  });
                  setIsMounted(true);
                } catch (err) {
                  console.error('Failed to mount miniapp:', err);
                }
              }
            };

            mountMiniapp();

            return () => {
              sdk.destroy();
            };
          }, []);

          return (
            <div>
              <div ref={containerRef} style={{ width: '100%', height: '500px' }} />
              <p>Status: {isMounted ? "Mounted" : "Mounting..."}</p>
            </div>
          );
        }
        ```

        ### Direct Auth Flow Example

        ```tsx theme={"system"}
        import { useEffect, useRef, useState } from "react";
        import { AppboxoWebSDK } from "@appboxo/web-sdk";
        import type { PaymentRequest, PaymentResponse } from "@appboxo/web-sdk";

        function DirectAuthExample() {
          const containerRef = useRef<HTMLDivElement>(null);
          const sdkRef = useRef<AppboxoWebSDK | null>(null);
          const [isMounted, setIsMounted] = useState(false);

          useEffect(() => {
            const sdk = new AppboxoWebSDK({
              clientId: "your-client-id",
              appId: "your-app-id",
              debug: false,
              // Alternative: Use onGetAuthTokens callback
              // onGetAuthTokens: async () => {
              //   const response = await fetch('/api/get-miniapp-tokens');
              //   const result = await response.json();
              //   return { token: result.access_token, refresh_token: result.refresh_token };
              // }
            });

            // Direct auth flow - onAuth lifecycle hook
            sdk.onAuth(async () => {
              // Your backend calls Boxo Dashboard connect endpoint to get miniapp tokens
              const response = await fetch('/api/get-miniapp-tokens', {
                headers: { 'Authorization': `Bearer ${yourToken}` }
              });
              const tokens = await response.json();
              sdk.setAuthTokens(tokens.access_token, tokens.refresh_token);
            });

            // Alternative: Pre-set tokens if you already have them
            // const tokens = await getTokensFromBackend();
            // sdk.setAuthTokens(tokens.access_token, tokens.refresh_token);

            sdk.onLoginComplete((success, data) => {
              console.log('Login:', success ? 'success' : 'failed', data);
            });

            sdkRef.current = sdk;

            const mountMiniapp = async () => {
              if (containerRef.current) {
                try {
                  await sdk.mount({
                    container: containerRef.current,
                    className: "miniapp-iframe"
                  });
                  setIsMounted(true);
                } catch (err) {
                  console.error('Failed to mount miniapp:', err);
                }
              }
            };

            mountMiniapp();

            return () => {
              sdk.destroy();
            };
          }, []);

          return (
            <div>
              <div ref={containerRef} style={{ width: '100%', height: '500px' }} />
              <p>Status: {isMounted ? "Mounted" : "Mounting..."}</p>
            </div>
          );
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
