JavaScript SDK
@idcheck/web embeds the hosted verification flow in your page —
modal, inline iframe or full-page redirect. Zero dependencies, ~4 KB minified, ships as ESM (npm)
and IIFE (window.IdCheck, script tag).
Install
npm install @idcheck/web<script src="https://cdn.jsdelivr.net/npm/@idcheck/web@0/dist/index.global.js"></script>
<!-- exposes window.IdCheck -->Quickstart
Five lines from a client token (created by your backend via
POST /v1/verifications) to a working verification flow:
import { createIdCheck } from '@idcheck/web';
const idcheck = createIdCheck({ publicKey: 'pk_test_...', sessionToken });
idcheck.open();Script-tag equivalent:
<script>
const idcheck = IdCheck.createIdCheck({ publicKey: 'pk_test_...', sessionToken });
idcheck.open();
</script>onComplete fires in the user's browser and can be forged. Always confirm the outcome server-side: read GET /v1/verifications/{id} or trust only your signed webhook.
createIdCheck config
createIdCheck(config)
| Field | Type | Description |
|---|---|---|
| publicKeyrequired | string | Your publishable key, e.g. pk_test_…. Identifies your integration to the hosted flow. |
| sessionTokenoptional | string | Client token (X-Client-Token value) from POST /v1/verifications. Provide this or createSessionToken. |
| createSessionTokenoptional | () => Promise<string> | Async alternative — called lazily on each open(), ideal when tokens must be minted on demand (they expire after 30 minutes). |
| baseUrloptional | string | Hosted flow origin. Default https://verify.idcheck.now. |
| modeoptional | "modal" | "redirect" | "inline" | Embed mode. Default modal. See modes below. |
| containeroptional | HTMLElement | Host element for inline mode. |
| redirectUrloptional | string | Where redirect mode returns the user. Default: current URL. |
| themeoptional | object | { primaryColor?: string, colorScheme?: "dark" | "light" } — passed to the flow via postMessage init. |
| onEventoptional | (event) => void | Every flow event: ready, step, complete, error, exit. |
| onCompleteoptional | (result) => void | Final outcome: { verificationId, status } where status is approved | in_review | declined. |
| onExitoptional | (reason) => void | Flow closed without completing (close button, Escape, backdrop, programmatic close()). |
Instance methods
| Method | Description |
|---|---|
open() | Resolves the session token (calls createSessionToken if given) and presents the flow. Returns a Promise. |
close(reason?) | Tears down the UI; fires onExit(reason) unless already exited. |
destroy() | Removes listeners and DOM. The instance cannot be reused. |
isOpen | true while the modal/inline frame is mounted. |
Events
The hosted flow talks to your page over window.postMessage
({ source: 'idcheck', type, payload }); the SDK validates
event.origin against your baseUrl origin before dispatching to
onEvent.
| Event type | Fires when | Payload |
|---|---|---|
ready | Flow is loaded and ready (SDK posts init with publicKey + theme back into the frame) | — |
step | User advances between capture steps | step descriptor |
complete | Flow finished | { verificationId, status } — approved | in_review | declined |
error | Recoverable error inside the flow | error detail |
exit | Flow closed | reason string |
Embed modes
| Mode | Behavior |
|---|---|
modal (default) | Dimmed fixed overlay with a centered 420×680 responsive iframe, close button, backdrop-click and Escape to close. |
inline | Iframe mounted inside your container element, no overlay. |
redirect | Full-page navigation to the hosted flow, returning to redirectUrl. onComplete/onEvent do not fire across a navigation — read the result from your backend (webhook/poll). |
const idcheck = createIdCheck({
publicKey: 'pk_test_...',
createSessionToken: async () => (await fetch('/api/idcheck/session', { method: 'POST' })).json().then(d => d.client_token),
mode: 'modal',
theme: { primaryColor: '#00f0ff', colorScheme: 'dark' },
onEvent: (e) => console.log(e.type, e.payload),
onComplete: async ({ verificationId }) => {
// Confirm server-side before trusting:
const v = await fetch(`/api/verifications/${verificationId}`).then(r => r.json());
if (v.decision === 'approve') unlockAccount();
},
onExit: (reason) => console.log('exited:', reason),
});
document.querySelector('#verify-btn').addEventListener('click', () => idcheck.open());React / Vue / vanilla
React
import { useEffect, useRef } from 'react';
import { createIdCheck } from '@idcheck/web';
export function VerifyButton({ getToken }) {
const ref = useRef(null);
useEffect(() => {
ref.current = createIdCheck({ publicKey: 'pk_test_...', createSessionToken: getToken });
return () => ref.current?.destroy(); // always destroy on unmount
}, [getToken]);
return <button onClick={() => ref.current.open()}>Verify identity</button>;
}Vue
<script setup>
import { onBeforeUnmount } from 'vue';
import { createIdCheck } from '@idcheck/web';
const idcheck = createIdCheck({ publicKey: 'pk_test_...', createSessionToken: getToken });
onBeforeUnmount(() => idcheck.destroy());
</script>
<template><button @click="idcheck.open()">Verify identity</button></template>Vanilla
No framework needed — create one instance per page, call open() from a click
handler, and destroy() on page unload if you recreate it. A complete vanilla page
ships in the package under example/index.html.
Security notes
- Only the client token reaches the browser. API keys must never appear in frontend code.
- Client tokens expire after 30 minutes — prefer
createSessionTokenso a fresh token is minted per attempt. - The SDK validates message origins; do not attach your own
messagelisteners that skip origin checks. - Final decisions must be read server-side (webhook or
GET /v1/verifications/{id}).