SDKs

Octolit Embed SDK

The trading module inside your own app, with a small native bridge. The SDK wraps the web view and the protocol so your team writes the host app, not the plumbing. Packages are provided by Octolit on request.

#Platforms

iOS
Swift package QEEmbed, iOS 14+, WKWebView, no dependencies
Android
Gradle module qeembed, minSdk 24, WebView + JavascriptInterface
Web
iframe + postMessage, nothing to install
Protocol
v1 - 17 events, 12 commands

#What the SDK does - and does not do

In the SDK

  • The web view with embed mode on, the options injected before the page scripts run.
  • The bridge: events to your listener, commands as methods, queued until the module is ready.
  • Session storage in the keychain (iOS) / Keystore-encrypted preferences (Android), restored on the next start.
  • Biometric unlock with the system prompt (device passcode as fallback), unless you take it over.
  • Push token hand-over and the push payload → screen helper.
  • Deep links: your universal / app links and the module's own links → navigate.
  • KYC uploads: the file picker and camera sheet inside the web view.
  • Navigation guard: the web view loads only the module's origin.

Not in the SDK, on purpose

  • APNs / Firebase registration - you register as you do today and hand the token over.
  • Your login UI and your backend call for the one-time token.
  • Your cashier.
  • Analytics.
  • Third-party dependencies - there are none.
  • Certificate pinning - the platform's certificates rotate automatically.

#The protocol in one page

One message shape in each direction. The native SDKs implement it; a React Native or plain web host can implement it from the embed guide alone.

module → host (event)
{ "source": "qe-embed", "v": 1, "type": "<event>", "data": { ... } | null, "ts": <ms> }
host → module (command)
{ "source": "qe-host", "type": "<command>", "data": { ... } | null }
TransportEvents arrive throughCommands go through
ioswindow.webkit.messageHandlers.qeEmbed.postMessage(json)evaluateJavaScript("window.QEEmbed && window.QEEmbed.handle({…})")
androidwindow.QEEmbedAndroid.postMessage(json)evaluateJavascript("window.QEEmbed && window.QEEmbed.handle({…})")
rnwindow.ReactNativeWebView.postMessage(json)injectJavaScript("window.QEEmbed && window.QEEmbed.handle({…})")
iframewindow.parent.postMessage(object, origin)frame.contentWindow.postMessage({ source: "qe-host", … }, moduleOrigin)
eventsreadystateerrorloginlogoutsession_expiredauth_requirednavigationtrade_openedtrade_closeddeposit_requestedopen_externalheightunlock_requestedunlockedtheme_appliedpush_registered
commandsinitloginrestoreSessionlogoutsetThemesetLanguagenavigatepushTokenRegisteredlockunlockresumegetState

Payloads for every event and command, and the full option list, are in the embed guide.

React Native - the bare protocol
// React Native host (transport "rn") - the same contract without a library
<WebView
  ref={web}
  source={{ uri: 'https://live.your-brand.com/?embed=1&transport=rn&screen=terminal&deposit=host&links=host' }}
  onMessage={(e) => {
    const m = JSON.parse(e.nativeEvent.data);          // { source: 'qe-embed', v: 1, type, data, ts }
    if (m.source !== 'qe-embed') return;
    if (m.type === 'login') keep(m.data.session);
  }}
/>
// host -> module
web.current.injectJavaScript('window.QEEmbed && window.QEEmbed.handle(' + JSON.stringify({ type: 'navigate', data: { screen: 'wallet' } }) + '); true;');

#Host duties

What the module cannot do by itself, so your app does it:

  1. Sign-in

    Get a one-time token from your backend (which calls the Partner API, POST …/users/{external_id}/sso) and pass it with start(loginToken:) / start(token) / ?token=. Keep the session from the login event (the SDKs do), pass it on the next cold start, drop it on logout and session_expired.

  2. Biometrics

    On unlock_requested run the system prompt and answer unlock { ok } - the SDKs do this unless you take it over.

  3. Push

    Register the device with APNs / FCM yourself, then registerPushToken(…). Trade and margin pushes are sent by the platform to that device.

  4. KYC uploads

    The file input inside the module needs the picker and camera: the SDKs handle the web view side, your app declares the camera / photo permissions.

  5. Deposits and outside links

    With depositByHost / linksByHost (both default on) the module hands over and you open your cashier or the system browser.

  6. Deep links

    Map your universal link / app link to navigate; the SDKs ship a mapper for /trade/<screen>, yourapp://trade/<screen> and the module's own /dashboard/… links.

#Where to start

  • Read the embed guide once - options, events, commands and the sign-in flow are the same on every platform.
  • Get the Partner API token flow working on your backend first (SSO guide); everything else is UI.
  • Then the platform page: iOS, Android or Web. Each ends with the same 9-point test plan.
One module instance per app
Create the controller / view when your app starts, call start() early and show the tab later. Do not recreate the web view per screen - use navigate.