iOS SDK

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.

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:

https://github.com/Appboxo/appboxo-ios-spm.git

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

Then, select Add Package.

CocoaPods installation

Using CocoaPods to create a Podfile if you don’t already have one.

cd your-project-directory
pod init

Add the Boxo pod to your Podfile

pod 'AppBoxoSDK'

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

pod install
open your-project.xcworkspace

Add Usage Descriptions (optional)

  • Add Camera Usage Description in info.plist

    To use camera functionality, you must provide a usage description in your Info.plist. Please add the Privacy - Camera Usage Description (NSCameraUsageDescription) key along with a brief explanation of why your app requires camera access.

  • Add Privacy - Location When In Use Usage Description in info.plist

    To use location functionality, please add the Privacy - Location When In Use Usage Description (NSLocationWhenInUseUsageDescription) key to your Info.plist file. Provide a brief explanation for why your app requires access to location data.

  • Add Privacy - Microphone Usage Description in info.plist

    To use the microphone, you must provide a rationale for its use. Please add the Privacy - Microphone Usage Description (NSMicrophoneUsageDescription) key to your Info.plist file with a brief explanation of why your app requires access to the microphone.

Launch miniapp

Import Boxo SDK in your ViewController:

import AppBoxoSDK 

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

let config = Config(clientId: "client_id")
config.language = "en" // use it to provide language to miniapp. by default 'en'
config.permissionsPage = false // use it to hide "Settings" from Miniapp menu, by default 'true'
config.showClearCache = false // use it to hide "Clear cache" from Miniapp menu, by default 'true'
config.showAboutPage = false // hide/show "About page" on Miniapp menu, by default 'true'
Appboxo.shared.setConfig(config: config)

To launch the miniapp, you will need a UIViewController:

UIKit

To open miniapp write this code in your UIViewController:

let miniapp = Appboxo.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:

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 = Appboxo.shared.getMiniapp(appId: "app_id")
            miniapp.open(viewController: currentViewController)
        }) {
            Text("Open miniapp")
        }
    }
}

Miniapp lifecycle events

Miniapp lifecycle events allow you to monitor key activities, such as onLaunch, onResume, onPause, onClose, and onError. These events help track the miniapp’s behavior throughout its usage lifecycle.

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)")
    }
}

Dark mode

Dark mode support for splash screen and other native components used inside miniapp.

Appboxo.shared.setConfig(config: Config(clientId: "client_id", theme: .Dark)) //[Dark, Light, System] System - by default

Use MiniappConfig to override theme of miniapp.

miniapp.setConfig(config: MiniappConfig(theme: .Dark))

Auth flow

Setup onAuth listener for login event from Miniapp

miniapp.delegate = self
...
extension ViewController : MiniappDelegate {
  func onAuth(miniapp: Miniapp) {
    miniapp.setAuthCode(authCode: "[AUTH_CODE]")
  }
}

Logout to clear mininapp data

When host app user logs out, it is highly important to clear all miniapp storage data. To clear call .logout():

Appboxo.shared.logout()

Miniapp URL listener

To listen for any URL change events, use .setUrlChangeListener:

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)")
        }
    }
}

Append custom params to miniapp URL

To append custom data params to miniapp URL use .params:

let miniapp = Appboxo.shared.getMiniapp(appId: "app_id")
let miniappConfig = MiniappConfig(theme: .System)
// Set params that will be appended to miniapp's url
// Ex. https://google.com/?name=Orave
miniappConfig.setExtraParams(extraParams: ["name" : "Orave"])
miniapp.setConfig(config: miniappConfig)

Custom action menu item

You can add your custom action menu item to existing default action menu item by defining .setCustomActionMenuItemImage

let miniapp = Appboxo.shared.getMiniapp(appId: "app_id")
let miniappConfig = MiniappConfig(theme: .System)
// Set third custom action menu item
// It is hidden by default
miniappConfig.setCustomActionMenuItemImage(image: UIImage(named: "ic_custom_action_button"))
miniapp.setConfig(config: miniappConfig)
...
extension ViewController : MiniappDelegate {
    func didSelectCustomActionMenuItemEvent(miniapp: Miniapp) {
        //show any custom dialog when custom action menu item is clicked
    }
}

To show/hide custom action menu item use miniapp.showCustomActionMenuItem() and miniapp.hideCustomActionMenuItem()

Get list of miniapps

Appboxo.shared.getMiniapps { miniapps, error in
    miniapps.forEach { data in
        print(data.appId)
        print(data.name)
        print(data.longDescription)
        print(data.logo)
        print(data.category)
    }
}
let config = Config(clientId: "CLIENT_ID")
config.setUserId(id: "HOST_APP_USER_ID") //will be used for the consent screen
Appboxo.shared.setConfig(config: config)

To skip miniapp splash screen

let miniapp = Appboxo.shared.getMiniapp(appId: "app_id")
            
let miniappConfig = MiniappConfig()
miniappConfig.enableSplash(isSplashEnabled: false) // 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.
miniapp.setConfig(config: miniappConfig)

miniapp.open(viewController: self)

Sandbox mode

sandboxMode: it should open miniapps in “Approved” and “InTesting” statuses List of miniapps returns:

  • when true, miniapps in “Approved” and “InTesting” statuses
  • when false, miniapps only in “Approved” status
let config = Config(clientId: "CLIENT_ID")
config.sandboxMode = true //by default false
Appboxo.shared.setConfig(config: config)

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.

let config = MiniappConfig()
config.pageAnimation = PageAnimation.RIGHT_TO_LEFT

let miniapp = Appboxo.shared.getMiniapp(appId: "app_id")
miniapp.setConfig(config: config)
miniapp.open(viewController: self)

SDK size

  • BoxoSDK - 5.9 MB

Android SDK

Please see our sample Android app to learn more.

Compatibility

Your project must target at least Android 5.0 (API level 21) or higher.

Installation

Latest version: Link

To install Boxo SDK, add com.appboxo:sdk to the dependencies block of your app/build.gradle file:

app/build.gradle.kts
...
dependencies {
	implementation("com.appboxo:sdk:1.x.x")
}

Add it in your settings.gradle.kts at the end of repositories:

settings.gradle.kts
...
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ..
        maven { setUrl("https://jitpack.io") }
        maven {
            setUrl("https://maven.pkg.github.com/Appboxo/android-sdk-packages")
            credentials {
                username = "appboxoandroidsdk"
                password =
                    "\u0037\u0039\u0064\u0031\u0065\u0064\u0061\u0036\u0030\u0034\u0063\u0061\u0031\u0066\u0030\u0032\u0066\u0031\u0037\u0066\u0032\u0061\u0039\u0033\u0064\u0035\u0039\u0039\u0061\u0035\u0035\u0062\u0066\u0065\u0031\u0064\u0066\u0064\u0038\u0038"
            }
        }
    }
}

Add this line to root gradle.properties:

android.enableJetifier=true

Launch miniapp

  1. Add to your existing Application class or create a new one if you don’t have an Application class yet.

    MyApplication.kt
    import android.app.Application
    import com.appboxo.sdk.Appboxo
    import com.appboxo.sdk.Config
    
    class MyApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            Appboxo.init(this)
                .setConfig(
                    Config.Builder()
                        .setClientId("client_id")
                        .build()
                )
        }
    }
    
  2. Then register it in AndroidManifest.xml:

    <application
    	android:name=".MyApplication"
    	...>
    
  3. Open miniapp

    val miniapp = Appboxo.getMiniapp(appId)
    miniapp.open(context)
    
MainActivity.kt
package io.boxo.launchminiapp

import android.os.Bundle
import androidx.activity.ComponentActivity
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 com.appboxo.launchminiapp.ui.theme.LaunchminiappTheme
import com.appboxo.sdk.Appboxo

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

@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 = {}
        )
    }
}

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’

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

System Behavior

Appboxo.setConfig(
    Config.Builder()
        .multitaskMode(false)
        .debug(BuildConfig.DEBUG)
        .build()
    )
ParameterTypeDescriptionDefault
multitaskModeBooleanShows Miniapps in Android Recents screen when truefalse
debugBooleanEnables WebView debugging (Chrome DevTools)false

Miniapp Menu Customization

Appboxo.setConfig(
    Config.Builder()
        .permissionsPage(false)  // Hide "Settings"
        .showClearCache(false)   // Hide "Clear Cache"
        .showAboutPage(true)    // Show "About"
        .build()
    )
ParameterDescriptionDefault
permissionsPageSetting menu itemtrue
showClearCacheClear Cache menu itemtrue
showAboutPageAbout Miniapp menu itemtrue

Sandbox Mode Configuration

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

Appboxo.setConfig(
    Config.Builder()
        .sandboxMode(true)  // Enable sandbox mode
        .build()
)

Behavior: Retrieve Miniapp List will return miniapps with the statuses listed below.

Sandbox ModeAvailable Miniapp StatusesUse Case
trueApproved + InTestingDevelopment environment - access to miniapps still in testing
falseApproved onlyProduction 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:

OptionDescription
SYSTEMAutomatically matches device theme
LIGHTForces light theme
DARKForces dark theme

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

Global Theme (Affects all miniapps)

Appboxo.setConfig(Config.Builder()
    ...
	.setTheme(Config.Theme.SYSTEM)  // DEFAULT: Follows system setting
    .build())

Per-Miniapp Theme Override

// Override theme for specific miniapp
Appboxo.getMiniapp(appId)
    .setConfig(MiniappConfig.Builder()
        .setTheme(Config.Theme.LIGHT)  // Overrides global theme
        .build())
    .open()

Miniapp Auth Flow

Handle authentication between your host app and miniapps:

miniapp.setAuthListener { appboxoActivity, miniapp ->
	// 1. Fetch auth code from your backend
    val authCode = fetchAuthCodeFromBackend()

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

User Logout & Data Clearing

When users log out of your host app, you must completely clear all miniapp session data

Appboxo.logout()

Miniapp URL Change Listener

To listen for any URL change events use .setUrlChangeListener:

Appboxo.getMiniapp(appId)
    .setUrlChangeListener { appboxoActivity, miniapp, uri ->
        Log.e("URL Path", uri.path)
        uri.queryParameterNames.forEach {
            Log.e("URL params", "$it = ${uri.getQueryParameter(it)}")
        }
    }
    .open(this)

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

Appboxo.getMiniapp(appId)
    .setConfig(
        MiniappConfig.Builder()
            .setExtraUrlParams(
                mapOf(
                    "user_id" to "u_12345",
                    "campaign" to "summer_sale"
                )
            )
            .build()
    )
    .open(this)

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

https://miniapp.example.com?user_id=u_12345&campaign=summer_sale

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
miniapp.setCustomEventListener { activity, 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)
}

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
Appboxo.getMiniapp(appId)
    .setConfig(
        MiniappConfig.Builder()
            .setCustomActionMenuItem(R.drawable.ic_custom_menu)
            .build()
    )
    .setCustomActionMenuItemClickListener { appboxoActivity, miniapp ->
        // do something
    }
    .open(this)

Control Visibility:

// Hide the item
miniapp.hideCustomActionMenuItem()

// Show when needed
miniapp.showCustomActionMenuItem()

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
Appboxo.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)
                }
            }
        })

Splash Screen Configuration

Control the miniapp loading experience by customizing splash screen behavior. By default, miniapps display a splash screen that automatically hides when 50% of web content has loaded.

Appboxo.getMiniapp(appId)
    .setConfig(
        MiniappConfig.Builder()
            .enableSplash(false)  // Skip splash screen entirely
            .build()
    )
    .open(this)

Page Animation Configuration

Important: Animations will only work if multitaskMode is set tofalse. Make sure to configure it accordingly to enable page transition animations.

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.

Appboxo.getMiniapp(appId)
    .setConfig(
        MiniappConfig.Builder()
            ...
			// Set the page animation to slide from right to left
            .pageAnimation(PageAnimation.RIGHT_TO_LEFT)
            .build()
    )
    .open(requireActivity())

Miniapp Lifecycle Events

Track key moments in a miniapp’s execution by implementing the LifecycleListener. These events help you monitor user interactions and manage app state transitions.

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 on every user touch event
        // Useful for implementing custom idle timeouts
    }
})

Flutter SDK

A Flutter plugin to integrate Boxo for iOS and Android. Please see our sample Flutter app to learn more.

Installation

Run this command: With Flutter:

flutter pub add appboxo_sdk

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

dependencies: appboxo_sdk: ^0.7.0

Add this line to android/gradle.properties

  android.enableJetifier=true

Launch Miniapp

import 'package:appboxo_sdk/appboxo_sdk.dart';
Appboxo.setConfig( clientId: '[client_id]');
Appboxo.openMiniapp(appId );

Set Config

import 'package:appboxo_sdk/appboxo_sdk.dart';

Appboxo.setConfig(
    clientId: '[client_id]', // your Appboxo 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'
    multitaskMode: true, // (optional) 'multitaskMode' works only on Android. By default 'true', each miniapp appears as a task in the Recents screen.
    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'
);

Appboxo.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.
);

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

Appboxo.logout(); //On logout from your app, call it to clear all miniapps data.

Sandbox mode

sandboxMode: it should open miniapps in “Approved” and “InTesting” statuses List of miniapps returns:

  • when true, miniapps in “Approved” and “InTesting” statuses
  • when false, miniapps only in “Approved” status

Get list of miniapps

Appboxo.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}');
});

Appboxo.getMiniapps();

To listen miniapp lifecycle events:

import 'package:flutter/material.dart';
import 'package:appboxo_sdk/appboxo_sdk.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 = Appboxo.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}');
            Appboxo.setAuthCode(appId, "");
          } else {
            Appboxo.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');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Appboxo SDK Test'),
        ),
        body: Center(
          child: MaterialButton(
            onPressed: () {
              Appboxo.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,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

React Native SDK

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

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

Launch Miniapp

import appboxo from '@appboxo/react-native-sdk';
Appboxo.setConfig( clientId );
Appboxo.openMiniapp( appId );

Usage:

import React from 'react';
import appboxo from '@appboxo/react-native-sdk';
import { StyleSheet, View, Button } from 'react-native';

export default function App() {

  React.useEffect(() => {
    appboxo.setConfig(
      '[client_id]', { // your Appboxo client_id
        userId: [hostapp_user_id], // will be used for the consent screen
        language: 'en', // to provide language to miniapp. by default 'en'
        enableMultitaskMode: true, // (optional) 'multitaskMode' works only on Android. By default 'true', each miniapp appears as a task in the Recents screen.
        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'
      }
    );
  }, [])

  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)
    }
    appboxo.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',
  },
});

Miniapp lifecycle events

Important Miniapp lifecycle events available in 1.0.8+ versions

import React from 'react';
import appboxo from '@appboxo/react-native-sdk';
import { StyleSheet, View, Button } from 'react-native';

export default function App() {

  React.useEffect(() => {
    appboxo.setConfig('[client_id]', false); //set your Appboxo client id
    
    const subscription = appboxo.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 or when destroyed miniapp activity
      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
    });

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

  const handleOpenMiniapp = () => {
    appboxo.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',
  },
});

Append custom params to miniapp URL

Important Custom params available in 1.0.26+ versions

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

const options = {
  extraUrlParams: {param: 'test'}  // (optional) extra query params to append to miniapp URL (like: http://miniapp-url.com/?param=test)
}
appboxo.openMiniapp(
  '[miniapp_id]',           // miniapp ID to be launched
  options                   // (optional) options
);

Sandbox mode

sandboxMode: it should open miniapps in “Approved” and “InTesting” statuses List of miniapps returns:

  • when true, miniapps in “Approved” and “InTesting” statuses
  • when false, miniapps only in “Approved” status

Get list of miniapps

React.useEffect(() => {
    const miniappListSubscription = appboxosdk.miniapps.subscribe((miniapps: MiniappData[]) => {
            setMiniapps(miniapps);
        }, (error) => {
            console.log(error)
        },
        );
    appboxosdk.getMiniapps();
    return () => miniappListSubscription();
  }, [])

Capacitor

Installation

npm install @appboxo/capacitor-boxo-sdk
npx cap sync

Launch Miniapp

import { Appboxo } from 'capacitor-boxo-sdk';
Appboxo.setConfig({  clientId: clientId });
Appboxo.openMiniapp({ appId: appId });

Example:

<!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>
js/example.js
import { Appboxo } from 'capacitor-boxo-sdk';

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

Appboxo.setConfig({
  clientId: clientId
});

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

Set Config

setConfig(options: ConfigOptions) => Promise<void>

Config Options

PropTypeDescription
clientIdstringyour client id from dashboard
userIdstring(optional) hostapp userId, will be used for the Consent Management
languagestringlanguage value will be passed to the miniapp
sandboxModebooleanswitch to sandbox mode
enableMultitaskModeboolean(Android only) Each miniapp appears as a task in the Recents screen.
theme’light’ | ‘dark’ | ‘system’theme for splash screen and other native components used inside miniapp.
isDebugbooleanenables webview debugging
showPermissionsPagebooleanuse it to hide “Settings” from Miniapp menu
showClearCachebooleanuse it to hide “Clear cache” from Miniapp menu
showAboutPagebooleanuse it to hide “About Page” from Miniapp menu
miniappSettingsExpirationTimenumberuse it to change miniapp settings cache time in sec. Default: 60 sec

Miniapp Control

Open

openMiniapp(options: OpenMiniappOptions) => Promise<void>

Open miniapp with options

OpenMiniappOptions

PropTypeDescription
appIdstringminiapp id
dataobject(optional) data as Map that is sent to miniapp
theme’light’ | ‘dark’ | ‘system’(optional) miniapp theme “dark” | “light” (by default is system theme)
extraUrlParamsobject(optional) extra query params to append to miniapp URL (like: http://miniapp-url.com/?param=test)
urlSuffixstring(optional) suffix to append to miniapp URL (like: http://miniapp-url.com/?param=test)
colorsColorOptions(optional) provide colors to miniapp if miniapp supports
enableSplashboolean(optional) use to skip miniapp splash screen
saveStateboolean(optional) use to save state on close miniapp

ColorOptions

PropType
primaryColorstring
secondaryColorstring
tertiaryColorstring

Close

closeMiniapp(options: { appId: string; }) => Promise<void>

close miniapp by appId

Hide

hideMiniapps() => Promise<void>

Miniapp opens on a native screen. To show payment processing page need to hide miniapp screen. To use this function need to enable ‘enableMultitaskMode: true’ in Appboxo.setConfigs()

Miniapp Auth Flow

Handle authentication between your host app and miniapps:

 setAuthCode(options: { appId: string; authCode: string; }) => Promise<void>

User Logout & Data Clearing

When users log out of your host app, you must completely clear all miniapp session data

logout() => Promise<void>

Retrieve Miniapp List

getMiniapps() => Promise<MiniappListResult>

Get list of miniapps

MiniappListResult

PropType
miniapps[MiniappData]
errorstring

MiniappData

PropType
appIdstring
namestring
categorystring
descriptionstring
logostring

Miniapp Custom Events

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.

ParamType
eventName’custom_event’
listenerFunc(customEvent: CustomEvent) => void
sendCustomEvent(customEvent: CustomEvent) => Promise<void>

send custom event data to miniapp

PropType
appIdstring
requestIdnumber
typestring
errorTypestring
payloadobject

Miniapp Payment Events

addListener(eventName: 'payment_event', listenerFunc: (paymentEvent: PaymentEvent) => void) => Promise<PluginListenerHandle>
ParamType
eventName’payment_event’
listenerFunc(paymentEvent: PaymentEvent) => void
sendPaymentEvent(paymentEvent: PaymentEvent) => Promise<void>

send payment data to miniapp

PropType
appIdstring
transactionTokenstring
miniappOrderIdstring
amountnumber
currencystring
statusstring
hostappOrderIdstring
extraParamsobject

Miniapp Lifecycle Events

addListener(eventName: 'miniapp_lifecycle', listenerFunc: (lifecycle: LifecycleEvent) => void) => Promise<PluginListenerHandle>
ParamType
eventName’miniapp_lifecycle’
listenerFunc(lifecycle: LifecycleEvent) => void

LifecycleEvent

PropType
appIdstring
lifecyclestring
errorstring

onLaunch - Called when the miniapp will launch with Appboxo.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 touch event is dispatched to the miniapp page. onAuth - Called when the miniapp starts login and user allows it

Expo

Expo plugin to integrate Boxo for iOS and Android. Please see our sample Expo app to learn more.

Installation

npm install @appboxo/expo-boxo-sdk

Configuration in app.json/app.config.js

{
  "expo": {
    "plugins": [
      ["@appboxo/expo-boxo-sdk"]
    ]
  }
}

Launch Miniapp

import * as Boxo from 'expo-boxo-sdk';
Boxo.setConfig({  clientId: clientId });
Boxo.openMiniapp({ appId: appId });

Set Config

setConfig(options: ConfigOptions)

ConfigOptions

PropTypeDescription
clientIdstringyour client id from dashboard
userIdstring(optional) hostapp userId, will be used for the Consent Management
languagestringlanguage value will be passed to the miniapp
sandboxModebooleanswitch to sandbox mode
enableMultitaskModeboolean(Android only) Each miniapp appears as a task in the Recents screen.
theme’light’ | ‘dark’ | ‘system’theme for splash screen and other native components used inside miniapp.
isDebugbooleanenables webview debugging
showPermissionsPagebooleanuse it to hide “Settings” from Miniapp menu
showClearCachebooleanuse it to hide “Clear cache” from Miniapp menu
showAboutPagebooleanuse it to hide “About Page” from Miniapp menu
miniappSettingsExpirationTimenumberuse it to change miniapp settings cache time in sec. Default: 60 sec

Miniapp Control

Open

openMiniapp(options: MiniappOptions)

Open miniapp with options

MiniappOptions

PropTypeDescription
appIdstringminiapp id
dataobject(optional) data as Map that is sent to miniapp
theme’light’ | ‘dark’ | ‘system’(optional) miniapp theme “dark” | “light” (by default is system theme)
extraUrlParamsobject(optional) extra query params to append to miniapp URL (like: http://miniapp-url.com/?param=test)
urlSuffixstring(optional) suffix to append to miniapp URL (like: http://miniapp-url.com/?param=test)
colorsColorOptions(optional) provide colors to miniapp if miniapp supports
enableSplashboolean(optional) use to skip miniapp splash screen
saveStateboolean(optional) use to save state on close miniapp

ColorOptions

PropType
primaryColorstring
secondaryColorstring
tertiaryColorstring

Close

closeMiniapp(appId: string)

close miniapp by appId

Hide

hideMiniapps()

Miniapp opens on a native screen. To show payment processing page need to hide miniapp screen. To use this function need to enable ‘enableMultitaskMode: true’ in Appboxo.setConfigs()

Miniapp Auth Flow

Handle authentication between your host app and miniapps:

Boxo.addAuthListener((authEvent) => {
    Boxo.setAuthCode(authEvent.appId, authCode)
});

User Logout & Data Clearing

When users log out of your host app, you must completely clear all miniapp session data

logout()

Retrieve Miniapp List

Boxo.addMiniappListListener((result) => {
  console.log(result.miniapps);
});

Get list of miniapps

MiniappListResult

PropType
miniapps[MiniappData]
errorstring

MiniappData

PropType
appIdstring
namestring
categorystring
descriptionstring
logostring

Miniapp Custom Events

Boxo.addCustomEventListener((customEvent) => {
  ..handle custom event
  Boxo.sendCustomEvent(customEvent);
});

Send custom event data to miniapp

PropType
appIdstring
requestIdnumber
typestring
errorTypestring
payloadobject

Miniapp Payment Events

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

PropType
appIdstring
transactionTokenstring
miniappOrderIdstring
amountnumber
currencystring
statusstring
hostappOrderIdstring
extraParamsobject

Miniapp Lifecycle Events

Boxo.addMiniappLifecycleListener((lifecycleData) => {
  console.log(lifecycleData);
});

LifecycleEvent

PropType
appIdstring
lifecyclestring
errorstring

onLaunch - Called when the miniapp will launch with Appboxo.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 touch event is dispatched to the miniapp page. onAuth - Called when the miniapp starts login and user allows it