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 for iOS 14+. QEEmbedController around a WKWebView, QEEmbedView (SwiftUI) and QEEmbedViewController (UIKit), keychain session store, Face ID / Touch ID unlock, push and deep-link helpers.
→Android
Gradle library module qeembed, minSdk 24. QEEmbedView (a FrameLayout around a WebView), Keystore-encrypted session store, BiometricPrompt unlock, KYC file and camera picker, deep links.
→Web
No library: one iframe and the postMessage bridge. A complete host page with a bridge log is part of the package.
→QEEmbed, iOS 14+, WKWebView, no dependenciesqeembed, minSdk 24, WebView + JavascriptInterfacepostMessage, nothing to install#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.
{ "source": "qe-embed", "v": 1, "type": "<event>", "data": { ... } | null, "ts": <ms> }{ "source": "qe-host", "type": "<command>", "data": { ... } | null }| Transport | Events arrive through | Commands go through |
|---|---|---|
ios | window.webkit.messageHandlers.qeEmbed.postMessage(json) | evaluateJavaScript("window.QEEmbed && window.QEEmbed.handle({…})") |
android | window.QEEmbedAndroid.postMessage(json) | evaluateJavascript("window.QEEmbed && window.QEEmbed.handle({…})") |
rn | window.ReactNativeWebView.postMessage(json) | injectJavaScript("window.QEEmbed && window.QEEmbed.handle({…})") |
iframe | window.parent.postMessage(object, origin) | frame.contentWindow.postMessage({ source: "qe-host", … }, moduleOrigin) |
Payloads for every event and command, and the full option list, are in the embed guide.
// 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:
Sign-in
Get a one-time token from your backend (which calls the Partner API,
POST …/users/{external_id}/sso) and pass it withstart(loginToken:)/start(token)/?token=. Keep the session from theloginevent (the SDKs do), pass it on the next cold start, drop it onlogoutandsession_expired.Biometrics
On
unlock_requestedrun the system prompt and answerunlock { ok }- the SDKs do this unless you take it over.Push
Register the device with APNs / FCM yourself, then
registerPushToken(…). Trade and margin pushes are sent by the platform to that device.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.
Deposits and outside links
With
depositByHost/linksByHost(both default on) the module hands over and you open your cashier or the system browser.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.
start() early and show the tab later. Do not recreate the web view per screen - use navigate.