@okyc/web
Open the hosted flow from any website — modal, inline, popup or redirect. Zero dependencies, under 10 KB.
Version0.2.0
Install
npm install @okyc/webYour backend creates the session and returns clientToken and url (see sessions).
Before embedding, add your site's origin under Settings → Embedding & redirects → Allowed embed origins in the
dashboard; the hosted flow refuses to render inside other origins.
Start the flow
Okyc.start(options) opens the flow and returns a Flow with close(), on(event, handler) and the url.
This example uses the React wrapper, which calls Okyc.start for you:
function App() {
const [status, setStatus] = useState('Not verified');
return (
<main style={{ fontFamily: 'system-ui', maxWidth: 480, margin: '64px auto' }}>
<h1>Acme onboarding</h1>
<p>Status: {status}</p>
<OkycButton
// Your backend creates the session and returns { clientToken, sessionUrl }.
getClientToken={() => fetch('/api/kyc/session', { method: 'POST' }).then((r) => r.json())}
{...flowHandlers(setStatus)}
>
Verify identity
</OkycButton>
</main>
);
}Handle events
// UX only — the webhook on your backend is the source of truth.
function flowHandlers(setStatus) {
return {
onStepStarted: (e) => console.debug('step started', e.step),
onComplete: (e) => setStatus(`Submitted (${e.status}) — we'll confirm shortly`),
onExit: () => setStatus('Closed before finishing'),
onError: (e) => setStatus(`Error: ${e.code}`),
};
}| Callback | Event | Payload |
|---|---|---|
onReady | ready | — |
onStepStarted | step_started | { sessionId, step } |
onStepCompleted | step_completed | { sessionId, step } |
onComplete | complete | { sessionId, status } — processing, approved, declined or review |
onExit | exit | { sessionId, reason } — user_closed or expired |
onError | error | { code, message } — e.g. token_expired, camera_denied, origin_not_allowed, popup_blocked |
flow.on('complete', handler) is the same as the callback. Events are for your UI only: grant access after the
webhook.
Options
| Option | Default | |
|---|---|---|
clientToken | required | st_… from your backend. A secret key is rejected. |
sessionUrl / sessionId | one required | The session url (its origin and id are used) or the ses_… id. |
verifyUrl | https://verify.okyc.stream | Hosted flow origin, when you pass sessionId. Must be https except on localhost. |
mode | modal | See below. |
container | — | Element or selector; required for inline. |
locale | — | Override the flow language. |
theme | workflow branding | Colour scheme: 'light', 'dark' or 'system'. Brand colour, radius and font come from the workflow branding. (The older { colorScheme } object still works; its primaryColor and radius were never applied.) |
| Mode | Behaviour |
|---|---|
modal | Full-screen overlay on phones, a centred dialog on desktop in the flow's own card style. Esc or the flow's ✕ closes it (exit with user_closed). |
inline | An iframe in your container; it resizes to the flow's height. |
popup | A new window; falls back to redirect (and emits popup_blocked) when blocked. |
redirect | Navigates to the flow; it returns to the session's redirect_url with ?session_id=&status=. |
Security
- The client token goes in the URL fragment (
#t=…), which browsers never send to servers. - Messages are accepted only from the flow's exact origin and window, with
source: "okyc"andv: 1. - The iframe gets
allow="camera; microphone; fullscreen; clipboard-write"and nothing else. - Expired token? Get a new one from your backend (
POST /v1/sessions/:id/client_token) and callstartagain; the flow resumes at the first unfinished step.
@okyc/node
The server SDK for Node 18+, Bun, Deno and edge runtimes — typed, retried, never logs bodies.
@okyc/react
A button, an inline component and a hook around @okyc/web. SSR-safe.
© 2026 Aiistic Technologies Private Limited. OKYC is a product of Aiistic Technologies Private Limited. Privacy notice