This guide covers changes from 2.3.x to 2.4.0. The replacement behavior below targets 2.4.0 or later. Keep core and web on matching versions. Removed APIs have no compatibility period in 2.4.0; complete the applicable migration before upgrading.
Warning
This guide is specific to Web SDK 2.x. For Web SDK 1.x, you can find documentation here.
Do not attempt to upgrade or implement without support. Contact your Incode representative to check if you are a candidate for this upgrade.
Review the sections that apply to your configuration, custom UI, deployment, or styles. Applications using SDK components still need to check removed configuration options.
Manual upload removal
Before: manualUploadIdCapture and manualUploadSelfieCapture let the user upload an ID or selfie image from a file. Custom UIs handled the manualUpload state and called the manual-upload methods.
In 2.4.0: both options are removed, together with their states, methods, and fields. Use camera capture or Digital ID for supported documents.
| Previous usage | Required action |
|---|---|
manualUploadIdCapture in ID Capture configuration |
Remove the option. |
ID Capture manualUpload state, manualUploadChangeTab(tab), manualUploadSelectFile(side, file), manualUploadContinue(), and manualUploadReset() |
Remove the state handler and the calls. |
manualUploadSelfieCapture in Selfie configuration |
Remove the option. |
Selfie manualUpload state, goToManualUpload(), manualUploadSelectFile(file), and manualUploadContinue() |
Remove the state handler and the calls. |
showManualUploadLink in Selfie tutorial state fixtures |
Remove the field from typed fixtures. |
WASM integrity checks
Before: the SDK ran the WASM binaries, glue files, and models that it downloaded.
In 2.4.0: the SDK checks each WASM file against the official files for its release before it runs the file. The check applies wherever the files are hosted: the Incode CDN or a self-hosted copy. If a file does not match, the SDK does not run it and WASM initialization fails.
- Strict Content-Security-Policy: the SDK loads the verified glue from a
blob:URL. Addblob:to yourscript-srcdirective. - Self-hosted WASM: serve the unmodified distribution that matches your SDK version. Files from another release no longer load, so refresh the full distribution each time you upgrade. See Hosting WASM Files.
- Secure pages: the check needs
crypto.subtle, which browsers expose only on pages served over HTTPS or fromlocalhost.
For each integrity error code and its fix, see Troubleshooting.
Capture-only ID responses
Before: CaptureOnlyResponse.frontImage was always present, and a back-only capture (onlyBack: true) did not call onCapture. With an onCapture callback, createIdCaptureManager and <incode-id> could run the regular upload flow instead of the capture-only flow.
In 2.4.0: CaptureOnlyResponse is a union. frontImage is undefined for a back-only capture, which now calls onCapture with the back image. TypeScript code that reads response.frontImage.blob no longer compiles. Check frontImage first:
import type { CaptureOnlyResponse } from '@incodetech/core/id';
declare function uploadToMyBackend(front?: Blob, back?: Blob): Promise<void>;
async function handleCapture(response: CaptureOnlyResponse) {
await uploadToMyBackend(response.frontImage?.blob, response.backImage?.blob);
}
An ID configuration with onCapture now always runs the capture-only flow. Nothing is uploaded, and only the capture-only fields apply: showTutorial, captureAttempts, autoCaptureTimeout, deviceIdleTimeout, enableId, enablePassport, onlyFront, onlyBack, and showDocumentChooserScreen. Runtime behavior for front and front-and-back captures does not change. See ID Capture.
Identity Reuse
Before: the user selected a document on a radio card, then confirmed with a separate button.
In 2.4.0: a tap on a document card or on "Scan a new document" submits that choice at once. The screen also adds a "What data will be shared?" sheet and a link to Incode's Privacy Policy.
- Custom UIs: call
submit(documentId)with a document id orSCAN_NEW_DOCUMENT.submit()without an argument still submits the current selection, andchooseDocument(documentId)still works for two-step UIs. Both ignore ids that are not among the offered documents. - Organization name: the
documentsFoundstate has an optionalcompanyName. Name the receiving organization when it is present and use generic copy when it is absent. - Loading state:
loadingis now a parallel state, so itssnapshot.valueis an object. Usesnapshot.matches('loading')instead of a value comparison. - Machine overrides: if you override actors with
identityReuseMachine.provide(), also provide the newfetchCompanyNameactor, typed withFetchCompanyNameResponse. Otherwise, the real request runs. - Styles and tests: the radio-picker class names
IncodeIdentityReuseCardSelected,IncodeIdentityReuseRadio,IncodeIdentityReuseRadioChecked,IncodeIdentityReuseRadioInner,IncodeIdentityReuseCardBody,IncodeIdentityReuseCardHeaderLeft, andIncodeIdentityReuseScanNewBodyare removed. Theidentity-reuse-confirm-buttontest id is removed. Update stylesheets and tests that target them.
import {
createIdentityReuseManager,
SCAN_NEW_DOCUMENT,
} from '@incodetech/core/identity-reuse';
const manager = createIdentityReuseManager({ config: {} });
// Call from the "Scan a new document" card.
function scanNewDocument() {
manager.submit(SCAN_NEW_DOCUMENT);
}
See Identity Reuse.
Flow completion redirects
Before: the flow completion screen navigated to any redirectionUrl.
In 2.4.0: the SDK navigates only to an absolute https URL. For any other value, the completion screen shows, and the console logs a warning. For local development, an http://localhost URL is allowed while the page itself runs on localhost. The Digital ID bank redirect uses the same rule.
Change any http redirect URL in your flow configuration to https.
Session expiry
Before: when the current session expired, the next request failed inside the module, and each module handled that failure separately.
In 2.4.0: when a request for the current session returns HTTP 401, the SDK ends every mounted module, Flow, and Workflow, and releases the camera. It then calls onError once, with SESSION_EXPIRED as the third argument and the error object as the fourth:
onError('Session expired', 401, 'SESSION_EXPIRED', error);
- Components: handle
SESSION_EXPIREDinonError, for example by starting a new session and mounting a new element. - Host-supplied managers: the SDK stops a manager that you pass through the
managerprop. A stopped manager cannot be reused, so create a new one for the replacement session. - Headless integrations: subscribe with
onSessionExpired(). Each subscription is called once.
import { onSessionExpired } from '@incodetech/core/session';
const unsubscribe = onSessionExpired((error) => {
// error.code is 'SESSION_EXPIRED' and error.statusCode is 401.
// Stop your managers, start a new session, and create new managers.
});
// Call unsubscribe() when the owner of the subscription unmounts.
A connection failure with no HTTP status does not expire the session. Requests that do not carry the session token do not expire it either.
Workflow completion copy
Before: onFinish for <incode-workflow> returned endScreenTitle and endScreenText as null, even when Dashboard had custom completion copy.
In 2.4.0: self-loading Workflows fill both fields from Dashboard. In token mode, the SDK does not see your session response. Forward both values from the response to the component:
<incode-workflow
config={{ token: sessionToken, endScreenTitle, endScreenText }}
onFinish={handleFinish}
/>
See Workflow.
Field Comparison validation
Before: Field Comparison enabled Continue only after the user completed the first and last name.
In 2.4.0: Continue starts enabled. Submitting a blank first or last name shows a required-field error for each missing value and disables Continue until the user corrects them. In a custom UI, render the manager's validation feedback and do not add a separate completeness gate. See Field Comparison.