SDK reference, Incode Web SDK 2 Reference / Reference

Web SDK 2.0 API Reference

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 i18n, uiConfig, and theme. Both entry points support flow; their feature-management option types differ as described below.

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 back end creating the session. Core's setup() accepts optional apiURL and token properties. setup() pairs with initializeSession(); the web wrapper requires token up front.
  • You need an option the web wrapper does not accept — encryption, tri, or trueSight. 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 with the same preload and mergeConfig semantics. 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)
  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. Use true only during local development.
  tri?: { token: string; apiURL: string; autostart?: boolean }; // Optional TRI telemetry config
  trueSight?: { enabled?: boolean };                   // Temporarily unavailable; option accepted for compatibility.
  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 }). 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.
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. Default true; set false to skip submission. With false, Flows and Workflows do not automatically add mandatory consent; your integration must handle any required consent.
devMode boolean ❌ Development mode. Default false; use true only for local development; keep it false in production. WASM console logging is controlled separately by wasm.showLogs; see WASM Configuration.
tri { token: string; apiURL: string; autostart?: boolean } ❌ Transactional Risk Intelligence (TRI) telemetry. Provide token (an 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 } ❌ Diagnostics are temporarily unavailable in this release. The option remains accepted for compatibility, but enabled: true and server flags cannot activate collection or uploads. Regular SDK analytics are unaffected.
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
awaitInitialization boolean false Whether setup() waits for gate and experiment values to load before it resolves. By default, setup() resolves as soon as the HTTP client is ready (typically 150–250 ms sooner) while values load in the background; reads made before that settle return their defaults (status: 'uninitialized'). Await getIsFeatureManagementInitialized() when you need one that early, or set true to block setup() until they are loaded. <incode-flow>, <incode-workflow>, and the SDK's own modules are unaffected.
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 from 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 | { clientExperimentId?: string; disableStableId?: boolean; disablePersistence?: boolean; redactedUserInfo?: FeatureManagementRedactedUserInfo };
  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, environment, flow same as core ❌ Forwarded to the core setup() unchanged — see the table above.

Web setup accepts only clientExperimentId, disableStableId, disablePersistence, and redactedUserInfo in its feature-management object. Core additionally accepts custom, appVersion, and awaitInitialization. Use core setup when you need those fields, and configure presentation as described above; they are not accepted in a web setup object literal in 2.3.0.

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()
  signal?: AbortSignal;     // Optional: abort the activation (e.g. on unmount)
  preloadFlow?: boolean;    // Optional: fetch the flow configuration alongside activation
  awaitFingerprint?: boolean; // Optional: false resolves before the device fingerprint finishes (default true)
});

// Returns: { features, disableIpify, fingerprintSuccess, fingerprintResult }
Option Type Required Description
token string ✅ Session token returned by createSession(). Application code should always pass this explicitly.
signal AbortSignal ❌ Cancellation signal; useful for unmount-aborts in single-page apps.
preloadFlow boolean ❌ Fetch the flow configuration in the same request wave as activation, so a later getFlow() or flow manager load() hits the cache. Default false.
awaitFingerprint boolean ❌ false resolves as soon as the feature config is in and lets device-fingerprint submission finish in the background. fingerprintSuccess / fingerprintResult on the result are then not yet known; read them via whenSessionFingerprintSettled(). Default true.

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.

whenSessionFingerprintSettled()

Use with to awaitFingerprint: false. Resolves with the DeviceFingerprintResult after the background fingerprint finishes, or undefined when fingerprinting failed or was skipped. Never rejects. If the fingerprint was already awaited, it resolves immediately with the cached result.

import { initializeSession, whenSessionFingerprintSettled } from '@incodetech/core/session';

const { features } = await initializeSession({ token, awaitFingerprint: false });
renderHome(features);

const fingerprint = await whenSessionFingerprintSettled();
if (fingerprint?.showMandatoryConsent) showConsent(fingerprint.regulationType);

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. setup() does not wait for gate and experiment values to load: it resolves as soon as the HTTP client is ready and the values arrive in the background, so a read made immediately after await setup() may still see the defaults below. When you need a real value that early, call await getIsFeatureManagementInitialized() first, or pass setup({ featureManagement: { awaitInitialization: true } }) to make setup() block until values are loaded. <incode-flow>, <incode-workflow>, and the SDK's own modules never need either: they read after the session identity update, which waits for loading itself. Before values load, 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
redirectToMobileUrl string ❌ Override the destination URL for the Redirect to Mobile step
urlUuid string ❌ QR anti-phishing token from URL
injectCss boolean ❌ Opt into automatic Flow and lazy module stylesheet loading. Default false. Keep base/theme CSS imports.
cssNonce string ❌ CSP nonce for stylesheets injected when injectCss is enabled.
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:

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:

Legacy Flow manager

The manager also provides subscribeFlowEvent(listener) for curated milestones. It returns an unsubscribe function; see headless flow events for subscription and teardown.

createFlowManager() from @incodetech/core/flow loads a Flow and exposes manual step navigation. Prefer createOrchestratedFlowManager for automatic module orchestration.

Method/Getter Contract
load() Start loading in idle.
cancel() Cancel in loading, returning to idle.
nextStep() Advance in ready; the last step reaches finished.
prevStep() Move backward in ready when not on the first step.
canNext True in ready when another step follows. False on the last step, although nextStep() can finish it.
canPrev True in ready when a previous step exists.
getModuleConfig<T>(moduleKey) Configuration for the named module, or undefined when absent or outside ready.
isModuleEnabled(moduleKey) Whether the named module exists; false outside ready.
reset() Return to idle from ready, error, or this legacy manager's non-final finished state.

The modern orchestrator instead uses completeModule() and getModuleConfig<T>() for the current module; it has no legacy prevStep()/canPrev contract. Both support getState(), subscribe(), and stop().

See Also

Was this page helpful?