Guides
How it works#
All three SDKs host the same embed app in a WebView, as a top-level page at https://embed.finbaze.com/m/<tag> (sandbox: https://sandbox.embed.finbaze.com), not in an iframe. Native code adds what a WebView cannot do: camera and files, biometric step-up through your app, native sheets, and deep-link hand-off. The embed token stays in WebView memory and the SDK never stores it.
Your app SDK WebView embed.finbaze.com/m/<tag> fetchClientSecret() <------ FinBaze(publishableKey, appId) loads /m/<tag>?pk=...&app=... onStepUpRequired() <------ stepup.required component needs approval camera / scanner <------ capture.request file bytes go back via the bridge handle(notification) ------> open the component's sheet
Register the app#
In the portal you register each app (ios or android, bundle id or package name, URL scheme). A session created for a mobile app can only be exchanged through the /m/* shell with that app id; a session without one only inside an allowed web origin. Use the publishable key of the same platform on the device.
Camera and files#
The component asks for a photo or file; the SDK opens the native camera or document scanner (VisionKit, CameraX or ML Kit, or the libraries already in your React Native app) and sends the bytes back. Files over 10 MB are rejected natively. If you need your own scanner, the SDKs expose a capture callback, the same idea as onCameraCapture in the browser SDK.
Step-up with your own biometrics#
FinBaze does not implement biometrics. Banks own strong customer authentication. When a component needs approval (filing a VAT return, approving a payment request) the API answers STEP_UP_REQUIRED with a challenge and the SDK calls your onStepUpRequired. You run Face ID, BiometricPrompt or your SCA server, and complete the challenge from your backend with your own assertion, the same server-side contract as Delegated actions: step-up. Platforms that are not banks can opt into a device-local confirmation in the portal; it is a weaker signal and is labelled as such in the audit log.
Open a component from a push#
FinBaze holds no APNs or FCM credentials for partners. A message routed partner_delivers reaches your webhook (Messages and routing); for mobile it carries an action that names the component and a signed, opaque intent valid for 7 days. You send your own push with the intent in the payload. On tap you pass the payload to the SDK, which asks your backend for a client secret for that component and opens it. Your backend can verify an intent with resolveEmbedIntent before minting the session.
// Planned shape, iOS
let finbaze = FinBaze(publishableKey: "fb_pk_test_...", mobileAppId: "fb_app_...") { request in
try await api.finbazeClientSecret(component: request.component, company: request.company)
}
finbaze.onStepUpRequired = { challenge in try await bank.performSCA(challenge) }
if finbaze.canHandle(userInfo) { finbaze.handle(userInfo, presentingFrom: rootVC) }
WebView security#
The SDKs only load the FinBaze embed origins in the WebView and open everything else in the system browser. They disable file access and mixed content, allow the bridge only from the FinBaze origin, turn WebView debugging off in release builds, offer screen protection for payroll components, and bundle no analytics.
What works today#
The same components run in the browser through @finbaze/embed-js, including the camera, payment and step-up callbacks. The neobank demo has a web part you can deploy now; its Expo app ships with the mobile SDKs.
Pitfalls#
- Treating a leaked client secret as harmless: without app attestation it can be exchanged by any app within 15 minutes, once. Mint it only for a signed-in user, and return a new one each time.
- Persisting the embed token: do not; the WebView holds it.