Hosted launcher
@arkyc/sdk/browser opens the hosted widget in an overlay iframe, your frontend bundles almost nothing, and the only thing the browser needs is the one-time client token from your server. The widget runs the guided capture flow (document, selfie, liveness, plus an optional address step on custom workflows).
Want to bundle the flow into your own frontend and point it at your API for full control of layout? Use @arkyc/widget instead.
Install
Use the SDK’s browser entry with a bundler, or the standalone global script for a no-bundler setup.
// Bundler
import { ArkycWidget } from '@arkyc/sdk/browser'<!-- Served from jsDelivr; exposes window.ArkycWidget -->
<script src="https://cdn.jsdelivr.net/npm/@arkyc/widget/dist/arkyc-widget.iife.global.js"></script>
<script>
ArkycWidget.open({ token: clientToken })
</script>Open as an overlay
ArkycWidget.open(options) mounts the hosted widget in a fullscreen overlay and returns a handle. token is the only required option; everything else is optional.
import { ArkycWidget } from '@arkyc/sdk/browser'
const handle = ArkycWidget.open({
token: clientToken, // required; from arkyc.sessions.create()
widgetUrl: 'https://arkyc.toneflix.net/verify', // optional: override the hosted origin
onComplete: (result) => { // flow reached a terminal state
console.log(result.status) // 'approved' | 'requires_review' | 'rejected' | …
},
onError: (error) => showError(error), // session errored or expired
onClose: () => {}, // overlay torn down (also after complete/error)
onEvent: (event) => { // live firehose of named events
console.log(event.name, event.data)
},
})Options
The full OpenWidgetOptions shape:
| Option | Type | Notes |
|---|---|---|
token | string | Required. The session’s one-time client token. open() throws if it’s missing. |
widgetUrl | string | Hosted widget origin. Defaults to https://arkyc.toneflix.net/verify. Set this when self-hosting the widget. |
onComplete | (result: WidgetResult) => void | The flow reached a terminal state. The overlay then closes automatically. |
onError | (error: unknown) => void | The session errored or expired. The overlay then closes automatically. |
onClose | () => void | The overlay was torn down by the user dismissing it, by handle.close(), or after a complete/error. |
onEvent | (event: WidgetEvent) => void | Firehose of every named event (see Events). |
doc / win | Document / Window | Test injectables; default to the global document / window. |
The widget handle
open() returns a WidgetHandle so you can dismiss the widget or subscribe to a single event.
| Member | Signature | Notes |
|---|---|---|
close | () => void | Remove the overlay and detach listeners. Triggers onClose. |
on | <K extends WidgetEventName>(event: K, listener: (data: WidgetEventMap[K]) => void) => () => void | Subscribe to one named event. event is a known event name and data is typed from it. Returns an unsubscribe function. |
const handle = ArkycWidget.open({ token: clientToken })
// Subscribe to one event; the call returns an unsubscribe fn.
const off = handle.on('session.transition', (data) => {
updateProgress(data)
})
// Later, stop listening, or close the widget yourself.
off()
handle.close()Events
onEvent receives a WidgetEvent, a discriminated union { name; data } — switch (event.name) narrows event.data to the payload below. handle.on(name, cb) subscribes to one event and hands its cb just that event’s data. Both are relayed from the hosted widget over postMessage.
| Event | Fires when | data payload | Also surfaced as |
|---|---|---|---|
session.transition | The session advances a stage (e.g. document_submitted → processing). | { session_id, status, previous_status } | None |
complete | The flow reached a terminal state. | WidgetResult | onComplete(result) |
error | The session errored or expired. | { message, status?, error? } | onError(error) |
close | The overlay was dismissed. | undefined | onClose() |
Result
onComplete receives a WidgetResult, { status, …extra }, where status mirrors the verification status. Treat it as a UX signal; use webhooks as your source of truth.
onComplete: (result) => {
// result.status:
// 'approved' | 'requires_review' | 'rejected'
// | 'processing' | 'expired' | 'cancelled'
switch (result.status) {
case 'approved': return onApproved()
case 'requires_review': return onPending() // a human will decide
default: return onRejected()
}
}Hosted page
Prefer a redirect (or a cross-device hand-off)? Send the user to the hosted widget URL with the token as a query param, the same page the overlay loads in its iframe.
https://arkyc.toneflix.net/verify?token=<clientToken>Rendering & permissions
open() appends a fixed, fullscreen dimmed backdrop (at the maximum z-index) with a centered card up to 480×720 px, and an iframe that requests camera and microphone. Notes:
- Serve your page over HTTPS, browsers only grant camera access on a secure origin.
- Each
open()mounts its own overlay; keep one open at a time (callhandle.close()before re-opening). - The overlay auto-closes on
completeanderror; you don’t need to callclose()in those callbacks.
Theming
The widget is themed from your project’s branding, primary color, logo and corner radius configured in the dashboard so it matches your product without extra code.
Capture-only mode
Don’t need Arkyc’s decisioning? Run the widget purely to capture a high-quality document and selfie, then forward the artifacts to your own KYC provider. Your users get a flow they’ll finish; you keep your existing verification. The captured images are exposed as signed, time-limited URLs on the session’s assets see the server SDK and webhooks.
