Skip to main content

Veryfi Lens for Checks - Comprehensive Integration Guide

Overview

This guide provides step-by-step instructions for integrating Veryfi Lens for Checks into your iOS and Android application. The guide focuses on configuration settings that ensure compliance with X9 banking standards, which is critical for check processing and deposit workflows.

Table of Contents

  1. Prerequisites
  2. Obtaining Credentials
  3. Installation
  4. Project Configuration
  5. SDK Initialization
  6. Recommended Settings for X9 Compliance
  7. Implementation
  8. Response Handling
  9. Best Practices

Prerequisites

Before starting the integration, ensure you have:

  • API credentials from Veryfi Hub (Client ID, Username, API Key, URL)
  • Access credentials for SDK download (CocoaPods username and password)
  • Xcode project with Swift Package Manager (recommended) or CocoaPods
  • Xcode 16.4 or later for compilation
  • iOS 12.1 or later
  • CocoaPods installed (if using CocoaPods method - deprecated)

Obtaining Credentials

1. Access Credentials (SDK Download)

To download the Veryfi Lens SDK, you need access credentials:

  1. Sign in to the Veryfi API Portal
  2. Navigate to SettingsKeys
  3. In the Lens: Cocoapods (iOS) section, click "Add Access Key"
  4. Fill in:
    • First Name
    • Last Name
    • Email Address
    • Create a Password (save this securely - it won't be shown again)
  5. Your username will be generated automatically

Store credentials securely using Git Credential Tool (Recommended):

git credential approve <<EOF
protocol=https
host=repo.veryfi.com
path=shared/lens/veryfi-lens-podspec.git
username=COCOAPODS_USERNAME
password=COCOAPODS_PASSWORD
EOF

2. Configuration Credentials (API Access)

To configure the SDK, you need API credentials:

  1. In the Veryfi Hub, go to SettingsKeys
  2. In the API Auth Credentials section, you'll find:
    • Client ID: Unique identifier for your application
    • Username: Your account username
    • API Key: Authentication key for API access
    • Environment URL: API endpoint (e.g., api.veryfi.com or devapi.veryfi.com)

⚠️ Security Note: Never commit these credentials to version control. Store them securely using environment variables, Keychain, or secure configuration files.


Installation

  1. Store SPM Access Credentials:

    git credential approve <<EOF
    protocol=https
    host=repo.veryfi.com
    path=shared/lens/veryfi-lens-spm.git
    username=COCOAPODS_USERNAME
    password=COCOAPODS_PASSWORD
    EOF
  2. In Xcode:

    • File → Add Package Dependencies
    • Enter package URL: https://repo.veryfi.com/shared/lens/veryfi-lens-spm.git
    • Enter credentials when prompted (use CocoaPods username and password)
    • Select version:
      • Latest: Choose Dependency Rule Branch with value master
      • Specific version: Use Dependency Rule Exact Version with SemVer format (e.g., 2.2.33)
  3. Add to Target: Ensure the package is added to your app target

Option B: CocoaPods (Deprecated)

⚠️ Note: CocoaPods installation is deprecated. Use Swift Package Manager for new projects.

  1. Update Podfile:

    source 'https://repo.veryfi.com/shared/lens/veryfi-lens-podspec.git'
    source 'https://github.com/CocoaPods/Specs.git'

    target 'YourApp' do
    use_frameworks!
    pod 'VeryfiLens', '~> 2.2.33.4' # Replace with latest version
    end

    Note: Version release notes can be found at: https://github.com/veryfi/veryfi-lens-checks-ios-demo/releases

  2. Install:

    pod repo update
    pod install
  3. Always open .xcworkspace, not .xcodeproj


Project Configuration

1. Update Build Settings

Note: If using Xcode 14+, these settings may be deprecated and not required.

  • Enable Bitcode: NO
  • Validate Workspace: YES

2. Add Required Permissions to Info.plist

Add the following keys to your Info.plist:

<key>NSCameraUsageDescription</key>
<string>Scan checks for deposit processing</string>

<key>NSPhotoLibraryAddUsageDescription</key>
<string>Back up check images in your photo gallery</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>Choose check images to process from your photo gallery</string>

Or via Xcode UI:

  1. Select your project → Target → Info tab
  2. Add:
    • Privacy - Camera Usage Description = "Scan checks for deposit processing"
    • Privacy - Photo Library Additions Usage Description = "Back up check images in your photo gallery"
    • Privacy - Photo Library Usage Description = "Choose check images to process from your photo gallery"

SDK Initialization

1. Import the SDK

import VeryfiLens

2. Configure Credentials

let CLIENT_ID = "XXX" // Replace with your Client ID
let AUTH_USERNAME = "XXX" // Replace with your Username
let AUTH_APIKEY = "XXX" // Replace with your API Key
let URL = "XXX" // Replace with your Endpoint URL (e.g., api.veryfi.com)

let veryfiLensCredentials = VeryfiLensCredentials(
clientId: CLIENT_ID,
username: AUTH_USERNAME,
apiKey: AUTH_APIKEY,
url: URL
)

3. Configure Settings for Checks

let veryfiLensSettings = VeryfiLensSettings()
veryfiLensSettings.documentTypes = ["check"]
veryfiLensSettings.showDocumentTypes = true
// ... configure additional settings (see Recommended Settings section)

Note: See the "Recommended Settings for X9 Compliance" section below for comprehensive instructions on recommended settings.

4. Implement the Delegate

extension ViewController: VeryfiLensDelegate {
func veryfiLensClose(_ json: [String : Any]) {
// Handle camera close event
// json contains: session_scan_count, msg, etc.
}

func veryfiLensError(_ json: [String : Any]) {
// Handle errors during processing
// json contains: error, msg, etc.
}

func veryfiLensSuccess(_ json: [String : Any]) {
// Handle successful check processing
// json contains: data, package_id, document_type, etc.
}

func veryfiLensUpdate(_ json: [String : Any]) {
// Handle processing updates (upload progress, thumbnails, etc.)
// json contains: status, msg, package_id, progress, etc.
}
}

5. Initialize the SDK

VeryfiLens.shared().delegate = self
VeryfiLens.shared().configure(
with: veryfiLensCredentials,
settings: veryfiLensSettings
) { success in
if success {
// SDK configured successfully
print("Veryfi Lens configured successfully")
} else {
// Handle configuration failure
print("Veryfi Lens configuration failed")
}
}

6. Launch the Camera

VeryfiLens.shared().showCamera(in: self)

The following settings are critical for ensuring checks meet X9 banking standards and prevent rejection by banking partners. These are the default values in VeryfiLensChecksSettings():

Critical Validation Settings

These settings enforce strict validation to meet X9 standards:

{
"validateCheckSize": true,
"validateCheckSides": true,
"validateCheckCorners": true,
"allowSubmitUndetectedDocsIsOn": false,
"captureMarginRatio": 0.08
}

Purpose:

  • validateCheckSize: Ensures check dimensions meet minimum requirements (at least 820px width or 351px height)
  • validateCheckSides: Validates that the correct side (front/back) is being captured
  • validateCheckCorners: Ensures all four corners of the check are visible and detected
  • allowSubmitUndetectedDocsIsOn: Prevents submission of images that don't contain a valid check
  • captureMarginRatio: Ensures check is properly positioned with margin; this setting is tied to validateCheckCorners

Check-Specific Settings

{
"documentTypes": ["check"],
"showDocumentTypes": true,
"checksBackIsOn": true,
"checksBackIsRequired": false,
"checkSequenceMode": true,
"checksCropMargin": 5,
"forceLandscapeImage": true,
"multipleDocumentsIsOn": false
}

Purpose:

  • checksBackIsOn: Enables capture of check back side after front side
  • checkSequenceMode: Provides alternative UX for sequential front/back scanning (recommended)
  • checksCropMargin: Sets margin around cropped checks (0-10, default: 5)
  • forceLandscapeImage: Forces horizontal preview orientation for checks
  • multipleDocumentsIsOn: When enabled, this setting will send multiple images as different transactions

Note: checksBackIsOn and checksBackIsRequired are implicit in checkSequenceMode, so they are not relevant when the latter is enabled.

Image Quality Settings

{
"autoRotateIsOn": false,
"autoSkewCorrectionIsOn": false,
"blurDetectionIsOn": true,
"allowSubmitBlurredDocsIsOn": false,
"glareDetectionIsOn": false,
"fraudDetectionIsOn": true,
"gpuIsOn": true
}

Purpose:

  • autoRotateIsOn: Disabled to preserve original check orientation
  • autoSkewCorrectionIsOn: Disabled to maintain check geometry
  • blurDetectionIsOn: Enabled to ensure image clarity
  • allowSubmitBlurredDocsIsOn: Enforces a hard check on blurred images at the submit preview screen
  • fraudDetectionIsOn: Requires the feature to be enabled in your account configuration; checks whether the capture is from an LCD screen
  • gpuIsOn: Enabled for faster processing (useful to disable on older devices, but all actively supported iPhone devices handle this without issues)

Note: If preventing LCD screen captures is important for your use case, the showLCDIsNotAllowed setting will add a hard check to prevent submitting those types of captures.

Crop Layout Settings (Visual Guide)

{
"cropLayoutWidth": 60,
"cropLayoutAspectRatio": 2.18,
"cropLayoutCornerRadius": 5,
"cropLayoutOverlayAlpha": 0.3,
"cropLayoutShowDelay": 8.0,
"forceCropLayoutOnRetake": true,
"checksMinAspectRatio": 1.9,
"checksMaxAspectRatio": 2.85
}

Purpose:

  • Provides visual guide for proper check positioning
  • cropLayoutAspectRatio: Matches standard check aspect ratio (2.18:1)
  • checksMinAspectRatio / checksMaxAspectRatio: Validates check proportions

Processing Settings

{
"dataExtractionEngine": "api",
"autoCaptureIsOn": false,
"returnStitchedPDF": true,
"saveLogsIsOn": true
}

Purpose:

  • dataExtractionEngine: Uses cloud API for accurate extraction
  • autoCaptureIsOn: Disabled for manual control (recommended for checks)
  • returnStitchedPDF: Returns PDF when multiple images are combined

UI/UX Settings

{
"moreMenuIsOn": false,
"autoSelectManualCropIsOn": true,
"backupDocsToGallery": false,
"backupDocsToiCloud": false,
"galleryIsOn": false
}

Purpose:

  • moreMenuIsOn: Disabled to prevent users from changing critical settings
  • autoSelectManualCropIsOn: Automatically enters crop mode for better control on the manual crop screen (accessible from the submit preview screen)

Here's the complete JSON configuration for X9-compliant check processing:

{
"documentTypes": ["check"],
"showDocumentTypes": true,
"dataExtractionEngine": "api",

"validateCheckSize": true,
"validateCheckSides": true,
"validateCheckCorners": true,
"allowSubmitUndetectedDocsIsOn": false,
"allowSubmitBlurredDocsIsOn": false,

"checksBackIsOn": true,
"checksBackIsRequired": false,
"checkSequenceMode": true,
"checksCropMargin": 5,
"checksMinAspectRatio": 1.9,
"checksMaxAspectRatio": 2.85,

"forceLandscapeImage": true,
"multipleDocumentsIsOn": false,
"autoRotateIsOn": false,
"autoSkewCorrectionIsOn": false,
"blurDetectionIsOn": true,
"gpuIsOn": true,

"cropLayoutWidth": 60,
"cropLayoutAspectRatio": 2.18,
"cropLayoutCornerRadius": 5,
"cropLayoutOverlayAlpha": 0.3,
"cropLayoutShowDelay": 8.0,
"forceCropLayoutOnRetake": true,

"autoCaptureIsOn": false,
"captureMarginRatio": 0.08,
"returnStitchedPDF": true,
"saveLogsIsOn": true,

"moreMenuIsOn": false,
"autoSelectManualCropIsOn": true,
"backupDocsToGallery": false,
"galleryIsOn": false
}

Note: For details on all VeryfiLens settings not specific to checks (including UI customization and general purpose use cases), see: https://docs.veryfi.com/lens/mobile/settings/


Implementation

Complete Example: ViewController

import UIKit
import VeryfiLens

class CheckScanViewController: UIViewController, VeryfiLensDelegate {

override func viewDidLoad() {
super.viewDidLoad()
setupVeryfiLens()
}

private func setupVeryfiLens() {
// Configure credentials
let CLIENT_ID = "YOUR_CLIENT_ID"
let AUTH_USERNAME = "YOUR_USERNAME"
let AUTH_APIKEY = "YOUR_API_KEY"
let URL = "YOUR_URL"

let veryfiLensCredentials = VeryfiLensCredentials(
clientId: CLIENT_ID,
username: AUTH_USERNAME,
apiKey: AUTH_APIKEY,
url: URL
)

// Configure settings using predefined checks settings
let veryfiLensSettings = VeryfiLensChecksSettings()

// Set delegate and configure
VeryfiLens.shared().delegate = self
VeryfiLens.shared().configure(
with: veryfiLensCredentials,
settings: veryfiLensSettings
) { success in
if success {
print("Veryfi Lens for Checks configured successfully")
} else {
print("Configuration failed")
}
}
}

@IBAction func scanCheck(_ sender: Any) {
VeryfiLens.shared().showCamera(in: self)
}

// MARK: - VeryfiLensDelegate

func veryfiLensClose(_ json: [String : Any]) {
print("Lens closed: \(json)")
if let scanCount = json["session_scan_count"] as? Int {
print("Scans in session: \(scanCount)")
}
}

func veryfiLensError(_ json: [String : Any]) {
print("Lens error: \(json)")
if let error = json["error"] as? String {
print("Error: \(error)")
}
if let msg = json["msg"] as? String {
print("Message: \(msg)")
}
}

func veryfiLensSuccess(_ json: [String : Any]) {
print("Lens success: \(json)")

// Extract check data
if let data = json["data"] as? [String: Any] {
// Process check data
processCheckData(data)
}
}

func veryfiLensUpdate(_ json: [String : Any]) {
print("Lens update: \(json)")

if let status = json["status"] as? String {
switch status {
case "start":
print("Upload started")
case "update":
if let msg = json["msg"] as? String {
if msg == "img_thumbnail_path" {
print("Thumbnail available")
} else if let progress = json["progress"] as? Double {
print("Upload progress: \(Int(progress * 100))%")
}
}
default:
break
}
}
}

private func processCheckData(_ data: [String: Any]) {
// Extract check fields
let checkNumber = data["check_number"] as? String
let amount = data["amount"] as? Double
let payerName = data["payer_name"] as? String
let bankName = data["bank_name"] as? String
let routingNumber = data["check_account_routing"] as? String
let date = data["date"] as? String

// Process extracted check data
// Send to your backend, save to database, etc.
}
}

Response Handling

Success Response Structure

When a check is successfully processed, veryfiLensSuccess receives a JSON object with the following structure:

{
"status": "success",
"package_id": "unique-package-id",
"document_type": "check",
"data": {
"check_number": "1234",
"amount": 100.50,
"amount_text": "One hundred and 50/100",
"payer_name": "John Doe",
"payer_address": "123 Main St, City, State 12345",
"receiver_name": "Jane Smith",
"receiver_address": "456 Oak Ave, City, State 67890",
"bank_name": "Example Bank",
"bank_address": "789 Bank St, City, State 11111",
"fractional_routing_number": "12-3456/7890",
"check_account_routing": "123456789",
"date": "2024-01-15",
"memo": "Payment for services",
"pdf_url": "https://..."
}
}

Error Response Structure

When an error occurs, veryfiLensError receives:

{
"status": "error",
"error": "Error type",
"msg": "Error message",
"package_id": "unique-package-id"
}

Update Response Structure

During processing, veryfiLensUpdate receives multiple updates:

{
"status": "update",
"msg": "img_thumbnail_path",
"package_id": "unique-package-id",
"data": "/path/to/thumbnail.jpg"
}
{
"status": "update",
"msg": "upload_progress",
"package_id": "unique-package-id",
"progress": 0.75
}

Close Response Structure

When camera closes, veryfiLensClose receives:

{
"status": "close",
"session_scan_count": 2,
"msg": "camera_closed"
}

Best Practices

1. X9 Compliance Checklist

To ensure checks meet X9 standards:

  • ✅ Enable all validation settings (validateCheckSize, validateCheckSides, validateCheckCorners)
  • ✅ Set allowSubmitUndetectedDocsIsOn to false
  • ✅ Use appropriate checksCropMargin (5 is recommended)
  • ✅ Ensure checksMinAspectRatio and checksMaxAspectRatio are set correctly
  • ✅ Enable blurDetectionIsOn to prevent blurry submissions
  • ✅ Disable autoRotateIsOn and autoSkewCorrectionIsOn to preserve check geometry
  • ✅ Use crop layout set of settings to guide users for proper positioning

Additional Resources


Support

For technical support or questions: