Checks Quick Start Guide
Get started quickly with checks using Veryfi Lens SDK. This guide provides complete step-by-step instructions for integrating check capture with front and back side processing.
Prerequisites:
- Node.js (latest LTS version recommended)
- CLIENT ID from the Keys section in Settings of your account
- Lens For Browser enabled for your account (confirm with Customer Support)
Authorization
- Create an account at Veryfi Portal
- Contact Veryfi's sales/support team to request SDK access
- Once approved, obtain your Client ID from the Keys section in Settings
Project Setup
- Vanilla JavaScript
- Next.js/React
1. Create Project
In current directory:
npm create vite@latest . -- --template vanilla
Or in a new directory:
npm create vite@latest check-scanner-app -- --template vanilla
cd check-scanner-app
2. Install SDK
npm install veryfi-lens-wasm@latest
3. Copy WASM files
mkdir -p public/wasm
cp -r node_modules/veryfi-lens-wasm/wasm/* public/wasm/
4. Store Client ID in .env file
Make sure to add .env file to .gitignore to avoid committing it to the repository.
VITE_VERYFI_CLIENT_ID=your_client_id_here
5. Create vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
}
},
optimizeDeps: {
esbuildOptions: {
define: {
global: 'globalThis'
}
}
}
});
6. Update index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Check Scanner</title>
</head>
<body>
<div id="app">
<header>
<h1>Check Scanner</h1>
</header>
<main>
<div class="scanner-controls">
<button id="scan-check-btn" class="scan-btn">
Scan Check
</button>
</div>
<div id="status-display" class="status-display"></div>
<div id="result-display" class="result-display"></div>
</main>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
7. Update src/style.css
:root {
--primary-color: #4CAF50;
--hover-color: #45a049;
--error-color: #ff4444;
--text-color: #333;
--background-color: #f5f5f5;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background-color: var(--background-color);
}
#app {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
margin-bottom: 2rem;
}
.scanner-controls {
display: flex;
justify-content: center;
margin-bottom: 2rem;
}
.scan-btn {
padding: 1rem 2rem;
font-size: 1rem;
border: none;
border-radius: 4px;
background-color: var(--primary-color);
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
}
.scan-btn:hover {
background-color: var(--hover-color);
}
.status-display {
margin-bottom: 1rem;
padding: 1rem;
border-radius: 4px;
background-color: white;
min-height: 2rem;
}
.result-display {
padding: 1rem;
border-radius: 4px;
background-color: white;
overflow-x: auto;
}
.error {
color: var(--error-color);
}
8. Update src/main.js
import './style.css';
import VeryfiLens from 'veryfi-lens-wasm';
const CLIENT_ID = import.meta.env.VITE_VERYFI_CLIENT_ID;
class CheckScanner {
constructor() {
this.statusDisplay = document.getElementById('status-display');
this.resultDisplay = document.getElementById('result-display');
this.initializeEventListeners();
}
async initializeScanner() {
try {
await VeryfiLens.init(CLIENT_ID, {
lensFlavor: "checks",
captureBackOfCheck: true,
enforceBothSides: true,
// Manual mode settings
checksEnableManualMode: true,
checksManualModeTimeout: 3000,
checksMaxAspectRatio: 2.7,
checksMinAspectRatio: 1.8,
checksCropMargin: 0.1,
persistManualModeOnRetake: true,
forceLandscapeCheckPreview: true,
// Overlay customization
cropLayoutBorderColor: "#54C08B",
cropLayoutStroke: 2,
cropLayoutOverlayAlpha: 0.6,
cropLayoutCornerRadius: 8,
cropLayoutTipMessage: "Align check within the guide",
cropLayoutTipPosition: "bottom",
// UI elements
torchButton: true,
exitButton: true,
onClose: (isVisible) => {
console.log("Camera closed:", isVisible);
}
});
this.setupEventHandlers();
this.updateStatus('Scanner initialized');
await VeryfiLens.showCamera();
} catch (error) {
this.handleError('Initialization failed', error);
}
}
setupEventHandlers() {
VeryfiLens.onSuccess((result) => {
this.updateStatus('Check processed successfully');
this.displayResult(result);
});
VeryfiLens.onFailure((error) => {
this.handleError('Processing failed', error);
});
VeryfiLens.onUpdate((status) => {
this.updateStatus(`Status: ${status.status}`);
});
}
updateStatus(message) {
this.statusDisplay.textContent = message;
}
displayResult(result) {
this.resultDisplay.innerHTML = `
<h3>Check Data:</h3>
<pre>${JSON.stringify(result, null, 2)}</pre>
`;
}
handleError(context, error) {
console.error(`${context}:`, error);
this.statusDisplay.innerHTML = `
<div class="error">
${context}: ${error.message}
</div>
`;
}
initializeEventListeners() {
document.getElementById('scan-check-btn').addEventListener('click', () => {
this.initializeScanner();
});
}
}
// Initialize the app
document.addEventListener('DOMContentLoaded', () => {
new CheckScanner();
});
9. Run the development server
npm run dev
Open the link provided in terminal (e.g., http://localhost:5173/)
Final Project Structure
/check-scanner-app
├── node_modules/
│ └── veryfi-lens-wasm/
├── public/
│ └── wasm/ # WASM files from SDK
├── src/
│ ├── main.js # Check scanner logic
│ └── style.css # Styles
├── index.html
├── package.json
├── vite.config.js
└── .env # CLIENT_ID (add to .gitignore)
1. Create Project
In current directory:
npx create-next-app@latest .
Or in a new directory:
npx create-next-app@latest check-scanner-app
cd check-scanner-app
Choose the following options:
- TypeScript: Optional
- ESLint: Optional
- Tailwind CSS: Optional
src/directory: No- Use Turbopack: No
- App Router: Yes
2. Install SDK
npm install veryfi-lens-wasm@latest
3. Copy WASM files
mkdir -p public/wasm
cp -r node_modules/veryfi-lens-wasm/wasm/* public/wasm/
4. Store Client ID in .env file
Make sure to add .env file to .gitignore to avoid committing it to the repository.
NEXT_PUBLIC_CLIENT_ID=your_client_id_here
5. Update next.config.js
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
headers: async () => [
{
source: '/:path*',
headers: [
{
key: 'Cross-Origin-Embedder-Policy',
value: 'require-corp'
},
{
key: 'Cross-Origin-Opener-Policy',
value: 'same-origin'
}
]
}
]
};
export default nextConfig;
6. Update app/page.tsx
'use client'
import { useEffect, useState } from "react";
export default function Home() {
const CLIENT_ID = process.env.NEXT_PUBLIC_CLIENT_ID || '';
const [status, setStatus] = useState('');
const [scanResult, setScanResult] = useState(null);
const [veryfiLens, setVeryfiLens] = useState<any>(null);
useEffect(() => {
if (typeof window !== 'undefined') {
import('veryfi-lens-wasm').then(module => setVeryfiLens(module.default));
}
}, []);
const initializeScanner = async () => {
if (!veryfiLens) return;
try {
await veryfiLens.init(CLIENT_ID, {
lensFlavor: "checks",
captureBackOfCheck: true,
// UI elements
torchButton: true,
exitButton: true,
onClose: (isVisible) => {
console.log("Camera closed:", isVisible);
}
});
setupEventHandlers();
setStatus('Scanner initialized');
await veryfiLens.showCamera();
} catch (error: any) {
handleError('Initialization failed', error);
}
};
const setupEventHandlers = () => {
veryfiLens.onSuccess((result: any) => {
setStatus('Check processed successfully');
setScanResult(result);
});
veryfiLens.onFailure((error: any) => {
handleError('Processing failed', error);
});
veryfiLens.onUpdate((status: any) => {
setStatus(`Status: ${status.status}`);
});
};
const handleError = (context: string, error: any) => {
console.error(`${context}:`, error);
setStatus(`${context}: ${error.message}`);
};
return (
<div className="min-h-screen">
<header>
<h1>Check Scanner</h1>
</header>
<main>
<div className="scanner-controls">
<button
onClick={initializeScanner}
className="scan-btn"
disabled={!veryfiLens}
>
Scan Check
</button>
</div>
{status && (
<div className="status-display">
{status}
</div>
)}
{scanResult && (
<div className="result-display">
<h3>Check Data:</h3>
<pre>{JSON.stringify(scanResult, null, 2)}</pre>
</div>
)}
</main>
</div>
);
}
If you are using TypeScript and get errors, create app/types/veryfi-lens-wasm.d.ts:
declare module 'veryfi-lens-wasm' {
const VeryfiLens: {
init: (clientId: string, options: any) => Promise<void>;
showCamera: () => Promise<void>;
onSuccess: (callback: (result: any) => void) => void;
onFailure: (callback: (error: any) => void) => void;
onUpdate: (callback: (status: any) => void) => void;
};
export default VeryfiLens;
}
7. Update app/globals.css
:root {
--primary-color: #4CAF50;
--hover-color: #45a049;
--error-color: #ff4444;
--text-color: #333;
--background-color: #f5f5f5;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background-color: var(--background-color);
}
#app {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
margin-bottom: 2rem;
}
.scanner-controls {
display: flex;
justify-content: center;
margin-bottom: 2rem;
}
.scan-btn {
padding: 1rem 2rem;
font-size: 1rem;
border: none;
border-radius: 4px;
background-color: var(--primary-color);
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
}
.scan-btn:hover {
background-color: var(--hover-color);
}
.scan-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.status-display {
margin-bottom: 1rem;
padding: 1rem;
border-radius: 4px;
background-color: white;
text-align: center;
}
.result-display {
padding: 1rem;
border-radius: 4px;
background-color: white;
overflow-x: auto;
}
.error {
color: var(--error-color);
}
8. Run the development server
npm run dev
Open the link provided in terminal (e.g., http://localhost:3000/)
Final Project Structure
/check-scanner-app
├── app/
│ ├── page.tsx # Check scanner component
│ ├── layout.tsx
│ ├── globals.css
│ └── types/
│ └── veryfi-lens-wasm.d.ts
├── public/
│ └── wasm/ # WASM files from SDK
├── .env # CLIENT_ID (add to .gitignore)
├── next.config.ts
└── package.json
Configuration Options Explained
The initialization includes several check-specific settings:
Basic Settings
lensFlavor: "checks"- Enables check scanning modecaptureBackOfCheck: true- Allows capturing the back sideenforceBothSides: true- Requires both front and back capture
Manual Mode Settings
When automatic check detection struggles with certain aspect ratios, manual mode provides a guide overlay:
checksEnableManualMode: true- Enables manual capture modechecksManualModeTimeout: 3000- Switches to manual mode after 3 secondschecksMaxAspectRatio: 2.7- Maximum aspect ratio (width:height)checksMinAspectRatio: 1.8- Minimum aspect ratiochecksCropMargin: 0.1- 10% margin around the checkpersistManualModeOnRetake: true- Keeps manual mode when retaking
Standard US checks have an aspect ratio of ~2.61. Adjust min/max values if scanning international checks with different dimensions.
Overlay Customization
Style the manual mode guide overlay:
cropLayoutBorderColor- Border color (default: "#54C08B")cropLayoutStroke- Border width in pixels (default: 2)cropLayoutOverlayAlpha- Overlay transparency 0-1 (default: 0.6)cropLayoutCornerRadius- Corner radius in pixels (default: 8)cropLayoutTipMessage- Instructional text shown to usercropLayoutTipPosition- Text position: "top", "bottom", "left", "right"
Display Settings
forceLandscapeCheckPreview: true- Forces horizontal preview displaytorchButton: true- Shows flashlight toggleexitButton: true- Shows close button
Capture Modes
You can configure different capture workflows:
Optional Back Side
{
captureBackOfCheck: true, // User chooses whether to scan back
enforceBothSides: false
}
Required Back Side
{
captureBackOfCheck: true,
enforceBothSides: true, // Must scan both sides
}
Automatic Back Side
{
captureBackOfCheck: true,
enforceAndSkipBothSides: true, // Auto-proceeds to back after front
delayBetweenCaptures: 1000 // 1 second delay between captures
}
Customizing Messages
Personalize user-facing text:
await VeryfiLens.init("YOUR_CLIENT_ID", {
lensFlavor: "checks",
captureBackOfCheck: true,
enforceBothSides: true,
// Custom messages
checkEnforcedModalMessage: "Please flip the check and capture the back side",
checkOptionalModalMessage: "Would you like to capture the back of the check?",
checkContinueButtonText: "Continue",
checkYesButtonText: "Yes",
checkNoButtonText: "No",
blurModalMessage: "The image is too blurry. Please try again",
submitButtonText: "Process Check",
retakeButtonText: "Retake Photo"
});
Next Steps
- Configuration Options - Explore all available settings
- UI Customization - Style the check scanner with CSS
- Event Handling - Learn about all available events