Skip to main content

Prescription Label Quick Start Guide

Get started quickly with prescription label capture using Veryfi Lens SDK. This guide covers the Prescription Label flavor: switch overlays during capture — the bottle overlay records video of a rotating pill bottle, and the box overlay captures still images of box sides. Captures land in the review gallery, then are packaged and submitted for data extraction.

info

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​

  1. Create an account at Veryfi Portal
  2. Contact Veryfi's sales/support team to request SDK access
  3. Once approved, obtain your Client ID from the Keys section in Settings

Project Setup​

1. Create Project​

In current directory:

npm create vite@latest . -- --template vanilla

Or in a new directory:

npm create vite@latest prescription-label-app -- --template vanilla
cd prescription-label-app

2. Install SDK​

npm install veryfi-lens-wasm@latest

3. Store Client ID in .env file​

danger

Make sure to add .env file to .gitignore to avoid committing it to the repository.

VITE_VERYFI_CLIENT_ID=your_client_id_here

4. 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>Prescription Label Scanner</title>
</head>
<body>
<div id="app">
<header>
<h1>Prescription Label Scanner</h1>
</header>

<main>
<div class="scanner-controls">
<button id="scan-prescription-btn" class="scan-btn">
Scan Prescription Label
</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>

5. 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);
}

6. Update src/main.js​

import './style.css';
import VeryfiLens from 'veryfi-lens-wasm';

const CLIENT_ID = import.meta.env.VITE_VERYFI_CLIENT_ID;

class PrescriptionLabelScanner {
constructor() {
this.statusDisplay = document.getElementById('status-display');
this.resultDisplay = document.getElementById('result-display');
this.initializeEventListeners();
}

async initializeScanner() {
try {
await VeryfiLens.init(CLIENT_ID, {
lensFlavor: "prescription_label",
torchButton: true,
torchOnStart: false,
exitButton: true,
prescriptionLabelShowOverlay: true,
prescriptionLabelShowOverlayToggle: true,
onClose: () => {
console.log("Camera closed");
},
});

this.setupEventHandlers();
this.updateStatus('Scanner initialized');
await VeryfiLens.showCamera(video => {
console.log('Video captured', video);
});
} catch (error) {
this.handleError('Initialization failed', error);
}
}

setupEventHandlers() {
VeryfiLens.onSuccess((result) => {
this.updateStatus('Prescription label 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>Prescription Label 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-prescription-btn').addEventListener('click', () => {
this.initializeScanner();
});
}
}

document.addEventListener('DOMContentLoaded', () => {
new PrescriptionLabelScanner();
});

7. Run the development server​

npm run dev

Open the link provided in terminal (e.g., http://localhost:5173/)

Final Project Structure​

/prescription-label-app
├── node_modules/
│ └── veryfi-lens-wasm/
├── src/
│ ├── main.js # Prescription label scanner logic
│ └── style.css # Styles
├── index.html
├── package.json
└── .env # CLIENT_ID (add to .gitignore)

Configuration Options Explained​

The initialization includes several Prescription Label–specific settings:

Basic Settings​

  • lensFlavor: "prescription_label" - Enables the Prescription Label (video) mode
  • selectedBlueprint: "prescription_medication_label" - Pre-selects the blueprint used for data extraction. This is also the default when no blueprint is provided

Overlay Settings​

  • prescriptionLabelShowOverlay: true - Shows the bottle-shaped cutout overlay that guides the user where to position the pill bottle
  • prescriptionLabelShowOverlayToggle: true - Lets the user switch between bottle (video) and box (still) overlays during capture
  • prescriptionLabelWidthRatio: 0.55 - Width of the bottle overlay (0–1 relative to viewport)
  • prescriptionLabelHeightRatio: 0.65 - Height of the bottle overlay (0–1 relative to viewport)
  • prescriptionLabelText: "Position prescription label in outline" - Instructional text shown to the user
  • prescriptionLabelMaxVideoDuration: 12 - Auto-stop bottle recording after this many seconds (0 disables the limit)

Optional Box Overlay​

  • prescriptionLabelShowSquareOverlay: false - Start on the box overlay instead of the bottle outline
  • prescriptionLabelBoxMultiSide: true - After a box still, add more sides from the review gallery ("Add Page")
  • prescriptionLabelBoxMaxSides: 4 - Maximum sides (pages) per box document

Display Settings​

  • torchButton: true - Shows flashlight toggle
  • torchOnStart: false - Flashlight is off by default when the camera opens
  • exitButton: true - Shows close button

Capture Workflow​

The Prescription Label flavor supports two overlays. Switch them with the in-camera toggle.

Bottle (video) — for cylindrical bottles where the label wraps around:

  1. The camera opens with the bottle outline overlay
  2. The user taps the capture button to start recording
  3. A red "REC" indicator (or draining outline when prescriptionLabelProgressFill is on) appears while recording
  4. The user slowly rotates the bottle so the entire label passes through the overlay
  5. The user taps the capture button again to stop recording, or recording stops at prescriptionLabelMaxVideoDuration
  6. The review gallery opens with Retake / Submit

Box (still) — for rectangular packaging:

  1. Switch to the box overlay
  2. Tap to capture a still of one side
  3. Add more sides from the review gallery ("Add Page") up to prescriptionLabelBoxMaxSides
  4. Submit packages the pages as one document
tip

Bottle capture: the capture button toggles recording — first tap starts, second tap stops. Listen for recording_started and recording_stopped via onUpdate. Box capture does not record video.

Recording Lifecycle Events​

Listen to recording and processing events through onUpdate:

VeryfiLens.onUpdate((status) => {
switch (status.status) {
case 'recording_started':
console.log('Recording started');
break;
case 'recording_stopped':
console.log('Recording stopped');
break;
case 'capture_started':
console.log('Preparing video for submission');
break;
case 'processing_started':
console.log('Zipping video');
break;
case 'processing_completed':
console.log('Video zipped, ready to upload');
break;
case 'capture_completed':
console.log('Submission complete');
break;
case 'capture_failed':
console.log('Capture failed');
break;
}
});

Customizing the Overlay​

Bottle Outline Only (default)​

{
lensFlavor: "prescription_label",
prescriptionLabelShowOverlay: true,
prescriptionLabelWidthRatio: 0.55,
prescriptionLabelHeightRatio: 0.65,
prescriptionLabelText: "Position prescription label in outline"
}

Square/Rectangular Overlay​

Use a rectangular guide instead of the bottle outline:

{
lensFlavor: "prescription_label",
prescriptionLabelShowOverlay: false,
prescriptionLabelShowSquareOverlay: true,
prescriptionLabelSquareWidthRatio: 0.8,
prescriptionLabelSquareHeightRatio: 0.5
}

No Overlay​

Hide both overlays for a clean camera view:

{
lensFlavor: "prescription_label",
prescriptionLabelShowOverlay: false,
prescriptionLabelShowSquareOverlay: false
}

Custom Submit Handler​

If you need to handle the recorded video yourself instead of letting the SDK upload it, set a customSubmitHandler. It receives the base64-encoded ZIP that contains the video file:

await VeryfiLens.init("YOUR_CLIENT_ID", {
lensFlavor: "prescription_label",
customSubmitHandler: (zipBase64) => {
console.log('Got video ZIP (base64), size:', zipBase64.length);
}
});

Next Steps​