Vecminds Intelligence — Integration Guide
This guide covers everything needed to integrate Vecminds into your existing loan-origination system. Vecminds is a document intelligence layer that sits on top of your LOS and turns a borrower's document package — pay stubs, bank statements, tax returns, financial statements — into a clean, structured, verified credit file in minutes. Income computed. Discrepancies reconciled. Fraud signals flagged. Your underwriter decides.
Vecminds does not make the lending decision. It prepares the verified credit file and hands it to your underwriter. Every figure in the output is sourced to the document line that produced it. Every step is replayable for regulators and auditors.
Every file Vecminds processes is eventually tagged with a real repayment outcome. That outcome data trains the model on your specific borrower population — creating a flywheel that sharpens fraud signal accuracy and income pattern recognition in a way no off-the-shelf model can replicate.
Architecture
Vecminds slots into the existing document flow as a read-only processing layer between your document store and your underwriting UI. Nothing in your LOS is modified.
Your LOS / Document Store
│
│ read-only connector
▼
┌───────────────────────────────────────────┐
│ Vecminds Intelligence │
│ │
│ Document Parser ──► Income Engine │
│ PDF · scan · CSV gross · net · │
│ multi-source │
│ │ │
│ ▼ │
│ Discrepancy Detector │
│ cross-doc reconciliation │
│ │ │
│ ▼ │
│ Fraud Signal Model │
│ outcome-trained on your │
│ portfolio │
│ │ │
│ ▼ │
│ Audit Logger (immutable) │
└─────────────────────────────┬─────────────┘
│ structured JSON
▼
Your Underwriting UI
│
│ outcome tag (on close / default)
▼
Outcome Flywheel
(retrains on your portfolio —
proprietary signal)Key principles
- Read-only by default. Vecminds never writes to your LOS. Documents are read; the verified file is returned as a response.
- Augment, not replace. The verified credit file goes to your underwriter. Vecminds does not approve or decline loans.
- Explainable at every step. Every figure in the output is sourced to the specific document line that produced it.
- Outcome-trained. As real repayment outcomes are tagged back, the model sharpens on your portfolio — not generic training data.
- Your perimeter. In VPC and on-prem deployments, documents never leave your network.
Authentication
All API requests require a Bearer token in the Authorization header. Keys are scoped per deployment and never cross environments.
Key types
| Parameter | Type | Req | Description |
|---|---|---|---|
| ok_test_... | string | optional | Test key — documents are parsed but the outcome flywheel is not updated and audit records are marked test. Use for development and staging. |
| ok_live_... | string | optional | Live key — full processing, flywheel training, and immutable audit logging enabled. For VPC deployments, add IP allowlisting in the dashboard. |
POST /v1/intelligence/verify Authorization: Bearer ok_live_xxxxxxxxxxxxxxxxxxxx Content-Type: application/json
Key rotation
Keys can be rotated from the dashboard at any time. The previous key remains valid for a 15-minute overlap window to allow in-flight requests to complete before it is revoked.
Quickstart
Most teams are processing live documents within a week of starting a pilot. This section walks through submitting your first document package end-to-end.
Step 1 — Install the SDK
# Node.js / TypeScript npm install @vecminds/intelligence # Python pip install vecminds-intelligence # Java (Maven) # groupId: ai.vecminds artifactId: intelligence-sdk version: 2.4.0 # .NET dotnet add package Vecminds.Intelligence
Step 2 — Initialize the client
import { VecmindsClient } from "@vecminds/intelligence";
const client = new VecmindsClient({
apiKey: process.env.VECMINDS_API_KEY, // ok_live_...
// baseUrl: "https://vecminds.your-vpc.internal/v1", // VPC / on-prem
});Step 3 — Proxy through your server (Next.js example)
Your browser uploads documents to your own API route. That route forwards them to Vecminds server-to-server. The API key never leaves your server.
// This file runs on the server only. The VECMINDS_API_KEY env var
// is never bundled into the browser.
import { VecmindsClient } from "@vecminds/intelligence";
import { NextRequest, NextResponse } from "next/server";
const vecminds = new VecmindsClient({ apiKey: process.env.VECMINDS_API_KEY! });
export async function POST(req: NextRequest) {
// 1. Authenticate the incoming request with your own session/auth
const session = await getSession(req);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
// 2. Parse the multipart form submitted by your origination UI
const form = await req.formData();
const applicationId = form.get("application_id") as string;
const files = form.getAll("documents") as File[];
// 3. Forward to Vecminds server-to-server (key stays on the server)
const job = await vecminds.verify.create({
subject: { id: applicationId, type: "loan_application" },
documents: await Promise.all(
files.map(async (f) => ({ name: f.name, data: Buffer.from(await f.arrayBuffer()) }))
),
policy: "income.verify-2024",
notify: "https://your-los.internal/webhooks/vecminds",
});
// 4. Return only the job ID to the browser — no key, no raw docs
return NextResponse.json({ jobId: job.id });
}// The browser never touches Vecminds directly.
// It uploads to YOUR route and receives only the job ID.
async function submitApplication(applicationId: string, files: File[]) {
const form = new FormData();
form.append("application_id", applicationId);
files.forEach((f) => form.append("documents", f));
const res = await fetch("/api/verify", { method: "POST", body: form });
const { jobId } = await res.json();
return jobId; // poll /api/verify/[jobId] or wait for a push notification
}Step 4 — Read the verified credit file
// Receive via webhook (recommended) or poll:
const result = await client.verify.get(job.id);
// Verified income
console.log(result.income.gross_annual); // 84200
console.log(result.income.sources);
// [{ type: "employment", employer: "Meridian Corp",
// gross_annual: 84200, confidence: 0.97,
// verified_from: ["pay_stub_aug.pdf", "bank_stmt_q3.pdf"] }]
// Discrepancies between documents
console.log(result.discrepancies);
// [{ field: "monthly_income",
// document_a: { file: "pay_stub_aug.pdf", value: 7017, line: "Gross Pay" },
// document_b: { file: "bank_stmt_q3.pdf", value: 6100, line: "ACH deposit avg" },
// delta_pct: 0.15, severity: "medium" }]
// Fraud signals (empty = clean)
console.log(result.fraud_signals); // []
console.log(result.audit_id); // "aud_3F8C1B"Step 5 — Tag the outcome (feed the flywheel)
When the loan reaches a repayment outcome, tag it back to Vecminds. This is how the model learns which document patterns predict repayment in your portfolio. This call is triggered by a server-side event from your LOS — a loan close, a default flag, a charge-off — never from a browser session.
// Called by your LOS webhook / internal event bus when a loan closes.
// This is server-only code — a browser session is never involved.
async function onLoanClosed(event: LoanClosedEvent) {
const jobId = await db.getVecmindsJobId(event.applicationId);
await vecminds.outcomes.tag({
job_id: jobId,
outcome: "repaid", // repaid | default | early_payoff | charged_off
months_to_outcome: event.monthsFromOrigination,
loan_amount: event.loanAmount,
product_type: "personal",
});
}Core Concepts
These four concepts cover the full lifecycle of a document package through Vecminds.
Documents
A document is any borrower-submitted file. Accepted types:
| Parameter | Type | Req | Description |
|---|---|---|---|
| Pay stubs | PDF, image | optional | Current and prior month. Used for employment income, pay frequency, and employer verification. |
| Bank statements | PDF, CSV, OFX | optional | 3–12 months. Used for deposit pattern, recurring income, and cash reserve verification. |
| Tax returns (1040) | optional | 1–2 years. Used for gross income, self-employment income, and rental income. | |
| W-2 / 1099 | optional | Prior year. Cross-referenced against pay stubs and self-reported income figures. | |
| Business financials | optional | P&L, balance sheet. Used for business credit and self-employed borrower verification. | |
| Rent rolls | PDF, XLSX | optional | Investment property and commercial real estate income verification. |
Maximum file size: 50 MB per document, 200 MB per job. Documents are encrypted at rest (AES-256) and deleted from the processing environment within 24 hours of job completion (configurable via policy).
Credit Files
The structured output of a completed verification job:
{
"job_id": "job_9A4D2E",
"status": "completed",
"processing_time_ms": 2100,
"income": {
"gross_annual": 84200,
"net_monthly": 5616,
"confidence": 0.97,
"sources": [{
"type": "employment",
"employer": "Meridian Corp",
"gross_annual": 84200,
"pay_frequency":"biweekly",
"verified_from":["pay_stub_aug.pdf", "bank_stmt_q3.pdf"],
"confidence": 0.97
}]
},
"discrepancies": [{
"field": "monthly_income",
"document_a": { "file": "pay_stub_aug.pdf", "value": 7017, "line": "Gross Pay" },
"document_b": { "file": "bank_stmt_q3.pdf", "value": 6100, "line": "ACH deposit avg" },
"delta_pct": 0.15,
"severity": "medium",
"note": "Pay stub reflects pre-tax gross; bank deposits reflect net-of-deductions ACH."
}],
"fraud_signals": [],
"audit_id": "aud_3F8C1B",
"policy_version": "income.verify-2024@v3"
}Policies
A policy controls how Vecminds processes a document package — income source weights, discrepancy tolerances, required document types, and fraud detection behaviour. Policies are versioned YAML files. Standard policies ship with every account; custom policies are authored by your team.
| Parameter | Type | Req | Description |
|---|---|---|---|
| income.verify-2024 | policy | optional | Full employment income verification. Reconciles pay stubs, bank deposits, and tax returns. |
| income.self-employed-2024 | policy | optional | Self-employment income. Weights 1099s, bank deposits, and business P&L. |
| income.multi-source-2024 | policy | optional | Mixed employment and passive income — rental, investment, part-time. |
| fraud.detect-2024 | policy | optional | Document-level fraud signal detection only. No income computation. |
Outcomes
An outcome is a real-world repayment event tagged back to a verification job. Outcomes are the input to the flywheel — they teach the model which document patterns, discrepancy types, and fraud signals actually predict default in your portfolio.
| Parameter | Type | Req | Description |
|---|---|---|---|
| repaid | outcome | optional | Loan repaid in full at term. Strongest positive training signal. |
| early_payoff | outcome | optional | Loan repaid early. Positive signal with different prepayment pattern. |
| default | outcome | optional | Borrower missed 90+ days of payments. Core negative training signal. |
| charged_off | outcome | optional | Loan written off as uncollectible. Strong negative training signal. |
| pending | outcome | optional | Loan still active. Updates the outcome record; flywheel training deferred. |
API Reference
All endpoints are relative to https://api.vecminds.ai/v1. For VPC and on-prem deployments, replace the host with your internal endpoint. All requests and responses are JSON unless noted.
Request body
| Parameter | Type | Req | Description |
|---|---|---|---|
| subject.id | string | required | Your internal application or borrower ID. Appears in the audit log and webhook payload. |
| subject.type | string | required | One of: loan_application, refinance, heloc, business_credit, bnpl. |
| documents | array | required | Array of document objects. At least one required. |
| documents[].name | string | required | Filename with extension — used in output citations (e.g. 'pay_stub_aug.pdf'). |
| documents[].data | string (base64) | optional | Base64-encoded file content. Either data or url is required per document. |
| documents[].url | string | optional | Pre-signed URL. Vecminds fetches the document at processing time. Either url or data required. |
| policy | string | required | Policy ID to apply, e.g. 'income.verify-2024'. Pin a version with 'income.verify-2024@v3'. |
| notify | string | optional | Webhook URL called when the job completes. If omitted, poll GET /verify/{id}. |
| mode | string | optional | 'async' (default) returns immediately with job_id. 'sync' waits up to 30 s and returns the full credit file. |
| metadata | object | optional | Arbitrary key-value pairs passed through to the webhook payload and audit log. |
Request example
{
"subject": { "id": "app_7C3B1", "type": "loan_application" },
"documents": [
{ "name": "pay_stub_aug.pdf", "data": "<base64>" },
{ "name": "bank_stmt_q3.pdf", "url": "https://your-bucket.s3.amazonaws.com/bank_stmt_q3.pdf?..." },
{ "name": "1040_2023.pdf", "data": "<base64>" }
],
"policy": "income.verify-2024",
"notify": "https://your-los.internal/webhooks/vecminds",
"metadata": { "loan_officer_id": "lo_882", "product": "personal_unsecured" }
}Response — async (immediate)
{
"job_id": "job_9A4D2E",
"status": "processing",
"created_at": "2024-08-14T14:22:31Z",
"estimated_completion_ms": 2500
}Response — sync / completed
{
"job_id": "job_9A4D2E",
"status": "completed",
"processing_time_ms": 2100,
"income": {
"gross_annual": 84200,
"net_monthly": 5616,
"confidence": 0.97,
"sources": [{
"type": "employment",
"employer": "Meridian Corp",
"gross_annual": 84200,
"verified_from":["pay_stub_aug.pdf", "bank_stmt_q3.pdf"],
"confidence": 0.97
}]
},
"discrepancies": [{
"field": "monthly_income",
"document_a": { "file": "pay_stub_aug.pdf", "value": 7017, "line": "Gross Pay" },
"document_b": { "file": "bank_stmt_q3.pdf", "value": 6100, "line": "ACH deposit avg" },
"delta_pct": 0.15,
"severity": "medium",
"note": "Pay stub reflects pre-tax gross; bank deposits reflect net-of-deductions ACH."
}],
"fraud_signals": [],
"audit_id": "aud_3F8C1B",
"policy_version": "income.verify-2024@v3"
}Path parameters
| Parameter | Type | Req | Description |
|---|---|---|---|
| job_id | string | required | The job_id returned by POST /verify. |
Status values
| Parameter | Type | Req | Description |
|---|---|---|---|
| pending | status | optional | Job received; not yet picked up for processing. |
| processing | status | optional | Documents are being parsed and verified. |
| completed | status | optional | Verification complete. Full credit file available. |
| failed | status | optional | Processing failed. error.code and error.message describe the reason. |
Request body
| Parameter | Type | Req | Description |
|---|---|---|---|
| job_id | string | required | The verification job to tag. |
| outcome | string | required | repaid | default | early_payoff | charged_off | pending |
| months_to_outcome | integer | optional | Months from origination to this outcome event. |
| loan_amount | number | optional | Loan amount at origination, in whole currency units. |
| product_type | string | optional | personal | auto | mortgage | heloc | business | bnpl | other |
pending to default) by calling this endpoint again with the same job_id. The flywheel uses the most recent tag.{
"audit_id": "aud_3F8C1B",
"job_id": "job_9A4D2E",
"subject_id": "app_7C3B1",
"policy_version": "income.verify-2024@v3",
"created_at": "2024-08-14T14:22:31Z",
"completed_at":"2024-08-14T14:22:33Z",
"events": [
{ "ts": "2024-08-14T14:22:31.012Z", "type": "document_received",
"file": "pay_stub_aug.pdf", "size_bytes": 184320 },
{ "ts": "2024-08-14T14:22:31.420Z", "type": "income_extracted",
"file": "pay_stub_aug.pdf", "field": "gross_monthly",
"value": 7017, "page": 1,
"bounding_box": { "x": 0.62, "y": 0.34, "w": 0.18, "h": 0.04 } },
{ "ts": "2024-08-14T14:22:32.100Z", "type": "discrepancy_raised",
"field": "monthly_income", "delta_pct": 0.15, "severity": "medium" },
{ "ts": "2024-08-14T14:22:33.100Z", "type": "job_completed" }
]
}Audit records are immutable and retained for 7 years by default (configurable to match your document retention policy). They can be exported as JSON or PDF from the dashboard for examiner review.
LOS Connectors
Vecminds ships pre-built read-only connectors for the most common loan-origination systems. No schema changes to your LOS are required.
| Parameter | Type | Req | Description |
|---|---|---|---|
| Encompass (ICE) | connector | optional | Native Encompass SDK integration. Documents pulled from eFolder on milestone change. Application fields mapped to subject.id automatically. |
| Finastra Mortgagebot | connector | optional | REST connector. Documents pulled from the document checklist on status change events. |
| nCino | connector | optional | Salesforce-based. Listens to nCino loan document record inserts via Platform Events. |
| Temenos Transact | connector | optional | Event-driven. Subscribes to document upload events via Temenos Integration Framework. |
| S3 / Azure Blob | connector | optional | Watches a bucket prefix for new uploads. Compatible with any LOS that writes documents to object storage. |
| SDK (custom) | connector | optional | For platforms not on this list. Full TypeScript, Python, Java, and .NET SDKs. |
Encompass configuration example
# vecminds-connector.yaml
connector: encompass
auth:
client_id: $ENCOMPASS_CLIENT_ID
client_secret: $ENCOMPASS_CLIENT_SECRET
instance_id: $ENCOMPASS_INSTANCE_ID
trigger:
event: milestone_change
milestone: "Loan Submitted"
document_mapping:
- efolder_name: "Pay Stubs"
vecminds_type: pay_stub
- efolder_name: "Bank Statements"
vecminds_type: bank_statement
- efolder_name: "Tax Returns"
vecminds_type: tax_return
vecminds:
api_key: $VECMINDS_API_KEY
policy: income.verify-2024
notify: https://your-los.internal/webhooks/vecminds
metadata:
loan_officer_id: $ENCOMPASS_LOAN_OFFICER_IDWebhooks
Register a notify URL in your verification request to receive a POST when the job completes — eliminating the need to poll.
Event types
| Parameter | Type | Req | Description |
|---|---|---|---|
| verification.completed | event | optional | Job completed successfully. Full credit file is in the payload. |
| verification.failed | event | optional | Job failed. error.code and error.message describe the failure. |
| verification.document_unsupported | event | optional | One or more documents were unrecognised or too degraded to process. |
Payload
{
"event": "verification.completed",
"job_id": "job_9A4D2E",
"subject_id": "app_7C3B1",
"timestamp": "2024-08-14T14:22:33Z",
"data": { /* full verified credit file */ },
"metadata": { "loan_officer_id": "lo_882" }
}Verifying signatures
Every request includes an X-Vecminds-Signature header. Verify it before processing. The webhook secret lives in your server environment — never in the browser.
import crypto from "crypto";
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(payload, "utf8")
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
app.post("/webhooks/vecminds", (req, res) => {
const sig = req.headers["x-vecminds-signature"] as string;
if (!verifyWebhook(req.rawBody, sig, process.env.VECMINDS_WEBHOOK_SECRET!)) {
return res.status(401).send("Invalid signature");
}
const { event, data } = req.body;
if (event === "verification.completed") {
// hand data (verified credit file) to your underwriting UI
}
res.status(200).send("OK");
});GET /verify/{id}.Policy DSL
Policies are versioned YAML files that control how Vecminds processes a document package. Standard policies are maintained by Vecminds. Custom policies are authored by your team and uploaded via the dashboard or API.
Full policy reference
policy: income.verify-custom
version: "2024-02"
description: "Employment income + fraud detection for prime personal loans"
income_sources:
employment:
weight: 1.0
required_documents: [pay_stub, w2]
self_employment:
weight: 0.85
required_documents: [1040, bank_statement]
rental:
weight: 0.75
required_documents: [lease, bank_statement]
discrepancy:
tolerance: 0.05 # 5% variance allowed before a discrepancy is raised
severity_thresholds:
low: 0.05 # 5–10% delta
medium: 0.10 # 10–25% delta
high: 0.25 # >25% delta
auto_explain: true # attach a natural-language note to each discrepancy
fraud:
enabled: true
signals: [metadata, formatting, internal_consistency, behavioral]
block_on_signal: false # raise signal but do not block — underwriter reviews
output:
include_source_citations: true
include_confidence_scores: true
include_bounding_boxes: false # true = PDF highlight overlay in your UI
audit_retention_years: 7Versioning
Every policy is versioned (policy-slug@v3). The version in force at processing time is stamped on the credit file and audit log. Pin a specific version in your API calls with"policy": "income.verify-custom@v2" to freeze behaviour while a new version is under review.
SDKs
First-party SDKs for TypeScript/JavaScript, Python, Java, and .NET. All SDKs handle authentication, retries, base64 encoding, and webhook signature verification automatically.
TypeScript / JavaScript
import { VecmindsClient } from "@vecminds/intelligence";
const client = new VecmindsClient({ apiKey: process.env.VECMINDS_API_KEY });
// Submit and wait (sync mode)
const result = await client.verify.create({
subject: { id: "app_001", type: "loan_application" },
documents: [{ name: "pay_stub.pdf", data: buffer }],
policy: "income.verify-2024",
mode: "sync",
});
// Tag outcome
await client.outcomes.tag({
job_id: result.job_id,
outcome: "repaid",
months_to_outcome: 36,
});
// Fetch audit trail
const audit = await client.audit.get(result.audit_id);Python
from vecminds import VecmindsClient
import os
client = VecmindsClient(api_key=os.environ["VECMINDS_API_KEY"])
with open("pay_stub_aug.pdf", "rb") as f:
job = client.verify.create(
subject = {"id": "app_001", "type": "loan_application"},
documents = [{"name": "pay_stub_aug.pdf", "data": f.read()}],
policy = "income.verify-2024",
)
# Poll for result (or use notify= for webhook)
result = client.verify.wait(job.id, timeout=30)
print(result.income.gross_annual) # 84200
print(result.discrepancies) # [...]
# Tag outcome
client.outcomes.tag(job_id=job.id, outcome="repaid", months_to_outcome=24)Security & Compliance
Vecminds is designed to run entirely inside your infrastructure. In VPC and on-prem deployments, borrower documents never leave your network.
Deployment options
| Parameter | Type | Req | Description |
|---|---|---|---|
| VPC deployment | option | optional | Vecminds runs in a dedicated VPC in your cloud account (AWS, Azure, GCP). All traffic stays within your network perimeter. Recommended for regulated lenders. |
| On-premise | option | optional | Fully air-gapped. Documents never traverse external networks. Required for some core banking environments. |
| Private cloud | option | optional | Vecminds-managed infrastructure in a region-locked private cloud. Data residency guaranteed by contract. |
Certifications
Data handling
- Documents are encrypted at rest (AES-256) and in transit (TLS 1.3).
- Document content is deleted from the processing environment within 24 hours of job completion (configurable).
- Audit records are retained immutably for 7 years by default.
- API keys are hashed before storage — Vecminds cannot retrieve a plaintext key after issuance.
- Customer outcome data is never used to train shared models. The flywheel is per-customer and fully isolated.
Support
Your account includes a dedicated solutions engineer during the pilot and first 90 days in production. Ongoing support is available via Slack Connect, email, and the dashboard.
| Parameter | Type | Req | Description |
|---|---|---|---|
| Starter | tier | optional | Email support. SLA: next business day. Included in all plans. |
| Growth | tier | optional | Slack Connect + email. SLA: 4-hour response. Included in Growth and above. |
| Enterprise | tier | optional | Dedicated solutions engineer + pager escalation. SLA: 1-hour critical, 4-hour high. Custom SLA available. |
For integration questions, reach your solutions engineer via Slack Connect or email integrations@vecminds.ai. For urgent production issues, prefix your Slack message with /urgent to trigger the on-call escalation.