Skip to main content

Web SDK

Drop-in verification flow for web apps. Modal or new-tab presentation, full TypeScript types, no peer dependencies. Requires a one-time session token from your backend.

About this SDK

The Width Web SDK is a drop-in verification experience for KYC, KYB, and one-off liveness in your web app. ESM build, full TypeScript types, no peer dependencies.

FeatureSupported
KYC
KYB
One-off liveness
TypeScript types

1. Generate an access token (backend)

Call sdk.credentials from your server using the OpenAPI signing scheme:

POST {WIDTH_GATEWAY_URL}/gateway?api=sdk.credentials&apiVersion=1.0.0&apiKey={your_apiKey}&sign=...
Content-Type: application/json
x-domain: {domainId}

{}
{
  "apiCode": 200,
  "apiMsg": "OK",
  "data": {
    "data": {
      "sdkToken": "eyJhbGciOi...",
      "domains": [
        { "code": "DEFAULT", "name": "Default", "id": "dom_xxxxxxxx" }
      ]
    }
  }
}
Each sdkToken is single-use. Reissue a new token whenever a user starts a new verification.

2. Install the SDK

npm install @width/web-sdk
# or
pnpm add @width/web-sdk
yarn add @width/web-sdk

3. Initialize

import { WidthWebSDK } from '@width/web-sdk';

const { sdkToken, domainId } =
  await fetch('/your-backend/sdk-token').then(r => r.json());

WidthWebSDK.open({
  apiKey:   'ak_your_public_api_key',
  appToken: sdkToken,
  email:    'enduser@example.com',
  domainId,
  mode:     'modal',
  onResult: handleVerificationResult,
});

4. Handle the result

import type { VerificationResult } from '@width/web-sdk';

function handleVerificationResult(result: VerificationResult) {
  switch (result.type) {
    case 'COMPLETED':
      if (result.decision === 'APPROVED') grantAccess(result.executionId);
      else showDeclined(result.executionId);
      break;

    case 'WAITING':
      persistExecutionId(result.executionId);
      showPendingReview();
      break;

    case 'FAILED':
      handleFailure(result.code, result.message);
      break;

    case 'CANCELLED':
      break;
  }
}

Launch options

Required

ParameterTypeDescription
apiKeystringYour Width public API Key (ak_...)
appTokenstringSession-level token from your backend
email or customerIdstringAt least one required

Optional

ParameterTypeDefaultDescription
customerIdstringInternal user ID
emailstringValidated format
domainIdstringTenant defaultBusiness unit ID
mode'modal' \| 'newtab''modal'UI presentation
zIndexnumber9999Modal stacking order
onResultfunctionResult callback

Methods

MethodPurpose
WidthWebSDK.open(options)Launch the KYC / KYB flow
WidthWebSDK.openLiveness(options)Launch one-off liveness
WidthWebSDK.close()Programmatically close the modal

openLiveness

const livenessToken = new URLSearchParams(window.location.search).get('token');
const { sdkToken, domainId } =
  await fetch('/your-backend/sdk-token').then(r => r.json());

WidthWebSDK.openLiveness({
  apiKey:        'ak_your_public_api_key',
  appToken:      sdkToken,
  livenessToken,
  domainId,
  mode:          'modal',
  onResult:      handleVerificationResult,
});

Verification result

type VerificationResult =
  | { type: 'COMPLETED'; executionId: string; decision: 'APPROVED' | 'REJECTED' }
  | { type: 'WAITING';   executionId: string }
  | { type: 'FAILED';    code: VerificationErrorCode; message: string; executionId?: string }
  | { type: 'CANCELLED' };

type VerificationErrorCode = 'INVALID_INPUT' | 'SDK_ERROR' | 'WORKFLOW_FAILED';
CodeMeaningRetryable
INVALID_INPUTLaunch parameter issueNo — fix code
SDK_ERRORNetwork / runtime errorYes — retry
WORKFLOW_FAILEDNon-success workflow stateNo — contact support

Browser support

PlatformMinimum
Chrome / Edge92+
Firefox95+
Safari (desktop & iOS)15.4+
Chrome (Android)92+

The SDK relies on crypto.randomUUID, ES2020 syntax, and modern fetch + postMessage. Older browsers are not supported.

CSP & Permissions Policy

Content-Security-Policy: frame-src https://<width-verify-origin>;
Permissions-Policy: camera=(self "https://<width-verify-origin>"),
                    microphone=(self "https://<width-verify-origin>"),
                    accelerometer=(self "https://<width-verify-origin>"),
                    gyroscope=(self "https://<width-verify-origin>")

In the Width Admin Console, add your domain under SSO & Integration → API Keys & Webhooks → Web SDK Settings → Allowed Origins.

Troubleshooting

SymptomCauseResolution
apiKey is required.Missing apiKeyPass the public API Key
appToken is required.Backend issueCheck sdk.credentials integration
email format is invalid.Invalid formatValidate in your form first
apiKey / appToken mismatchDifferent apps / tenantsReissue token with the same key
SDK_ERRORNetwork issueRetry open()
Modal won't appearDomain not allowlisted / bad CSPAdd domain, update CSP
Camera deniedStrict Permissions-PolicyUpdate policy headers
onResult never firesSession ongoing or callback missingWait or confirm the callback