> ## Documentation Index
> Fetch the complete documentation index at: https://developer.verilock.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Web JavaScript

> Official Web SDK with verification modal and API client.

## Overview

The Web SDK ships two modules:

| Module               | File                   | Purpose                                        |
| -------------------- | ---------------------- | ---------------------------------------------- |
| **VerilockIdentity** | `verilock-identity.js` | Drop-in modal widget for end-user verification |
| **VerilockApi**      | `verilock-api.js`      | Server-side API client for full API access     |

<Warning>
  **VerilockIdentity** is designed for frontend use with a session token. **VerilockApi** requires an API key and must only be used from a backend server or secure environment.
</Warning>

***

## Installation

### Script tag

```html theme={null}
<!-- Modal widget (frontend) -->
<script src="https://cdn.verilock.io/js/verilock-identity.js"></script>

<!-- API client (backend / Node.js) -->
<script src="https://cdn.verilock.io/js/verilock-api.js"></script>
```

### ES module

```javascript theme={null}
import { VerilockIdentity } from './verilock-identity.js';
import { VerilockApi } from './verilock-api.js';
```

### npm

```bash theme={null}
npm install @verilock/web-sdk
```

```javascript theme={null}
const { VerilockIdentity } = require('@verilock/web-sdk/identity');
const { VerilockApi } = require('@verilock/web-sdk/api');
```

***

## Modal Verification Widget

`VerilockIdentity` renders a full-screen modal that walks the user through document capture, selfie, and verification -- all inside the browser.

### Quick start

```javascript theme={null}
const qi = new VerilockIdentity({
  sessionToken: 'tok_abc123',
  onComplete: (result) => {
    console.log('Decision:', result.decision);  // 'approved' or 'declined'
    console.log('Risk score:', result.risk_score);
  },
  onError: (error) => {
    console.error('Verification failed:', error.message);
  },
});

qi.start();
```

### Configuration

```javascript theme={null}
new VerilockIdentity({
  // Required
  sessionToken: 'tok_abc123',

  // Callbacks
  onComplete: (result) => { /* Verification finished */ },
  onError: (error) => { /* Something went wrong */ },
  onStep: (step) => { /* Step changed: 'welcome', 'doc_front', 'doc_back', 'selfie', 'processing', 'result' */ },

  // Theme customization
  theme: {
    primaryColor: '#6366f1',   // Brand color for buttons and accents
    logoUrl: 'https://example.com/logo.png',  // Shown on the welcome screen
    borderRadius: '12px',
  },

  // Text overrides
  text: {
    welcomeTitle: 'Identity Verification',
    welcomeSubtitle: 'We need to verify your identity. This is quick and secure.',
    welcomeButton: 'Get started',
    docFrontTitle: 'Front of your document',
    docFrontSubtitle: 'Take a photo or upload the front of your government-issued ID.',
    docBackTitle: 'Back of your document',
    docBackSubtitle: 'Take a photo or upload the back of your document.',
    selfieTitle: 'Take a selfie',
    selfieSubtitle: 'Position your face in the frame. Ensure good lighting.',
    processingTitle: 'Verifying your identity',
    processingSubtitle: 'This usually takes less than a minute.',
    successTitle: 'Verification Complete',
    successSubtitle: 'Your identity has been successfully verified.',
    failureTitle: 'Verification Unsuccessful',
    failureSubtitle: 'We were unable to verify your identity.',
  },

  // Optional
  baseUrl: 'https://identity.verilock.io',  // Override API endpoint
});
```

### Methods

| Method      | Description                                    |
| ----------- | ---------------------------------------------- |
| `start()`   | Open the verification modal and begin the flow |
| `destroy()` | Close the modal and release camera resources   |

### Verification steps

The modal progresses through these steps automatically:

1. **welcome** -- Greeting screen with instructions
2. **doc\_front** -- Capture front of ID (camera or file upload)
3. **doc\_back** -- Capture back of ID
4. **selfie** -- Selfie capture with face oval guide
5. **processing** -- Animated progress while the API verifies
6. **result** -- Approved or declined screen

Each step supports both camera capture and file upload. If the browser does not support camera access, it falls back to file upload automatically.

<Tip>
  Use the `onStep` callback to track user progress in your analytics or show custom UI alongside the modal.
</Tip>

### Closing the modal

The user can close the modal by clicking outside it or pressing the close button. You can also close it programmatically:

```javascript theme={null}
qi.destroy();
```

***

## API Client

`VerilockApi` is a full-featured client for the Verilock REST API. It uses `fetch()` and works in modern browsers (for server-side rendering) and Node.js 18+.

### Initialize

```javascript theme={null}
const api = new VerilockApi({
  apiKey: 'qi_live_...',
  baseUrl: 'https://verilock.io/api/v1',  // default
  timeout: 30000,   // request timeout in ms (default: 30s)
  maxRetries: 2,    // retries on 429/5xx (default: 2)
});
```

### Sessions

```javascript theme={null}
// Create a verification session
const session = await api.sessions.create({
  applicant_email: 'john@example.com',
  external_id: 'user_12345',
  redirect_url: 'https://example.com/callback',
  metadata: { plan: 'premium' },
});

// List sessions
const list = await api.sessions.list({
  status: 'completed',
  decision: 'approved',
  per_page: 20,
});

// Retrieve a session
const detail = await api.sessions.retrieve('ses_abc123');

// Upload a document
await api.sessions.uploadDocument('ses_abc123', fileBlob, 'front', 'passport');

// Upload a selfie
await api.sessions.uploadSelfie('ses_abc123', selfieBlob);

// Submit for evaluation
await api.sessions.submit('ses_abc123');
```

### AML Screening

```javascript theme={null}
// Screen a person
const aml = await api.aml.screen({
  name: 'John Doe',
  date_of_birth: '1990-01-15',
  nationality: 'US',
});

// Retrieve result
const amlResult = await api.aml.retrieve(aml.id);

// Submit decision
await api.aml.decide(aml.id, { decision: 'clear', notes: 'No matches found.' });
```

### Transaction Screening

```javascript theme={null}
// Screen a transaction
const tx = await api.transactions.screen({
  transaction_ref: 'TX-001',
  sender_name: 'Alice Smith',
  sender_country: 'US',
  receiver_name: 'Bob Johnson',
  receiver_country: 'NG',
  amount: 5000,
  currency: 'USD',
  transaction_type: 'wire_transfer',
});

// Batch screening
const batch = await api.transactions.screenBatch({
  transactions: [
    { transaction_ref: 'TX-002', sender_name: 'Alice', receiver_name: 'Charlie', amount: 200, currency: 'EUR' },
    { transaction_ref: 'TX-003', sender_name: 'Alice', receiver_name: 'Diana', amount: 15000, currency: 'USD' },
  ],
});

// List with risk filter
const highRisk = await api.transactions.list({ risk_level: 'high', per_page: 50 });

// Get available transaction types
const types = await api.transactions.listTypes();
```

### Wallet Screening

```javascript theme={null}
// Screen a crypto wallet
const wallet = await api.wallet.screen({
  address: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD08',
  network: 'ethereum',
});

const walletResult = await api.wallet.retrieve(wallet.id);
```

### Credentials

```javascript theme={null}
// Create a reusable KYC credential
const cred = await api.credentials.create({
  session_id: 'ses_abc123',
  shared_fields: ['full_name', 'date_of_birth', 'document_number'],
  expires_in_days: 365,
});

// Verify a credential token
const verified = await api.credentials.verify({ token: 'cred_token_...' });

// Revoke
await api.credentials.revoke(cred.id);
```

### Additional endpoints

```javascript theme={null}
// Biometric authentication
await api.biometric.authenticate('ses_abc123', selfieBlob, 0.85);
const bioResult = await api.biometric.retrieve('bio_abc123');

// Government database validation
const providers = await api.database.listProviders();
const dbResult = await api.database.validate({
  provider: 'ng_nin',
  first_name: 'John',
  last_name: 'Doe',
  document_number: '12345678901',
});

// Face search (1:N duplicate detection)
const faces = await api.faceSearch.search({ session_id: 'ses_abc123', threshold: 0.9 });

// Age verification
await api.ageVerify.verify(photoBlob, 18);
```

***

## Integration Patterns

### Modal (recommended)

The default `VerilockIdentity` modal overlays your page. Best for single-page apps and checkout flows:

```javascript theme={null}
new VerilockIdentity({ sessionToken: token, onComplete }).start();
```

### Iframe embed

Embed the hosted verification page in an iframe for a contained experience:

```html theme={null}
<iframe
  src="https://identity.verilock.io/verify/tok_abc123"
  width="480"
  height="700"
  allow="camera"
  style="border: none; border-radius: 12px;"
></iframe>
```

Listen for completion via `postMessage`:

```javascript theme={null}
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://identity.verilock.io') return;
  if (event.data.type === 'verification_complete') {
    console.log('Decision:', event.data.decision);
  }
});
```

### Redirect

Redirect the user to the hosted verification page. They return to your `redirect_url` when finished:

```javascript theme={null}
// Create session with redirect URL on your backend
const session = await api.sessions.create({
  applicant_email: 'john@example.com',
  redirect_url: 'https://example.com/verification-complete',
});

// Redirect the user
window.location.href = session.session_url;
```

The redirect URL receives `?session_id=ses_abc123&decision=approved` as query parameters.

***

## Error Handling

The API client throws `VerilockError` on failure:

```javascript theme={null}
try {
  await api.aml.screen({ name: 'John Doe' });
} catch (error) {
  if (error.name === 'VerilockError') {
    console.log(error.code);       // e.g. 'insufficient_credits'
    console.log(error.message);    // Human-readable description
    console.log(error.statusCode); // HTTP status code
    console.log(error.body);       // Full error response object
  }
}
```

The client automatically retries on `429` (rate limited) and `5xx` (server error) responses with exponential backoff. You can configure this with the `maxRetries` option.
