WASM Configuration

WebAssembly (WASM) powers the SDK's on-device ML pipelines — face detection and liveness for the Selfie module, document detection and quality scoring for the

📘

This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation here. We strongly recommend upgrading - contact your Incode Representative for upgrade information.

WebAssembly (WASM) powers the SDK's on-device ML pipelines — face detection and liveness for the Selfie module, document detection and quality scoring for the ID Capture module.

When WASM is Required

The SDK ships the following ML pipelines, all delivered as WebAssembly:

PipelineUsed byDefault warmup?What it does
selfie<incode-selfie>, <incode-authentication> (via createAuthenticationManager), createSelfieManager✅ when pipelines omittedFace detection, positioning feedback, liveness analysis.
idCapture<incode-id>, createIdCaptureManager✅ when pipelines omittedDocument detection plus blur / glare / barcode quality checks during capture.
onDeviceSelfieSelfie / Authentication when onDeviceFaceResultsSubmissionEnabled: true❌ opt-in onlyOn-device face-results pipeline. Computes the face analysis client-side; the SDK submits the results to the server only.

onDeviceSelfie is opt-in — it is not in the default pipelines set and is only loaded when a Selfie or Authentication config has onDeviceFaceResultsSubmissionEnabled: true (see Module: Selfie and Module: Authentication).

WASM is not needed for phone verification, email verification, consent, redirect-to-mobile, or any flow that doesn't include the selfie or ID-capture modules — unless you enable End-to-end encryption, which routes all SDK traffic through the WASM transport.

Configuration

The simplest integration is the wasm option on setup(). It accepts a WasmConfig object, the literal false, or can be omitted entirely:

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

// 1. Default: omit the option — the SDK does NOT preload WASM.
//    It loads lazily on first selfie or ID capture.
await setup({ apiURL: 'https://demo-api.incodesmile.com' });
await initializeSession({ token: 'your-session-token' });

// 2. Preload using Incode's CDN defaults (recommended for most apps).
//    Paths and model files come from the CDN; you only choose pipelines.
await setup({
  apiURL: 'https://demo-api.incodesmile.com',
  wasm: { pipelines: ['selfie'] }, // or ['selfie', 'idCapture']
});
await initializeSession({ token: 'your-session-token' });

// 3. Self-hosted: override paths individually. Anything you omit
//    falls back to the CDN default.
await setup({
  apiURL: 'https://demo-api.incodesmile.com',
  wasm: {
    wasmPath: '/wasm/webLib.wasm',
    glueCodePath: '/wasm/webLib.js',
    modelsBasePath: '/wasm/models',
  },
});
await initializeSession({ token: 'your-session-token' });

// 4. Explicitly disable WASM warmup (e.g. when this page only runs
//    phone or email verification, and you want to skip the bundle cost).
await setup({ apiURL: 'https://demo-api.incodesmile.com', wasm: false });
await initializeSession({ token: 'your-session-token' });

Each snippet pairs setup({ apiURL, wasm? }) (which provisions the HTTP client and optionally warms up WASM) with initializeSession({ token }) (which activates the session). The one-shot form setup({ apiURL, token }) is still supported and delegates to initializeSession internally — splitting them out lets you start setup before the session token exists, e.g. to begin WASM warmup while createSession is still in flight.

Advanced: warmupWasm() directly

For headless integrations or callers that want to pre-warm WASM before setup() runs (or with stricter typing), import the underlying helper from @incodetech/core/wasm:

import { warmupWasm } from '@incodetech/core/wasm';

await warmupWasm({
  wasmPath: '/wasm/webLib.wasm',
  wasmSimdPath: '/wasm/webLibSimd.wasm', // optional SIMD variant
  glueCodePath: '/wasm/webLib.js',
  modelsBasePath: '/wasm/models', // default: inferred from wasmPath
  pipelines: ['selfie', 'idCapture'], // default: both pipelines
});

WarmupConfig (the type that warmupWasm accepts) requires wasmPath and glueCodePath. WasmConfig (the type setup({ wasm }) accepts) makes those optional and fills missing fields from the Incode CDN.

WarmupConfig properties

PropertyTypeRequiredDescription
wasmPathstringPath to the .wasm binary
glueCodePathstringPath to the JS glue code
wasmSimdPathstringSIMD-optimized .wasm (falls back to wasmPath)
glueCodeSimdPathstringPath to the SIMD-optimized glue code (paired with wasmSimdPath). Defaults to a sibling .js derived from wasmSimdPath.
useSimdbooleanUse SIMD when available (default: true)
pipelinesWasmPipeline[]Pipelines to preload (default: ['selfie', 'idCapture'])
modelsBasePathstringBase path for model files (default: derived from wasmPath)
pipelineModelsobjectOverride model file names per pipeline

WasmPipeline is 'selfie' | 'idCapture' | 'onDeviceSelfie'. Add 'onDeviceSelfie' only when you've also enabled onDeviceFaceResultsSubmissionEnabled on the relevant Selfie or Authentication config.

End-to-end encryption

Setting setup({ encryption: true }) opts the SDK into end-to-end-encrypted transport for every request. The encrypted transport runs over the WASM binary channel — the legacy plain fetch / XHR transport does not support E2EE.

⚠️

Not a self-serve flag — contact your Incode account team first. E2EE has to be provisioned for your account. Once enabled, Incode will give you:

  1. A dedicated apiURL to point at — E2EE traffic is served from a different host than the regular API. Pointing encryption: true at your standard apiURL will fail the handshake at setup().
  2. The mgf1 scheme that environment expects ('sha1' by default, or 'sha256' for some environments) — pass it via encryption: { mgf1: 'sha256' }.

Both values are dictated by the environment Incode has provisioned for you, not by you. Don't guess — confirm with your account team.

Other constraints:

  • setup({ wasm: false, encryption: true }) throws. Either omit wasm (the SDK provisions the binary transport with CDN defaults automatically) or pass a WasmConfig object alongside encryption: true.
  • encryption: true does not require a session token. The handshake runs as part of setup() itself, before any per-session calls.
  • Encryption is locked at boot. The first setup() call decides whether encryption is on, and which mgf1 scheme is used. Subsequent setup() calls that would change either value throw. Call reset() first if you genuinely need to switch.
  • If the handshake fails (unreachable apiURL, environment without E2EE provisioning, mismatched mgf1, transient network or server error), setup() rejects with a descriptive error. There is no built-in retry — catch and re-call.
// apiURL here is the dedicated E2EE host Incode provisioned for your account
// (not your standard apiURL).
await setup({
  apiURL: 'https://<your-incode-e2ee-host>',
  encryption: true, // binary transport provisioned automatically; uses default mgf1 ('sha1')
});

// With an explicit mgf1 scheme (use whichever Incode tells you to use):
await setup({
  apiURL: 'https://<your-incode-e2ee-host>',
  encryption: { mgf1: 'sha256' },
});

// With self-hosted WASM:
await setup({
  apiURL: 'https://<your-incode-e2ee-host>',
  encryption: true,
  wasm: {
    wasmPath: '/wasm/webLib.wasm',
    glueCodePath: '/wasm/webLib.js',
    modelsBasePath: '/wasm/models',
  },
});

Hosting WASM Files

Copy WASM files to your public assets directory:

public/
  wasm/
    webLib.wasm
    webLibSimd.wasm
    webLib.js
    models/
      *.ortmodelv2

Server Configuration

Ensure your server serves WASM files with correct headers:

Content-Type: application/wasm

Nginx:

types {
  application/wasm wasm;
}

Apache:

AddType application/wasm .wasm

SIMD Support

The SDK automatically uses SIMD-optimized WASM when the browser supports it, falling back to standard WASM otherwise. Provide both files for best compatibility.

Lazy Loading

If you don't pass a wasm option to setup(), WASM stays unloaded until the first <incode-selfie> or <incode-id> (or their headless createSelfieManager / createIdCaptureManager counterparts) actually needs it. This keeps the initial bundle small for pages that only run phone, email, or consent flows. For latency-sensitive selfie/ID flows, prefer wasm: { pipelines: [...] } so warmup runs while the user is on earlier steps.

Troubleshooting

IssueSolution
WASM not loadingCheck file paths and server MIME types
404 errorsVerify files are in your public directory
Face detection not workingEnsure models are in the correct path

See Also