Handle custom event from miniapp.

The custom events system is a powerful feature that enables bidirectional data communication between a miniapp and the host app. The miniapp can send data that the host app can recognize. Additionally, certain operations can be implemented at the native app level for enhanced functionality.

Custom events example

iOS

miniapp.delegate = self
...
extension ViewController : MiniappDelegate {
    func didReceiveCustomEvent(miniapp: Miniapp, customEvent: CustomEvent) {
        customEvent.payload = [
            "message" : "text",
            "id" : 123,
            "checked" : true
        ]
        miniapp.sendCustomEvent(customEvent: customEvent)
    }
}

Android

miniApp.setCustomEventListener { miniAppActivity, miniApp, customEvent ->
    //doSomething
    customEvent.payload = mapOf("message" to "text",
                                "id" to 123,
                                "checked" to true)
    miniApp.sendEvent(customEvent)
}

java

miniApp.setCustomEventListener(new MiniApp.CustomEventListener() {
    @Override
    public void handle(@NotNull Activity miniAppActivity, @NotNull MiniApp miniApp, @NotNull CustomEvent customEvent) {
        Map<String, Object> payload = new HashMap<>();
        payload.put("message", "message");
        payload.put("id", 123);
        payload.put("checked", true);
        customEvent.setPayload(payload);
        miniApp.sendEvent(customEvent);
    }
});

Flutter

Handle custom events by listening to .customEvents().

Example receiving and sending back same event:

Appboxo.customEvents().listen((CustomEvent event) {
  if (event.appId == 'app123456') {
    event.payload = {"foo": "bar"};
    Appboxo.sendEvent(event);
  }
});

For cases when you want to hide all miniapps when a custom event is received, you can call Appboxo.hideMiniapps();

Example:

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> {
  @override
  void initState() {
    super.initState();
    Appboxo.setConfig("CLIENT_ID");
    Appboxo.customEvents().listen((CustomEvent event) {
      if (event.appId == 'app123456') {
        Appboxo.hideMiniapps();
        Future.delayed(const Duration(milliseconds: 2000), () {
          Appboxo.openMiniapp("app123456", "");
          event.payload = {"complete": "ok"};
          Appboxo.sendEvent(event);
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Appboxo SDK Test'),
        ),
        body: Center(
          child: RaisedButton(
            onPressed: () {
              Appboxo.openMiniapp("app123456", "");
            },
            child: Text("Miniapp"),
          ),
        ),
      ),
    );
  }
}

React Native

Handling custom events in React Native is straightforward. Use customEvents to both subscribe to and send custom events between the miniapp and the host app.

Example:

   appboxo.customEvents
      .subscribe<'eventType', { payloadKey: 'payloadData' }>(event => {
        const modifiedEvent = {
          app_id: '[miniap_id]', // miniapp id
          custom_event: {
            error_type: undefined, // throw the error with non empty 'error_type'
            payload: {payloadKey: 'payloadData'}, // payload data to send to miniapp
            request_id: '1', // event requet id
            type: 'eventType', // event type
          },
        }
        appboxo.customEvents.send(modifiedEvent) // your data that you want to send back to miniapp
      })

TIP

Please don’t forget to unsubscribe from events

Usage:

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

type eventType = 'eventType';
type eventPayload = { payloadKey: 'payload' };

export default function App() {

  React.useEffect(() => {
    appboxo.setConfig('[client_id]');  //set your Appboxo client_id

    const eventPayloadData = { payloadKey: 'payload' };

    const subscription = appboxo.customEvents
      .subscribe<eventType, eventPayload>( //listen custom event from miniapp
        event => {
          const modifiedEvent = {
            app_id: '[miniap_id]', // miniapp id
            custom_event: {
              request_id: event.custom_event.request_id, // event requet id
              payload: eventPayloadData, // payload data to send to miniapp
              type: eventType, // event type
            },
          };
          appboxo.customEvents.send(modifiedEvent); //send custom event to miniapp
        },
        (errorType?: string) => {
          console.error(errorType || 'Something went wrong!'); //handle error
        }     
      );

    return () => subscription(); //unsubscribe from custom events

  }, []);

  const handleOpenMiniapp = () => {
    appboxo.openMiniapp('[miniapp_id]', '[auth_payload]');  //launch miniapp by id with auth payload
  }

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

Boxo Event Bridge


Introduction

Boxo Event Bridge is a bidirectional communication functionality that enables host apps and miniapps to exchange events and information seamlessly within the Boxo ecosystem.

Event Bridge flow

Here is a diagram illustrating the event communication process between a miniapp and a host app.

  1. An app (either hostapp or miniapp) creates an event with a specific event type and payload
  2. The app sends the event to the Boxo Platform via the Event Bridge API
  3. The Boxo Platform validates the event and authenticates the sender
  4. The Boxo Platform forwards the event to the recipient’s event receiver URL
  5. The recipient processes the event and returns a response
  6. The Boxo Platform captures the response and forwards it to the original sender
  7. The original sender receives the response and can take appropriate actions

Setting up the backend

*Note: Feature must be enabled in Dashboard Partnership

Data format

JSON is used for data exchange. Event payloads can contain any valid JSON structure that both the sender and receiver agree upon.

1. “Event Receiver” Endpoint

This endpoint allows your app to receive events from the Boxo Platform.

URL and METHOD:

This endpoint must handle a HTTPS POST request URL to endpoint must be provided in Dashboard

Headers:

KeyValue
Authorization<prefix> <base64 encoded(hostapp_client_id:hostapp_secret_key)>
Content-typeapplication/json
  • Default <prefix>: Token. Access token prefix can be set in Boxo Connect.
  • hostapp_client_id and hostapp_secret_key must be provided in Dashboard

Body

FieldData typeDescription
app_idStringMiniapp identifier
client_idStringHostapp identifier
event_typeStringEvent type identifying the purpose of the event
payloadObjectEvent data containing information specific to the event

Response:

  • Response status must be 200 in all cases
  • Response body can contain any valid JSON that will be forwarded to the event sender

Request Example:

curl --location --request POST '[YOUR_SERVER_URL]/api/event-receiver/'\
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {{BASE64_ENCODED_CLIENT_ID_AND_CLIENT_SECRET}}' \
--data-raw '{
    "app_id": "{{MINIAPP_ID}}",
    "client_id": "{{CLIENT_ID}}",
    "event_type": "user_profile_updated",
    "payload": {
        "user_id": "user123",
        "name": "John Doe",
        "email": "john@example.com"
    }
}'

2. Sending Events API

This endpoint allows your app to send events to miniapps through the Boxo Platform.

URL and METHOD

This is HTTPS POST /api/v1/event-bridge/hostapp/ endpoint

Headers

KeyValue
Authorization<prefix> <base64 encoded(hostapp_client_id:hostapp_secret_key)>
Content-typeapplication/json
  • Default <prefix>: Token. Access token prefix can be set in Boxo Connect.
  • hostapp_client_id and hostapp_secret_key must be provided in Dashboard

Body

FieldData typeDescription
app_idStringMiniapp identifier (recipient)
client_idStringHostapp identifier (sender)
event_typeStringEvent type identifying the purpose of the event
payloadObjectEvent data containing information specific to the event

Response

  • Response status will be 200 if the event was delivered successfully
  • Response body will contain the response from the miniapp’s event receiver endpoint

Request Example

curl --location --request POST 'https://api.boxo.io/api/v1/event-bridge/hostapp/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {{BASE64_ENCODED_CLIENT_ID_AND_CLIENT_SECRET}}' \
--data-raw '{
    "app_id": "{{MINIAPP_ID}}",
    "client_id": "{{CLIENT_ID}}",
    "event_type": "payment_completed",
    "payload": {
        "transaction_id": "tx_12345",
        "amount": 100.50,
        "currency": "USD",
        "status": "completed"
    }
}'

Common Event Types

Here are some common event types that can be used for communication between host apps and miniapps:

Host App to Miniapp Events

Event TypeDescriptionExample Payload
user_profile_updatedUser profile information has been updated{"user_id": "123", "updated_fields": ["email"]}
payment_completedA payment has been processed successfully{"transaction_id": "tx_123", "amount": 100.50}
location_updatedUser’s location has been updated{"latitude": 37.7749, "longitude": -122.4194}
app_state_changeThe state of the host app has changed{"new_state": "background", "timestamp": 123456}

Miniapp to Host App Events

Event TypeDescriptionExample Payload
order_createdA new order has been created in the miniapp{"order_id": "ord_123", "amount": 50.25}
product_viewedUser has viewed a product in the miniapp{"product_id": "prod_123", "category": "shoes"}
cart_updatedUser’s shopping cart has been updated{"cart_id": "cart_123", "item_count": 3}
content_sharedUser has shared content from the miniapp{"content_id": "cont_123", "content_type": "image"}

Error Handling

If an error occurs during event processing, the Boxo Platform will return an appropriate error response:

Error CodeDescription
EVENT_RECEIVER_DISABLEDEvent receiver is not enabled for the recipient
INVALID_EVENT_DATAThe event data format is invalid
EVENT_DELIVERY_FAILEDFailed to deliver the event to the recipient
UNAUTHORIZEDSender is not authorized to send events

Best Practices

  1. Event Types: Use consistent event types that clearly indicate the purpose of the event
  2. Minimal Payloads: Keep event payloads as small as possible, including only necessary information
  3. Error Handling: Implement proper error handling for event processing failures
  4. Idempotency: Design event handlers to be idempotent to handle potential duplicate events
  5. Timeouts: Implement reasonable timeouts for event processing to avoid blocking operations

By following these guidelines, you can create a robust event-driven communication system between your host app and miniapps using Boxo Event Bridge.

Handle custom event from miniapp.

The custom events system is a powerful feature that enables bidirectional data communication between a miniapp and the host app. The miniapp can send data that the host app can recognize. Additionally, certain operations can be implemented at the native app level for enhanced functionality.

Custom events example

iOS

miniapp.delegate = self
...
extension ViewController : MiniappDelegate {
    func didReceiveCustomEvent(miniapp: Miniapp, customEvent: CustomEvent) {
        customEvent.payload = [
            "message" : "text",
            "id" : 123,
            "checked" : true
        ]
        miniapp.sendCustomEvent(customEvent: customEvent)
    }
}

Android

miniApp.setCustomEventListener { miniAppActivity, miniApp, customEvent ->
    //doSomething
    customEvent.payload = mapOf("message" to "text",
                                "id" to 123,
                                "checked" to true)
    miniApp.sendEvent(customEvent)
}

java

miniApp.setCustomEventListener(new MiniApp.CustomEventListener() {
    @Override
    public void handle(@NotNull Activity miniAppActivity, @NotNull MiniApp miniApp, @NotNull CustomEvent customEvent) {
        Map<String, Object> payload = new HashMap<>();
        payload.put("message", "message");
        payload.put("id", 123);
        payload.put("checked", true);
        customEvent.setPayload(payload);
        miniApp.sendEvent(customEvent);
    }
});

Flutter

Handle custom events by listening to .customEvents().

Example receiving and sending back same event:

Appboxo.customEvents().listen((CustomEvent event) {
  if (event.appId == 'app123456') {
    event.payload = {"foo": "bar"};
    Appboxo.sendEvent(event);
  }
});

For cases when you want to hide all miniapps when a custom event is received, you can call Appboxo.hideMiniapps();

Example:

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> {
  @override
  void initState() {
    super.initState();
    Appboxo.setConfig("CLIENT_ID");
    Appboxo.customEvents().listen((CustomEvent event) {
      if (event.appId == 'app123456') {
        Appboxo.hideMiniapps();
        Future.delayed(const Duration(milliseconds: 2000), () {
          Appboxo.openMiniapp("app123456", "");
          event.payload = {"complete": "ok"};
          Appboxo.sendEvent(event);
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Appboxo SDK Test'),
        ),
        body: Center(
          child: RaisedButton(
            onPressed: () {
              Appboxo.openMiniapp("app123456", "");
            },
            child: Text("Miniapp"),
          ),
        ),
      ),
    );
  }
}

React Native

Handling custom events in React Native is straightforward. Use customEvents to both subscribe to and send custom events between the miniapp and the host app.

Example:

   appboxo.customEvents
      .subscribe<'eventType', { payloadKey: 'payloadData' }>(event => {
        const modifiedEvent = {
          app_id: '[miniap_id]', // miniapp id
          custom_event: {
            error_type: undefined, // throw the error with non empty 'error_type'
            payload: {payloadKey: 'payloadData'}, // payload data to send to miniapp
            request_id: '1', // event requet id
            type: 'eventType', // event type
          },
        }
        appboxo.customEvents.send(modifiedEvent) // your data that you want to send back to miniapp
      })

TIP

Please don’t forget to unsubscribe from events

Usage:

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

type eventType = 'eventType';
type eventPayload = { payloadKey: 'payload' };

export default function App() {

  React.useEffect(() => {
    appboxo.setConfig('[client_id]');  //set your Appboxo client_id

    const eventPayloadData = { payloadKey: 'payload' };

    const subscription = appboxo.customEvents
      .subscribe<eventType, eventPayload>( //listen custom event from miniapp
        event => {
          const modifiedEvent = {
            app_id: '[miniap_id]', // miniapp id
            custom_event: {
              request_id: event.custom_event.request_id, // event requet id
              payload: eventPayloadData, // payload data to send to miniapp
              type: eventType, // event type
            },
          };
          appboxo.customEvents.send(modifiedEvent); //send custom event to miniapp
        },
        (errorType?: string) => {
          console.error(errorType || 'Something went wrong!'); //handle error
        }     
      );

    return () => subscription(); //unsubscribe from custom events

  }, []);

  const handleOpenMiniapp = () => {
    appboxo.openMiniapp('[miniapp_id]', '[auth_payload]');  //launch miniapp by id with auth payload
  }

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

Boxo Event Bridge


Introduction

Boxo Event Bridge is a bidirectional communication functionality that enables host apps and miniapps to exchange events and information seamlessly within the Boxo ecosystem.

Event Bridge flow

Here is a diagram illustrating the event communication process between a miniapp and a host app.

  1. An app (either hostapp or miniapp) creates an event with a specific event type and payload
  2. The app sends the event to the Boxo Platform via the Event Bridge API
  3. The Boxo Platform validates the event and authenticates the sender
  4. The Boxo Platform forwards the event to the recipient’s event receiver URL
  5. The recipient processes the event and returns a response
  6. The Boxo Platform captures the response and forwards it to the original sender
  7. The original sender receives the response and can take appropriate actions

Setting up the backend

*Note: Feature must be enabled in Dashboard Partnership

Data format

JSON is used for data exchange. Event payloads can contain any valid JSON structure that both the sender and receiver agree upon.

1. “Event Receiver” Endpoint

This endpoint allows your app to receive events from the Boxo Platform.

URL and METHOD:

This endpoint must handle a HTTPS POST request URL to endpoint must be provided in Dashboard

Headers:

KeyValue
Authorization<prefix> <base64 encoded(hostapp_client_id:hostapp_secret_key)>
Content-typeapplication/json
  • Default <prefix>: Token. Access token prefix can be set in Boxo Connect.
  • hostapp_client_id and hostapp_secret_key must be provided in Dashboard

Body

FieldData typeDescription
app_idStringMiniapp identifier
client_idStringHostapp identifier
event_typeStringEvent type identifying the purpose of the event
payloadObjectEvent data containing information specific to the event

Response:

  • Response status must be 200 in all cases
  • Response body can contain any valid JSON that will be forwarded to the event sender

Request Example:

curl --location --request POST '[YOUR_SERVER_URL]/api/event-receiver/'\
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {{BASE64_ENCODED_CLIENT_ID_AND_CLIENT_SECRET}}' \
--data-raw '{
    "app_id": "{{MINIAPP_ID}}",
    "client_id": "{{CLIENT_ID}}",
    "event_type": "user_profile_updated",
    "payload": {
        "user_id": "user123",
        "name": "John Doe",
        "email": "john@example.com"
    }
}'

2. Sending Events API

This endpoint allows your app to send events to miniapps through the Boxo Platform.

URL and METHOD

This is HTTPS POST /api/v1/event-bridge/hostapp/ endpoint

Headers

KeyValue
Authorization<prefix> <base64 encoded(hostapp_client_id:hostapp_secret_key)>
Content-typeapplication/json
  • Default <prefix>: Token. Access token prefix can be set in Boxo Connect.
  • hostapp_client_id and hostapp_secret_key must be provided in Dashboard

Body

FieldData typeDescription
app_idStringMiniapp identifier (recipient)
client_idStringHostapp identifier (sender)
event_typeStringEvent type identifying the purpose of the event
payloadObjectEvent data containing information specific to the event

Response

  • Response status will be 200 if the event was delivered successfully
  • Response body will contain the response from the miniapp’s event receiver endpoint

Request Example

curl --location --request POST 'https://api.boxo.io/api/v1/event-bridge/hostapp/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {{BASE64_ENCODED_CLIENT_ID_AND_CLIENT_SECRET}}' \
--data-raw '{
    "app_id": "{{MINIAPP_ID}}",
    "client_id": "{{CLIENT_ID}}",
    "event_type": "payment_completed",
    "payload": {
        "transaction_id": "tx_12345",
        "amount": 100.50,
        "currency": "USD",
        "status": "completed"
    }
}'

Common Event Types

Here are some common event types that can be used for communication between host apps and miniapps:

Host App to Miniapp Events

Event TypeDescriptionExample Payload
user_profile_updatedUser profile information has been updated{"user_id": "123", "updated_fields": ["email"]}
payment_completedA payment has been processed successfully{"transaction_id": "tx_123", "amount": 100.50}
location_updatedUser’s location has been updated{"latitude": 37.7749, "longitude": -122.4194}
app_state_changeThe state of the host app has changed{"new_state": "background", "timestamp": 123456}

Miniapp to Host App Events

Event TypeDescriptionExample Payload
order_createdA new order has been created in the miniapp{"order_id": "ord_123", "amount": 50.25}
product_viewedUser has viewed a product in the miniapp{"product_id": "prod_123", "category": "shoes"}
cart_updatedUser’s shopping cart has been updated{"cart_id": "cart_123", "item_count": 3}
content_sharedUser has shared content from the miniapp{"content_id": "cont_123", "content_type": "image"}

Error Handling

If an error occurs during event processing, the Boxo Platform will return an appropriate error response:

Error CodeDescription
EVENT_RECEIVER_DISABLEDEvent receiver is not enabled for the recipient
INVALID_EVENT_DATAThe event data format is invalid
EVENT_DELIVERY_FAILEDFailed to deliver the event to the recipient
UNAUTHORIZEDSender is not authorized to send events

Best Practices

  1. Event Types: Use consistent event types that clearly indicate the purpose of the event
  2. Minimal Payloads: Keep event payloads as small as possible, including only necessary information
  3. Error Handling: Implement proper error handling for event processing failures
  4. Idempotency: Design event handlers to be idempotent to handle potential duplicate events
  5. Timeouts: Implement reasonable timeouts for event processing to avoid blocking operations

By following these guidelines, you can create a robust event-driven communication system between your host app and miniapps using Boxo Event Bridge.