Document Verification
Complete guide to document verification workflows including verification types, status flows, and API operations
Document Verification
Comprehensive Verification SystemThe Loan Origination System provides a robust verification framework to validate borrower information, documents, and eligibility before making lending decisions.
Document verification is a critical component of the loan origination process. The LOS verification system supports multiple verification types, automated and manual workflows, and provides comprehensive status tracking for all verification activities.
Verification Overview
The verification dashboard provides a centralized view of all verification workflows associated with an application. Each verification type follows a defined workflow with specific status transitions and completion criteria.
Verification Dashboard
The verification dashboard displays:
- Verification Types - All available verification categories
- Current Status - Real-time status of each verification
- Document Requirements - Required documents for each verification
- Results - Verification outcomes (Passed, Failed, Review)
Screenshot: Verification DashboardThe verification dashboard provides an overview of all verification workflows and their current status.
Verification Types
The LOS supports multiple verification types, each designed to validate specific aspects of the borrower's application and eligibility.
| Type | Method | Description | Documents Required |
|---|---|---|---|
| Email Verification | 3rd Party | Validates email address ownership | None |
| Application Verification | System | Age check (18+ rule), basic eligibility | None |
| ID Verification | Document-based | Identity document review | Driver's License, Passport, State ID |
| Prefunding Verification | Checklist | Pre-funding checklist items | Varies by checklist |
| Income Verification | Document-based | Proof of income validation | Pay stubs, W-2, Tax returns, Bank statements |
| Bank Verification | Document/3rd Party | Bank account validation | Bank statements, Account verification |
Verification Status Flow
Each verification progresses through a series of statuses that reflect its current state in the workflow.
Data Status
| Status | Description | Icon |
|---|---|---|
None | Not initiated | ⬜ |
Initiated | Verification started | 🔄 |
Pending Doc | Document required | 📄 |
InProgress | Under review | 🔄 |
Completed | Finished | ✅ |
Failed | Verification failed | ❌ |
Verification Result
| Result | Description | Action Required |
|---|---|---|
Passed | Verification successful | None - can proceed |
Failed | Verification failed | Review/Reject application |
Review | Manual review needed | Back office review required |
Status Flow Diagram
%%{init: {'theme': 'base', 'themeVariables': {'background': '#ffffff', 'mainBkg': '#ffffff', 'clusterBkg': '#ffffff', 'clusterBorder': '#2563eb', 'titleColor': '#000000', 'primaryColor': '#2563eb', 'primaryTextColor': '#ffffff', 'lineColor': '#374151'}, 'flowchart': {'padding': 15, 'nodeSpacing': 25, 'rankSpacing': 30}}}%%
flowchart LR
subgraph MainContainer[✅ Verification Status Flow]
direction LR
A[⬜ None] --> B[🔄 Initiated]
B --> C[📄 Pending Doc]
C --> D[🔄 InProgress]
D --> E{⚖️ Result}
E -->|✅| F[✅ Passed]
E -->|❌| G[❌ Failed]
E -->|📋| H[📋 Review]
H --> D
end
style A fill:#6b7280,stroke:#4b5563,color:#fff
style B fill:#2563eb,stroke:#1e40af,color:#fff
style C fill:#d97706,stroke:#b45309,color:#fff
style D fill:#2563eb,stroke:#1e40af,color:#fff
style E fill:#6b7280,stroke:#4b5563,color:#fff
style F fill:#059669,stroke:#047857,color:#fff
style G fill:#dc2626,stroke:#b91c1c,color:#fff
style H fill:#d97706,stroke:#b45309,color:#fff
Document Upload
Documents can be uploaded for verification through the API. The system supports multiple file types and allows multiple documents per verification category.
Accepted File Types
- Images: JPG, JPEG, GIF, PNG
- Documents: PDF
Document Categories
Documents are categorized by verification type:
ID_VERIFICATION- Identity documentsINCOME_VERIFICATION- Income proof documentsBANK_VERIFICATION- Bank account documentsPREFUNDING_VERIFICATION- Pre-funding checklist documents
Mandatory vs Optional
Some verifications require mandatory documents before they can be completed, while others accept optional supporting documents.
ID Verification Workflow
ID verification validates the borrower's identity using government-issued identification documents.
Workflow Steps
- Document Upload - Borrower or back office uploads ID document
- Status: In Progress - Verification begins automatically
- Review - Back office reviews document (if manual review required)
- Result - Verification marked as Passed, Failed, or Unverifiable
Screenshot: ID Verification ModalThe ID verification modal allows back office staff to review uploaded identification documents and mark verification results.
ID Verification Flow
%%{init: {'theme': 'base', 'themeVariables': {'background': '#ffffff', 'mainBkg': '#ffffff', 'clusterBkg': '#ffffff', 'clusterBorder': '#2563eb', 'titleColor': '#000000', 'primaryColor': '#2563eb', 'primaryTextColor': '#ffffff', 'lineColor': '#374151'}, 'flowchart': {'padding': 15, 'nodeSpacing': 25, 'rankSpacing': 30}}}%%
flowchart LR
subgraph MainContainer[🆔 ID Verification Workflow]
direction LR
A[📄 Upload] --> B[🔄 InProgress]
B --> C[👁️ Review]
C --> D{⚖️ Result}
D -->|✅| E[✅ Passed]
D -->|❌| F[❌ Failed]
D -->|❓| G[❓ Unverifiable]
end
style A fill:#2563eb,stroke:#1e40af,color:#fff
style B fill:#2563eb,stroke:#1e40af,color:#fff
style C fill:#d97706,stroke:#b45309,color:#fff
style D fill:#6b7280,stroke:#4b5563,color:#fff
style E fill:#059669,stroke:#047857,color:#fff
style F fill:#dc2626,stroke:#b91c1c,color:#fff
style G fill:#6b7280,stroke:#4b5563,color:#fff
Prefunding Verification
Prefunding verification uses a checklist-based approach where all items must pass before funding can proceed.
Checklist Items
- All required documents uploaded
- Identity verified
- Income verified
- Bank account verified
- Credit check completed
- Compliance checks passed
Requirements
- All items must pass - No exceptions allowed
- Configurable checklist - Items can be customized per product
- Sequential completion - Items can be completed in any order
API Operations
Get Verification Status
Retrieve the current status of all verifications for an application.
curl -X GET 'https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/APP-2024-001234/verifications' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json'const getVerifications = async (applicationId) => {
const response = await fetch(
`https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/${applicationId}/verifications`,
{
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};import requests
def get_verifications(application_id):
url = f"https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/{application_id}/verifications"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()public String getVerifications(String applicationId) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/" + applicationId + "/verifications"))
.header("Authorization", "Bearer YOUR_TOKEN")
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}Sample Response
{
"records": [
{
"uid": "VER-001",
"name": "Income Verification",
"category": "financial",
"status": "InProgress",
"docRequired": true,
"filerefs": [
{
"documentId": "DOC-123",
"name": "W2_2024.pdf",
"valid": true,
"on": "2024-01-15T10:30:00Z"
}
]
},
{
"uid": "VER-002",
"name": "ID Verification",
"category": "identity",
"status": "Completed",
"verificationResult": "Passed"
}
]
}Upload Document for Verification
Upload a document for a specific verification category.
curl -X POST 'https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/APP-2024-001234/documents' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-F '[email protected]' \
-F 'category=ID_VERIFICATION' \
-F 'description=Drivers License'const uploadDocument = async (applicationId, file, category, description) => {
const formData = new FormData();
formData.append('file', file);
formData.append('category', category);
formData.append('description', description);
const response = await fetch(
`https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/${applicationId}/documents`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
},
body: formData
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};
// Usage
const fileInput = document.querySelector('input[type="file"]');
await uploadDocument('APP-2024-001234', fileInput.files[0], 'ID_VERIFICATION', 'Drivers License');import requests
def upload_document(application_id, file_path, category, description):
url = f"https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/{application_id}/documents"
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'category': category,
'description': description
}
headers = {'Authorization': 'Bearer YOUR_TOKEN'}
response = requests.post(url, files=files, data=data, headers=headers)
response.raise_for_status()
return response.json()
# Usage
upload_document('APP-2024-001234', 'drivers_license.pdf', 'ID_VERIFICATION', 'Drivers License')public String uploadDocument(String applicationId, String filePath, String category, String description) throws Exception {
HttpClient client = HttpClient.newHttpClient();
// Create multipart form data
String boundary = "----WebKitFormBoundary" + System.currentTimeMillis();
String formData = "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"file\"; filename=\"" + filePath + "\"\r\n"
+ "Content-Type: application/pdf\r\n\r\n"
+ new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(filePath)))
+ "\r\n--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"category\"\r\n\r\n"
+ category
+ "\r\n--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
+ description
+ "\r\n--" + boundary + "--\r\n";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/applications/" + applicationId + "/documents"))
.header("Authorization", "Bearer YOUR_TOKEN")
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofString(formData))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}Complete Verification
Mark a verification as complete with a result (Passed, Failed, or Review).
curl -X POST 'https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/VER-001/complete' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"result": "Passed",
"notes": "Document verified successfully",
"verifiedBy": "[email protected]"
}'const completeVerification = async (verificationId, result, notes, verifiedBy) => {
const response = await fetch(
`https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/${verificationId}/complete`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
result: result,
notes: notes,
verifiedBy: verifiedBy
})
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};
// Usage
await completeVerification('VER-001', 'Passed', 'Document verified successfully', '[email protected]');import requests
def complete_verification(verification_id, result, notes, verified_by):
url = f"https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/{verification_id}/complete"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
data = {
"result": result,
"notes": notes,
"verifiedBy": verified_by
}
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()
return response.json()
# Usage
complete_verification('VER-001', 'Passed', 'Document verified successfully', '[email protected]')public String completeVerification(String verificationId, String requestBody) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/" + verificationId + "/complete"))
.header("Authorization", "Bearer YOUR_TOKEN")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}Reinitiate Failed Verification
Reinitiate a failed verification when new documents are available or conditions have changed.
curl -X POST 'https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/VER-001/reinitiate' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"reason": "New document uploaded"
}'const reinitiateVerification = async (verificationId, reason) => {
const response = await fetch(
`https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/${verificationId}/reinitiate`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
reason: reason
})
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};
// Usage
await reinitiateVerification('VER-001', 'New document uploaded');import requests
def reinitiate_verification(verification_id, reason):
url = f"https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/{verification_id}/reinitiate"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
data = {
"reason": reason
}
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()
return response.json()
# Usage
reinitiate_verification('VER-001', 'New document uploaded')public String reinitiateVerification(String verificationId, String reason) throws Exception {
HttpClient client = HttpClient.newHttpClient();
String requestBody = "{\"reason\":\"" + reason + "\"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://loc.demo.kendra.lendfoundry.com/v1/darbaan/back-office/rest/api/verifications/" + verificationId + "/reinitiate"))
.header("Authorization", "Bearer YOUR_TOKEN")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}Verification Best Practices
1. Document Quality
- Clear images - Ensure documents are legible and complete
- Proper format - Use supported file types (PDF, JPG, PNG)
- Complete pages - Include all pages of multi-page documents
2. Verification Timing
- Early initiation - Start verifications as soon as documents are available
- Parallel processing - Initiate multiple verifications simultaneously
- Status monitoring - Regularly check verification status via API
3. Error Handling
- Failed verifications - Review failure reasons and reinitiate when appropriate
- Missing documents - Request additional documents promptly
- Manual review - Escalate to manual review when automated checks fail
Next Steps
| Resource | Description |
|---|---|
| Application Lifecycle | Learn about application status workflows |
| Loan Onboarding | Onboard approved applications to LMS |
| API Reference | Complete API endpoint documentation |
Ready to Continue?Return to Application Lifecycle to understand how verifications fit into the complete application workflow.
Updated 3 months ago
