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:
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?.
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.
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.
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 and 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. |
| 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. |
| 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:
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, Fiscal QR, and 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:
import type { IdCaptureState } from '@incodetech/core/id';
function acceptedDocumentNames(state: IdCaptureState): string[] {
if (state.status !== 'capture') return [];
return state.acceptedDocuments ?? [];
}
See 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.
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:
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 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:
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.
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.
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 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 and update your old initializing / error handling to its supported states.