Web SDK
Embed the Othento verification flow in any web app. The package is framework-agnostic, about 3.6 KB gzipped with zero runtime dependencies, and ships ESM, CommonJS and TypeScript types.
Install
npm i @alialjundi/web-sdk
Then import the class and its types:
import { OthentoSDK, OthentoError } from '@alialjundi/web-sdk';Initialize
Construct OthentoSDK with a config object and call start(). Configuration is validated synchronously in the constructor — a missing required field throws an OthentoError immediately rather than via onError.
import { OthentoSDK } from '@alialjundi/web-sdk';
const sdk = new OthentoSDK({
mode: 'create',
apiKey: 'pk_sandbox_•••',
workflowExternalId: 'wf_onboarding',
clientData: 'user-123',
onReady: () => {},
onSessionCreated: ({ externalId }) => save(externalId),
onStatusChange: (status) => {},
onCompleted: ({ decision, externalId }) => finish(decision),
onCancelled: ({ reason }) => {},
onError: (err, message) => {},
});
sdk.start();
// later, to tear down early:
sdk.destroy(); The three required fields in create mode are apiKey, workflowExternalId and clientData. See the API reference for every option.
Modal or inline
By default the flow opens as a centered modal. Pass a container (an element or CSS selector) to render it inline inside your own layout instead. In inline mode the built-in close button and backdrop options are ignored — you own dismissal.
new OthentoSDK({
mode: 'create',
apiKey: 'pk_sandbox_•••',
workflowExternalId: 'wf_onboarding',
clientData: 'user-123',
container: '#verify', // render inline instead of a modal
onCompleted: ({ decision }) => console.log(decision),
}).start();Lifecycle & callbacks
A session runs onReady → onSessionCreated → onStatusChange… and then fires exactly one terminal callback:
onCompleted— a decision was reached:Approved,DeclinedorInReview.onCancelled— the user dismissed the flow (close button, backdrop, escape, page hide…).onError(err, message)— a non-decision terminal error; inspecterr.code.
Callbacks dispatch asynchronously and exceptions inside them are caught, so one throwing handler never breaks the flow. Call destroy() to tear down early (e.g. on component unmount).
Error handling
Every error carries a typed code you can switch on for tailored recovery UX:
onError: (err, message) => {
switch (err.code) {
case 'camera_permission_denied': showCameraHelp(); break;
case 'session_expired': restartSession(); break;
case 'network': showRetry(); break;
default: showError(message);
}
}Camera-permission denial is the single biggest drop-off cause — always serve over HTTPS and show a clear retry path. See the reference for the full list of error codes.
Frameworks
Because it is a plain class, the SDK drops into any framework — construct it on mount, call start(), and call destroy() on unmount. See the Quickstart for a React example.
Security
- Document images and biometric data are captured and uploaded directly from the SDK to Othento — they never cross the host page or your servers.
- The SDK loads from a fixed origin and verifies every
postMessageby origin; consumers cannot redirect it elsewhere. - Public keys are scoped to mint sessions and read their own data only. For production, prefer Token mode to keep keys off the client.