---
title: "Upgrade to Web SDK 2.3.0"
url: "https://developer.incode.com/sdk-reference/web-sdk-2-upgrade-2-3-0/"
section: "sdk-reference"
group: "Incode Web SDK 2 Reference"
version: "v1.1"
status: "live"
---
# Upgrade to Web SDK 2.3.0

This guide covers changes from 2.2.0 to 2.3.0. The replacement behavior below targets **2.3.0 or later**. Keep core and web on matching versions. Removed APIs have no compatibility period in 2.3.0; complete the applicable migration before upgrading. No later removal or restoration date is implied.

Review the sections that apply to your configuration, custom UI, deployment, or event consumers. Applications using SDK components still need to check removed imports and setup options.

## Feature-management readiness

**Before:** `await setup()` waited for feature-management initialization. A host could read a gate immediately afterward.

**In 2.3.0:** initialization runs in the background by default. Early reads can return defaults while initialization is pending. To preserve blocking behavior, use core setup with `awaitInitialization: true`:

```typescript
import { setup } from '@incodetech/core';
import { getFeatureGate } from '@incodetech/core/feature-management';

await setup({
  apiURL: 'https://demo-api.incodesmile.com',
  featureManagement: { awaitInitialization: true },
});
const gate = getFeatureGate('YOUR_GATE_NAME');
```

Alternatively, keep background initialization and await `getIsFeatureManagementInitialized()` from `@incodetech/core/feature-management` before a dependent read. It resolves to `false` if initialization is unavailable or fails; handle your configured fallback. SDK Flow, Workflow, and module-owned reads already wait where required.

If switching a component integration to core setup, retain its presentation setup as described in [Which setup do I call?](/sdk-reference/web-sdk-2-reference/#when-you-deliberately-use-cores-setup-with-web-components).

## Government Validation

**Before:** custom integrations could configure `backgroundExecution` and `maxOtpAttempts`, render OTP/result screens, and call OTP or retry methods.

**In 2.3.0:** remove those two configuration properties. The public states are `idle`, `loading`, and `finished`; `load()` starts the request. The manager still provides `subscribe()`, `getState()`, and `stop()`.

Remove calls to `submitOtp()`, `setOtpCode()`, `validateOtp()`, `resendOtp()`, and `retry()`. Remove handlers for `awaitingOtp`, `verifyingOtp`, `displaySuccess`, and `error`, and stop reading `otpResponse`.

```typescript
import { createGovernmentValidationManager } from '@incodetech/core/government-validation';

const manager = createGovernmentValidationManager({
  config: { facialValidation: true, dataValidation: true },
});
const unsubscribe = manager.subscribe((state) => {
  if (state.status === 'loading') {
    // Show progress.
  } else if (state.status === 'finished') {
    // Advance the UI; completion does not establish verification approval.
  }
});
manager.load();

function disposeGovernmentValidation() {
  unsubscribe();
  manager.stop();
}
```

The module advances after the request regardless of the validation outcome. Use your supported server-side verification result to make business decisions. See [Government Validation / INE Validation](/sdk-reference/web-sdk-2-module-gov-validation-1/).

## Form validation

**Before:** Custom Fields and Watchlist for Business gated Continue on completed input. Custom UIs could follow that completeness check.

**In 2.3.0:** Continue starts enabled, and submission validates required fields. Render the manager's validation feedback and let the manager validate submission. The optimistic `canSubmit` value means no errors are currently displayed; it does not establish that all required input is present. Watchlist for Business still exposes `isValid` separately; use `canSubmit` to enable Continue. Avoid adding a separate validation gate that hides the manager's feedback.

See [Custom Fields](/sdk-reference/web-sdk-2-module-custom-fields/) and [Watchlist for Business](/sdk-reference/web-sdk-2-module-watchlist-for-business/).

## Headless states and test fixtures

**Before:** exhaustive switches and typed fixtures could rely on the 2.2.0 unions and required fields.

**In 2.3.0:** add the following cases and fields. Read them only after narrowing `state.status`; use the linked reference for each complete payload.

| Module | Update |
| --- | --- |
| Selfie | Handle `manualUpload`, with `phase`, `uploaded`, `canContinue`, `errorKey`, and `attemptsRemaining`. Add required `showManualUploadLink` to tutorial fixtures. Offer `goToManualUpload()` only from the tutorial when the flag is true. Submit files with `manualUploadSelectFile(file)` and call `manualUploadContinue()` when `canContinue` is true. |
| ID Capture | Update `loading`, `tutorial`, and `permissions` fixtures with their new presentation fields. Render from `phase`, `selectedDocumentType`, `currentMode`, and `tutorialEnabled` where present; read `usingBackCamera` for mirroring. See [ID Capture state properties](/sdk-reference/web-sdk-2-module-id-capture/). |
| ID digital methods | Handle the `digitalIdRedirect` and `deviceWallet` states when those methods are enabled. Show redirect success until the user calls `digitalIdRedirectContinue()`. Follow the method-specific actions in [ID Capture](/sdk-reference/web-sdk-2-module-id-capture/). |
| Fiscal QR | Handle `permissionDenied` with browser-permission instructions and a page reload after correction. It is not a retryable scan-error state. |
| Dynamic Forms | Handle `submitFailed` with failure feedback and call `retry()` on user request. |

For example, a 2.2.0 Selfie tutorial fixture could contain only `status: 'tutorial'`. Its 2.3.0 replacement includes the upload-link flag:

```typescript
import type { SelfieState } from '@incodetech/core/selfie';

const tutorial: Extract<SelfieState, { status: 'tutorial' }> = {
  status: 'tutorial',
  showManualUploadLink: false,
};
```

Authentication and Selfie capture-only share face state types, but do not support the Selfie manual-upload journey. Do not enable upload controls for them. See [Selfie](/sdk-reference/web-sdk-2-module-selfie-1/), [Fiscal QR](/sdk-reference/web-sdk-2-individual-modules/#compliance-consent), and [Dynamic Forms](/sdk-reference/web-sdk-2-module-dynamic-forms/).

## Accepted document types

**Before:** `UploadIdResponse.acceptedDocuments` was declared as objects with `type` and `name`. Code could read `entry.name`.

**In 2.3.0:** each entry is a string. Read the entry directly, tolerate unknown values, and hide the list when it is absent or empty. The capture state exposes `acceptedDocuments` and `countryCode` for error presentation:

```typescript
import type { IdCaptureState } from '@incodetech/core/id';

function acceptedDocumentNames(state: IdCaptureState): string[] {
  if (state.status !== 'capture') return [];
  return state.acceptedDocuments ?? [];
}
```

See [ID Capture](/sdk-reference/web-sdk-2-module-id-capture/) for the full error-state presentation.

## Self-hosted assets and fonts

**Before:** custom deployments could copy only `base.css`, inject its text without resolving asset URLs, or reuse a flattened on-device asset mirror.

**In 2.3.0:** deploy the complete release-matched asset distribution with its directory layout intact. Refresh the full distribution rather than replacing selected files, and invalidate stale caches. Keep all supplied compatibility assets. Obtain the supported distribution and import configuration from your Incode representative; see [Hosting WASM Files](/sdk-reference/web-sdk-2-wasm/#hosting-wasm-files).

Fonts now load separately through URLs relative to the stylesheet. If you copy `base.css`, also deploy its accompanying `assets/` directory in the same relative location. If you inject stylesheet text, resolve its font URLs against the deployed asset location first. Standard bundler imports and stylesheet links that preserve the package layout need no change.

## Document Capture uploads

**Before:** Document Capture could ignore `sendBase64`, so custom upload handling might receive base64 data even when the flag was false or omitted.

**In 2.3.0:** `false` or omission uses file uploads; `true` requests base64 uploads. To retain base64 handling, explicitly set `sendBase64: true`:

```typescript
import { createDocumentCaptureManager } from '@incodetech/core/document-capture';

const manager = createDocumentCaptureManager({
  config: { processingType: 'addressStatement', sendBase64: true },
});
// Subscribe and drive the capture UI, then call manager.stop() on teardown.
```

Check any custom request adapters against the mode you select. See [Document Capture](/sdk-reference/web-sdk-2-module-document-capture/) for supported document types and upload behavior.

## Event and error handling

**Before:** interview-event consumers could filter `code === 'experimentsAssigned'`.

**In 2.3.0:** filter `code === 'experimentAssigned'`. Consumers processing events from several SDK versions should accept both names while older integrations remain active.

Flow and Workflow module-error messages are now optional. Replace unconditional string operations on `state.error` with a fallback after narrowing to `status === 'error'`. `errorCode` and `moduleErrorCode` are optional too. For example:

```typescript
import type { OrchestratedFlowState } from '@incodetech/core/flow';

function flowErrorText(state: OrchestratedFlowState): string | undefined {
  if (state.status !== 'error') return undefined;
  return state.error || 'Verification could not continue.';
}
```

Use localized fallback copy in your application. Stop matching the former `Mandatory consent error` message. Consent cancellation uses the shared error presentation; messages are not stable identifiers. Forward module codes unchanged when calling `errorModule(error?, moduleErrorCode?)`. See [Event Callbacks](/sdk-reference/web-sdk-2-event-callbacks/).

## Video Selfie terminal outcomes

**Before:** custom hosts could assume the recording continued beyond the configured duration or that exhausted validation attempts remained retryable.

**In 2.3.0:** the configured maximum recording duration is enforced. Expiration shows timeout feedback, completes the current recording, and advances after the feedback screen. Exhausted ID or face validation attempts end the attempt; standalone components report an error, while Flow advances the configured journey.

Handle these outcomes in your custom UI and callbacks; do not automatically restart an exhausted attempt. Completion or journey advancement does not establish verification approval. Review the terminal states and actions in [Video Selfie](/sdk-reference/web-sdk-2-module-video-selfie/#terminal-errors).

## Browser support screens

**Before:** an unsupported browser could enter a module without the SDK's browser-support screen.

**In 2.3.0:** SDK components show guidance for unsupported browser environments, including a link-copy action and a choice to continue. Continuing does not make that browser supported. Test any embedded-browser integration against the [Browser Support](/sdk-reference/incode-web-sdk-2-reference/#browser-support) guidance; native WebViews and third-party in-app browsers are treated differently.

## TrueSight diagnostics

**Before:** an enabled TrueSight configuration could collect diagnostics.

**In 2.3.0:** diagnostics are unavailable, and the accepted setup option has no effect. Remove any operational dependency on receiving those diagnostics. Regular SDK analytics remain available. No restoration date or replacement diagnostic collector is specified.

## Removed APIs

These removals take effect in 2.3.0. Imports, custom configuration, or direct calls must be updated before upgrading.

| Previous usage | Replacement or required action |
| --- | --- |
| `@incodetech/core/personhood` and `createPersonhoodManager()` | Remove the import and the Personhood integration. Personhood is unavailable in this release; no equivalent replacement is provided. Do not present another capture module as the same verification capability. |
| `@incodetech/core/document-upload`, its manager, machine, and related types | Use `@incodetech/core/document-capture` for supported generic-document capture/upload. This is not a drop-in replacement for third-ID verification; third-ID capture remains unsupported. |
| `recording.capability` in ID, Selfie, or Authentication config | Remove the custom provider option and its associated contract imports. Use the supported `enableIdRecording` or `enableFaceRecording` option for SDK-managed recording. A custom-provider replacement is not provided. |
| `getVersions()` on `WasmUtilProvider` imported from `@incodetech/core/extensibility` | Remove the call. There is no replacement runtime-version lookup. |

For Document Upload migration, replace `DocumentUploadConfig.documentType` with a supported `DocumentCaptureConfig.processingType` for your actual document use case. Replace `createDocumentUploadManager()` with `createDocumentCaptureManager({ config })`. The old `capture(imageBase64)` submission becomes `setFile(file, previewDataUrl)` in `tutorial` or `capturing`, followed by `accept()` in `preview` and `continue()` after upload success.

The new manager begins in `tutorial`; do not copy the old `load()` call. It does not expose a `load()` method. Use the action/state table in [Document Capture](/sdk-reference/web-sdk-2-module-document-capture/) and update your old `initializing` / `error` handling to its supported states.