Note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation here. Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade.
Full rollout to all clients still TBD.
The SDK is written in TypeScript and provides full type definitions.
Importing Types
import type { FlowConfig } from '@incodetech/web/flow';
import type { FinishStatus } from '@incodetech/core/flow';
import type {
PhoneConfig,
PhoneState,
PhoneManager,
} from '@incodetech/core/phone';
import type {
EmailConfig,
EmailState,
EmailManager,
} from '@incodetech/core/email';
import type {
SelfieConfig,
SelfieState,
SelfieManager,
} from '@incodetech/core/selfie';
import type {
IdCaptureConfig,
IdCaptureState,
IdCaptureManager,
} from '@incodetech/core/id';
Each module's @incodetech/core/<name> subpath ships the canonical types — Config, State, and Manager for headless usage. Per-module deep-dives (Module: Selfie, Module: ID, Module: Phone, Module: Email) cover the property-level breakdowns; the rest of this page focuses on patterns and SDK-wide types.
Web Component Element Types
The SDK augments HTMLElementTagNameMap for <incode-flow> and <incode-workflow> so that document.createElement('incode-flow') and document.querySelector('incode-flow') return a fully typed element with .config, .onFinish, and .onError properties:
import '@incodetech/web/flow'; // registers the custom element + brings the type augmentation
const flow = document.createElement('incode-flow');
flow.config = {
// ✅ typed as FlowConfig
token: 'session-token',
lang: 'en-US',
enableHome: true,
};
flow.onFinish = (result) => {
// ✅ result typed as FinishStatus | undefined
console.log(result?.action);
};
flow.onError = (error, code) => {
// ✅ error: string | undefined, code: number | undefined
console.error(error, code);
};
Other module tags do not augment HTMLElementTagNameMap. Use the exported IncodeModuleProps to type their properties, and check selector results before assignment:
import type { IncodeModuleProps } from '@incodetech/web/extensibility';
import type { PhoneConfig, PhoneManager } from '@incodetech/core/phone';
import '@incodetech/web/phone';
type PhoneElement = HTMLElement & IncodeModuleProps<Partial<PhoneConfig>, void, PhoneManager>;
const phone = document.querySelector<PhoneElement>('incode-phone');
if (phone) {
phone.config = { otpVerification: true };
phone.onFinish = () => console.log('Phone verification complete');
}
Use the corresponding module's config and manager types for other tags. Component config accepts partial configuration; core manager factories can require complete configuration. See Web Components.
Configuration Types
Per-module config types (PhoneConfig, EmailConfig, SelfieConfig, IdCaptureConfig, FlowConfig, etc.) are documented in their respective deep-dive pages with full property tables. Import them from @incodetech/core/<module> (or @incodetech/web/flow for FlowConfig). Your editor's go-to-definition (or hover docs) takes you straight to the canonical declarations.
The remaining types in this section are SDK-wide and don't belong on a single module page.
WASM configuration
Import the supported configuration type instead of maintaining a local copy:
import type { WasmConfig, WasmPipeline, WasmSource, DefineWasmOptions } from '@incodetech/core/wasm';
WasmPipeline supports selfie, idCapture, onDeviceSelfie, videoSelfie, and videoSelfieId. The default warmup set is selfie and idCapture.
WasmConfig includes the self-hosting and source-loading options available in 2.3.0. See WASM Configuration for supported deployment choices.
Session initialization types
Define a SessionInitOptions object with your session token and any optional settings:
import type { SessionInitOptions, SessionInitResult } from '@incodetech/core/session';
const options: SessionInitOptions = {
token: 'YOUR_SESSION_TOKEN',
preloadFlow: true,
awaitFingerprint: false,
signal: new AbortController().signal,
};
Application code should pass token explicitly. preloadFlow optionally loads Flow configuration during initialization; signal supports cancellation.
awaitFingerprint defaults to true. With false, initialization resolves while fingerprint submission continues in the background. The initial result's fingerprintSuccess and fingerprintResult do not yet represent its final outcome; use whenSessionFingerprintSettled() to await that outcome. fingerprintResult is also undefined when fingerprint submission is disabled. See API Reference.
Features
type FeatureName =
| 'VIDEO_SELFIE_V2'
| 'USE_CLIENT_GLARE'
| 'USE_OPEN_VIDU'
| 'DISABLE_IPIFY';
type FeatureConfig = {
enabled: boolean;
feature: FeatureName;
config?: number | string;
};
type Features = {
features?: FeatureConfig[];
sessionIdentifier: string;
};
SpinnerConfig
type SpinnerSize = 'small' | 'medium' | 'large';
type SpinnerRenderMode = 'spinnerAndText' | 'spinnerOnly' | 'textOnly';
/** Loader presentation. Settable globally via `setup({ uiConfig: { spinner } })`
* or per element via `config.spinner`. Copy comes from i18n, not from here. */
type SpinnerPresentation = {
/** Which parts of the loader render */
renderMode?: SpinnerRenderMode;
/** Size of the spinner icon (default: 'medium') */
size?: SpinnerSize;
};
type SpinnerConfig = SpinnerPresentation & {
/** @deprecated Set copy via i18n translations. Still supported in 2.3.0. */
title?: string;
/** @deprecated Set copy via i18n translations. Still supported in 2.3.0. */
subtitle?: string;
};
Asset override types
type AssetKey =
| 'faceMatch.success'
| 'faceMatch.fail'
| 'documentCapture.tutorial'
| 'id.uploadScreen'
| 'id.ageVerification.dob'
| 'id.ageVerification.scan'
| 'id.ageVerification.privacy'
| 'videoSelfie.success'
| 'videoSelfie.fail'
| 'videoSelfie.tutorial.permission'
| 'videoSelfie.tutorial.selfie'
| 'videoSelfie.tutorial.frontId'
| 'videoSelfie.tutorial.backId'
| 'videoSelfie.tutorial.poa'
| 'videoSelfie.tutorial.questions'
| 'videoSelfie.tutorial.speech'
| 'loader.spinner';
type AnimationKey =
| 'id.tutorial.front'
| 'id.tutorial.back'
| 'id.tutorial.passport'
| 'id.flip'
| 'id.processing'
| 'selfie.tutorial'
| 'loader.spinner';
type AssetOverride =
| string // URL, or raw `<svg …>` markup (leading '<')
| { url: string }
| { raw: string } // sanitized before injection
| { svg: SvgComponent }; // precompiled Preact component
type AnimationOverride =
| LottieAnimationData
| { url: string }
| { animationData: LottieAnimationData };
type AssetOverrides = Partial<Record<AssetKey, AssetOverride>>;
type AnimationOverrides = Partial<Record<AnimationKey, AnimationOverride>>;
Import from @incodetech/web (or @incodetech/web/extensibility). AssetOverrides / AnimationOverrides are the maps accepted by UiConfig.assets / UiConfig.animations (global) and by FlowConfig / any module config prop (per-instance). See Asset Overrides for the full allowlist and precedence rules.
State Types
Every module's state is a discriminated union keyed on status. Import the canonical type and narrow it before reading state-specific fields:
import type { PhoneState } from '@incodetech/core/phone';
The Phone module reference documents loading, input validation, and OTP payloads. Avoid copying a shortened union into application code.
Using Discriminated Unions
function handleState(state: PhoneState) {
switch (state.status) {
case 'inputting':
// TypeScript knows state.countryCode exists here
console.log(state.countryCode);
break;
case 'awaitingOtp':
// TypeScript knows state.resendTimer exists here
console.log(state.resendTimer);
break;
}
}
Completion Result
The result delivered to the IncodeFlow onFinish callback, and to your code via the getFinishStatus helper, is FinishStatus, exported from @incodetech/core/flow:
import type { FinishStatus } from '@incodetech/core/flow';
// type FinishStatus = {
// redirectionUrl: string;
// action: 'approved' | 'rejected' | 'none';
// scoreStatus: 'OK' | 'WARN' | 'MANUAL_OK' | 'FAIL' | 'UNKNOWN' | 'MANUAL_FAIL';
// endScreenTitle: string | null;
// endScreenText: string | null;
// };
endScreenTitle and endScreenText contain Dashboard completion copy captured at session creation by the orchestrated Flow. Each is null when unconfigured. Apply your own display fallback. The raw getFinishStatus(flowId) helper always returns null for both fields; it does not restore session-creation copy.
Manager Types
Every headless manager guarantees these observation and cleanup methods:
type Manager<TState> = {
getState(): TState;
subscribe(listener: (state: TState) => void): () => void;
// module-specific methods (e.g. setPhoneNumber, submitOtp, capture, retryCapture, ...)
stop(): void;
};
Start and recovery methods are module-specific: most managers use load(), while Video Selfie uses start(). A final state cannot be reset; stop that manager and create a new one for another attempt. Use reset() only in the states documented by the module.
The module-specific method set is the actionable API. See each module's per-page deep-dive for the full table:
Or import the manager type directly: import type { PhoneManager } from '@incodetech/core/phone' (and equivalents for EmailManager, SelfieManager, IdCaptureManager).
See Also
- API Reference: Full API documentation
- Headless Mode: Using managers
- Asset Overrides: Replacing branded illustrations and animations