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.
Setup
setup()
Initialize the SDK before using any components.
Which setup() do I call?
You call one, never both. Two packages export a setup(), and @incodetech/web's version calls @incodetech/core's for you:
your app ──▶ setup() from '@incodetech/web' ──calls──▶ setup() from '@incodetech/core'
adds i18n, uiConfig, theme apiURL, token, wasm, encryption, …
your app ──▶ setup() from '@incodetech/core' (headless — the web layer is never loaded)
Start from what you render:
| You render | Call | Why |
|---|---|---|
| Your own UI, driving headless managers | setup() from @incodetech/core |
Nothing in the web layer needs configuring. |
| Web components, and you have the session token | setup() from @incodetech/web |
One call wires both layers, including language, branding, and the dashboard theme. |
Web components, but you need setup() before the token |
setup() from @incodetech/core |
The web wrapper requires token; core's does not. See the trade-off below. |
The web wrapper forwards every shared option to core unchanged, then adds the four presentation options core has no concept of: i18n, uiConfig, flow, and theme.
When you deliberately use core's setup() with web components
Two things pull integrators back to the core entry point even when they render components:
- You want
setup()to run before the session token exists, so WASM warmup overlaps with your backend creating the session. Core'sapiURLandtokenare both optional and it pairs withinitializeSession(); the web wrapper requirestokenup front. - You need an option the web wrapper does not accept —
encryption,hostingApp,tri,trueSight, orvideoSelfie. End-to-end encryption is the common case; see End-to-End Encryption.
That combination works, and the examples throughout these docs use it. Just wire the presentation layer yourself, because core's setup() cannot:
What web's setup() would have done |
Do this instead |
|---|---|
i18n — language and translations |
Call setI18nInstance(createI18n({ lang, translations })) from @incodetech/web. Text still renders without it, in English defaults. See Internationalization. |
uiConfig — logo, subtitle, assets, loader |
Call setUiConfig({ … }) from @incodetech/web. See Theming & Styling. |
theme — the dashboard theme |
<incode-flow> and <incode-workflow> fetch it themselves from their config.token, so they are unaffected. Standalone module components do not — they render unbranded. Apply your branding through setUiConfig instead. |
flow — Flow-backed standalone config |
Core accepts flow, but preload and mergeConfig only take effect through the web wrapper. See Individual Modules. |
The silent case is worth repeating: a standalone <incode-selfie> or <incode-id> set up through core skips the dashboard theme with no error. If your branding comes from the Incode dashboard rather than setUiConfig, use the web setup().
setup() from @incodetech/core
import { setup } from '@incodetech/core';
await setup({
apiURL?: string; // API base URL
token?: string; // Session token (one-shot convenience — delegates to initializeSession)
customHeaders?: Record<string, string>;
timeout?: number; // Request timeout (ms). No deadline when omitted.
wasm?: WasmConfig | false; // WASM warmup (see WASM Configuration)
encryption?: boolean | { mgf1?: 'sha1' | 'sha256' }; // End-to-end encryption (locked at boot)
hostingApp?: string; // Optional fingerprint hosting-app identifier
ipLookup?: boolean; // Default true. Set false to skip the third-party IP lookup (api.ipify.org).
fingerprint?: boolean; // Default true. Set false to skip device-fingerprint submission (transition flag).
flow?: false | { preload?: boolean; mergeConfig?: boolean }; // Flow-backed config for standalone modules
devMode?: boolean; // Default false. Set true in local development to silence the devtools detector.
tri?: { token: string; apiURL: string; autostart?: boolean }; // Optional TRI telemetry config
trueSight?: { enabled?: boolean }; // Default enabled. Set { enabled: false } to opt out of diagnostics.
featureManagement?: boolean | FeatureManagementSetupOptions; // Default true. Set false to opt out entirely.
environment?: 'development' | 'staging' | 'production'; // Default 'production'. Feature-management targeting only.
});
The canonical activation pattern is two calls — setup({ apiURL }) first, then initializeSession({ token }) once the session token is known. See initializeSession() below. Passing token to setup is a one-shot convenience that delegates to initializeSession internally.
| Option | Type | Required | Description |
|---|---|---|---|
apiURL |
string |
❌ | API base URL. Omit when every API actor is overridden via .provide() (advanced). |
token |
string |
❌ | Session token. One-shot convenience that delegates to initializeSession({ token, hostingApp }). Prefer the explicit two-call form: setup({ apiURL }) then initializeSession({ token }). The two-call form lets you start setup (including WASM warmup) before the token is known. |
customHeaders |
Record<string, string> |
❌ | Headers to attach to every SDK request. |
timeout |
number |
❌ | Request timeout in milliseconds. There is no default deadline — omit it and a request runs until it succeeds, fails at the network layer, or the API gateway ends it. That keeps large uploads alive on slow mobile connections, where a fixed timeout cut them off mid-transfer. Set this when your integration needs a bounded request. |
wasm |
WasmConfig | false |
❌ | WASM warmup. Omit to skip preload (loads lazily on first selfie/ID capture). Pass an object to warm up with CDN defaults plus any overrides. Pass false to explicitly disable. See WASM Configuration. |
encryption |
boolean | { mgf1?: 'sha1' | 'sha256' } |
❌ | Enable end-to-end encryption for SDK traffic. Independent of token — can be enabled before a session token is known. Not a self-serve flag — your Incode account team provisions the environment and gives you the dedicated apiURL and mgf1 scheme. Locked at boot (call reset() to change later) and requires the WASM binary transport. See End-to-End Encryption for the full walkthrough including API-key transmission, MGF1 schemes, and failure modes. |
hostingApp |
string |
❌ | Hosting app identifier forwarded to the fingerprinting service. |
ipLookup |
boolean |
❌ | Controls the third-party public-IP lookup (api.ipify.org). Default true (lookup enabled). Set false to opt out — no external call to ipify, at the cost of a less-precise fingerprint. Privacy-friendly for deployments where outbound calls to third-party services are restricted. |
fingerprint |
boolean |
❌ | Controls client-side device-fingerprint submission (POST /omni/add/device-fingerprint). Default true. Set false to skip it entirely — also blanks the fingerprint hash captured during selfie/ID/authentication verification. Transition flag: with fingerprint: false, the SDK does not auto-inject the mandatory-consent step in flow/workflow (no regulation data to base it on) — handle consent yourself if this applies to your integration. |
devMode |
boolean |
❌ | Disables the browser devtools detector for local development. Default false. Set true only during local development — the detector feeds an anti-fraud signal and must stay on in production. Do not ship devMode: true. WASM console logging is a separate flag (wasm.showLogs). See WASM Configuration. |
tri |
{ token: string; apiURL: string; autostart?: boolean } |
❌ | Transactional Risk Intelligence (TRI) telemetry. Provide token (a short-lived SDK token from createTRISession, not the org API key) and apiURL (the TRI ingest endpoint). TRI starts automatically unless autostart: false — use false to defer collection until after a consent gate, then call startTRI() from @incodetech/core/tri. Omitting this field opts out; no collectors start. |
flow |
false | { preload?: boolean; mergeConfig?: boolean } |
❌ | Controls whether standalone modules resolve their configuration from your dashboard Flow. Omit it (or pass {}) for lazy resolution on mount. preload: true fetches Flow during setup(). mergeConfig: true merges the config you supply over the Flow config. false disables Flow-backed resolution. See Individual Modules for the full matrix. |
trueSight |
{ enabled?: boolean } |
❌ | Incode-internal SDK-health diagnostics, used to debug capture issues you report. Enabled by default. During a session the SDK buffers sanitized diagnostic breadcrumbs — no personal data and no captured images — and uploads a single encrypted record when the session ends. Fire-and-forget: it never blocks or affects your flow. Set { enabled: false } to opt out entirely. Incode can also disable collection remotely. The value is fixed by the first setup() of the lifecycle; call reset() to change it. |
featureManagement |
boolean | FeatureManagementSetupOptions |
❌ | Controls the feature-management integration, which decides gate and experiment values for the session. Enabled by default, loaded as a separate chunk, and served by a third party — see Third-Party Dependencies. Pass false for a full opt-out: no chunk, no feature-management network traffic. Reads from @incodetech/core/feature-management keep working when disabled and resolve to their defaults. Only the first enabling setup() initializes it. See the option table below. |
environment |
'development' | 'staging' | 'production' |
❌ | Coarse deployment tier used for feature-management targeting, with no finer granularity. Default 'production'. Read by the first enabling setup() only, and inert when featureManagement is false. |
FeatureManagementSetupOptions
Pass this object form instead of true to configure identity and privacy. The defaults are already conservative: no customer API key is used, and identity starts from an SDK-generated ID rather than anything you supply.
| Option | Type | Default | Description |
|---|---|---|---|
clientExperimentId |
string |
— | Integrator-scoped targeting unit, agreed with your Incode representative. Use it to bucket gates for one integrator, such as a pilot rollout. |
disableStableId |
boolean |
false |
Stops the integration generating a per-user ID at all. The strongest privacy control — evaluations resolve to control values until session identity arrives later in the flow. |
disablePersistence |
boolean |
false |
Keeps identity in memory only, so it is never linkable across page loads. Trades away the local bootstrap cache, so every session fetches on boot. |
custom |
Record<string, unknown> |
— | Attributes attached for targeting rules and analytics. They do not bucket experiments. Keep personal data and secrets out — these reach the provider's logs as-is. |
redactedUserInfo |
FeatureManagementRedactedUserInfo |
ip, country redacted |
Which auto-collected fields to blank before they leave the browser. IP address and country are redacted by default; pass false for either to send it, or true for another field to redact that too. |
setup() from @incodetech/web
Use this one with the web components. apiURL and token are both required here, so create the session before you call it.
import { setup } from '@incodetech/web';
await setup({
apiURL: string; // Required
token: string; // Required: session token from createSession()
customHeaders?: Record<string, string>;
timeout?: number;
wasm?: WasmConfig | false;
ipLookup?: boolean;
fingerprint?: boolean;
devMode?: boolean;
featureManagement?: boolean | FeatureManagementSetupOptions;
environment?: 'development' | 'staging' | 'production';
i18n?: I18nOptions; // Language and translation overrides
uiConfig?: UiConfig; // Logo, subtitle, asset/animation and loader overrides
flow?: false | { preload?: boolean; mergeConfig?: boolean };
theme?: false | { preload?: boolean }; // Dashboard theme, independent of flow
});
| Option | Type | Required | Description |
|---|---|---|---|
apiURL |
string |
✅ | API base URL. |
token |
string |
✅ | Session token from createSession(). Unlike the core setup(), the web wrapper needs it up front. |
i18n |
I18nOptions |
❌ | Language selection and translation overrides. See Internationalization. |
uiConfig |
UiConfig |
❌ | Global branding and presentation: logo, subtitle, asset and animation overrides, loader presentation. See Asset Overrides and Theming & Styling. |
theme |
false | { preload?: boolean } |
❌ | Controls the dashboard theme independently of flow. Omit for lazy loading, { preload: true } to fetch and apply during setup(), or false to disable it. See Individual Modules. |
customHeaders, timeout, wasm, ipLookup, fingerprint, devMode, featureManagement, environment, flow |
same as core | ❌ | Forwarded to the core setup() unchanged — see the table above. |
createSession()
Create a verification session (call from your backend for production):
import { createSession } from '@incodetech/core/session';
const session = await createSession(apiKey, {
configurationId: string; // Required: Flow configuration ID from dashboard
language?: string; // Optional: Language code (e.g., 'en-US')
externalId?: string; // Optional: Your user reference ID
});
// Returns: { token: string; interviewId: string; ... }
initializeSession()
Activate a session by attaching the token to the HTTP client and pre-loading session-scoped state (feature flags, device fingerprint, analytics flush). Call once you have a session token — typically right after createSession() (or after your backend returns the token).
import { initializeSession } from '@incodetech/core/session';
await initializeSession({
token: string; // Required in application code: the session token from createSession()
hostingApp?: string; // Optional: hosting-app identifier forwarded to fingerprinting
signal?: AbortSignal; // Optional: abort the activation (e.g. on unmount)
});
// Returns: { features, disableIpify, fingerprintSuccess, fingerprintResult }
| Option | Type | Required | Description |
|---|---|---|---|
token |
string |
✅ | Session token returned by createSession(). Application code should always pass this explicitly. |
hostingApp |
string |
❌ | Hosting-app identifier forwarded to the fingerprinting service. |
signal |
AbortSignal |
❌ | Cancellation signal — useful for unmount-aborts in single-page apps. |
Results are cached per token: calling initializeSession again with the same token is a no-op; calling with a different token resets the cache and re-initializes from scratch. Idempotent across concurrent callers — a second in-flight call with the same arguments awaits the first.
Feature management
@incodetech/core/feature-management is the read surface for the gates, experiments, layers, and dynamic configs evaluated for the current session. The SDK handles initialization and identity itself during setup() and session activation — this subpath only reads. It ships as a separate subpath so integrations that never read a gate do not pay for it.
Incode agrees the gate and experiment keys with you; they are not self-serve.
import {
getFeatureGate,
getExperiment,
getLayer,
getFeatureDynamicConfig,
subscribeFeatureManagement,
} from '@incodetech/core/feature-management';
if (getFeatureGate('your_gate_key').enabled) {
// gated behavior
}
const experiment = getExperiment('your_experiment_key');
const variant = experiment.get('variantName', 'control');
const layer = getLayer('your_layer_key');
const timeoutMs = layer.get('timeoutMs', 10_000);
| Function | Returns | Description |
|---|---|---|
getFeatureGate(key) |
FeatureManagementGate |
Reads a boolean gate. Check .enabled. |
getExperiment(key) |
FeatureManagementExperiment |
Reads an experiment. Call .get(param, fallback) per parameter. |
getLayer(key) |
FeatureManagementLayer |
Reads a layer. Call .get(param, fallback) per parameter. |
getFeatureParameterStore(key, opts?) |
FeatureManagementParameterStore |
Reads a parameter store. |
getFeatureDynamicConfig(key) |
object or null |
Reads a dynamic config. |
subscribeFeatureManagement(fn) |
unsubscribe function | Notifies you when values change during the session, as identity is enriched. |
updateFeatureManagementUser(update) |
void |
Adds your own custom IDs to the evaluation identity. |
getIsFeatureManagementInitialized() |
boolean |
Whether initialization has finished. |
logEvent(...) |
void |
Records a custom event against the current identity. |
Every function here is graceful and none of them throw. Before setup() finishes, and whenever setup({ featureManagement: false }) disabled the integration, reads resolve to documented defaults: gates return false, experiments and layers return your fallback, and dynamic configs return null. Code that reads a gate stays correct with the integration switched off, so you can disable it without branching.
Components
<incode-flow>
Complete verification flow as a standard Web Component.
// Side-effect import registers the custom element
import '@incodetech/web/flow';
import '@incodetech/web/flow/styles.css';
| Property | Type | Required | Description |
|---|---|---|---|
config |
FlowConfig |
✅ | Flow configuration object |
onFinish |
(result?: FinishStatus) => void |
✅ | Called when flow completes |
onError |
(error: string | undefined, errorCode?: number) => void |
❌ | Called when an error occurs |
FlowConfig
apiURL is configured via setup(), not in FlowConfig.
| Property | Type | Required | Description |
|---|---|---|---|
token |
string |
✅ | Session token from createSession() (token-based variant) |
apiKey (or clientId) + configurationId |
string |
✅ (alt) | Self-loading variant — component creates its own session. Avoid in production. |
lang |
string |
❌ | Language code (e.g. 'en-US') |
enableHome |
boolean |
❌ | Show the SDK's built-in home screen |
authHint |
string |
❌ | QR/auth hint when re-entering a flow |
urlUuid |
string |
❌ | QR anti-phishing token from URL |
wasmConfig |
WasmConfig |
❌ | WASM configuration for ML features |
spinnerConfig |
SpinnerConfig |
❌ | Loading spinner customization |
disableDashboardTheme |
boolean |
❌ | Disable dashboard theme |
onFlowEvent |
(event: FlowEvent) => void |
❌ | Curated flow milestones |
onModuleLoading |
(moduleKey: string) => void |
❌ | Called when module starts loading |
onModuleLoaded |
(moduleKey: string) => void |
❌ | Called when module finishes loading |
onWasmWarmup |
(pipelines: string[]) => void |
❌ | Called when WASM warmup begins |
onUrlUuidRefreshed |
(urlUuid: string) => void |
❌ | New urlUuid available |
Other components
The SDK ships 20+ web components in addition to IncodeFlow — selfie, ID capture, phone, email, signature, consent, eKYC/eKYB orchestrators, and more. Rather than duplicate them here, see:
- Individual Modules: complete catalog of every web component and headless manager with import paths
- Web Components: tag-table reference for vanilla / framework-agnostic usage
- Module: Selfie, Module: ID, Module: Phone, Module: Email: deep-dive reference pages for the four most-used capture modules, including config tables, state machines, and full API surfaces
Headless Managers
Every module ships a corresponding createXxxManager factory for headless integrations. The full catalog (manager name, core import, what it does) lives in Individual Modules; detailed lifecycle, state, and method documentation for each manager lives in Headless Mode.
For the four most-used headless APIs, see:
- Module: Selfie § API Methods
- Module: ID § API Methods
- Module: Phone § API Methods
- Module: Email § API Methods
See Also
- TypeScript Types: Type definitions
- Headless Mode: Detailed headless API
- Individual Modules: Complete module catalog