@lendworks/lendiq
v1.5.0
Published
Official TypeScript SDK for the LendIQ API — AI-powered MCA underwriting platform
Maintainers
Readme
Upload a bank statement. Get an underwriting decision.
The official TypeScript SDK for the LendIQ API. Turn months of manual underwriting into a single API call.
Get API Key · Documentation · API Reference
7 lines. That's it.
import { LendIQ } from "@lendworks/lendiq";
const client = new LendIQ({ apiKey: "liq_live_..." });
const deal = await client.deals.create({ business_name: "Acme Trucking LLC" });
await client.documents.upload(deal.id, "./statements/chase_jan.pdf");
const result = await client.deals.get(deal.id);
console.log(result.recommendation.decision); // "approved"That PDF just went through Gemini-powered extraction, transaction screening, tamper detection, 12-factor health scoring, and a full underwriting recommendation. Your team didn't write a single rule.
Why teams switch to LendIQ
Before LendIQ
- Manual PDF review (20-40 min per deal)
- Spreadsheet-based scoring
- Inconsistent underwriting criteria
- No tamper detection
- Weeks to onboard new data sources
After LendIQ
- Automated analysis (seconds per deal)
- 12-factor composite health scoring
- Configurable rulesets with version history
- PDF integrity + tampering detection
- One API call to process any bank statement
LendIQ vs. the alternatives
| | LendIQ | Ocrolus | LendAPI | Plaid (Asset Reports) | DIY (in-house) | |---|:---:|:---:|:---:|:---:|:---:| | Upload PDF → full underwriting decision | Yes | No | Partial | No | Build it yourself | | Bank statement + tax return + P&L support | All three | Statements only | Statements only | No PDFs | Depends on scope | | Gemini native PDF extraction | Yes | Template OCR | Template OCR | N/A | Build it yourself | | Tamper / fraud detection | Built in | Add-on | No | No | Build it yourself | | Health scoring (12 sub-factors) | Built in | No | Basic | No | Build it yourself | | Underwriting recommendation engine | Built in | No | Basic | No | Build it yourself | | Custom rulesets with version history | Yes | No | No | No | Build it yourself | | MCA position detection | Yes | No | No | No | Build it yourself | | Real-time SSE streaming | Yes | Polling | Polling | Polling | Build it yourself | | Typed SDKs (Python + TypeScript) | Both | Python only | None | Multiple | N/A | | Pricing | Per document | Per document | Per document | Per connection | Engineering time |
We don't just extract data from bank statements. We understand them — and give you a decision you can act on.
Install
npm install @lendworks/lendiqRequires Node.js 20+. Zero runtime dependencies — uses native
fetch,crypto, andfs.
Everything is typed
Every method returns a fully typed interface. Not any. Not unknown. Real types with real autocompletion.
const detail = await client.deals.get(dealId);
// IDE knows every field, every nested object, every type
detail.health.health_score; // number
detail.health.health_grade; // string
detail.recommendation.decision; // "approved" | "conditional" | "declined"
detail.recommendation.risk_factors; // string[]
detail.recommendation.strengths; // string[]
detail.financials.avg_monthly_deposits; // number
detail.mca?.mca_credit_score; // number | undefined
// 12 health sub-factors, individually scored and weighted
for (const [name, factor] of Object.entries(detail.health.factors)) {
console.log(`${name}: ${factor.score}/${factor.max} (weight: ${factor.weight})`);
}All response types are forward-compatible. New API fields are accepted automatically — your code never breaks on deploy.
Document intelligence, built in
Upload a PDF and get back structured intelligence — no OCR pipeline, no prompt engineering, no infra to manage.
const doc = await client.documents.get(docId);
// Extraction metadata
doc.extraction_method; // "gemini_native_pdf"
doc.extraction_confidence; // 0.94
doc.document_type; // "bank_statement"
// Tamper detection
doc.integrity.tampering_risk_level; // "clean" | "low" | "medium" | "high"
// Financial analysis (bank statements)
doc.analysis.average_daily_balance; // 16215.30
doc.analysis.total_deposits; // 48920.00
doc.analysis.health_score; // 78.5
doc.analysis.health_grade; // "B"
// Identity verification (driver's licenses)
doc.driver_license_analysis?.full_name; // "John Smith"
doc.driver_license_analysis?.expiration_date; // "2028-06-15"
// Bank verification (voided checks)
doc.voided_check_analysis?.routing_number; // "021000021"
doc.voided_check_analysis?.is_voided; // trueInstant analysis — no account required
Let prospects try LendIQ before they sign up. The instant endpoint processes a PDF in under 2 seconds with no data persistence.
const result = await client.instant.analyze("./statement.pdf");
console.log(result.summary.total_deposits); // 284500.00
console.log(result.summary.total_mca_positions); // 3
console.log(result.summary.avg_revenue_quality); // 0.82
// Per-file breakdown
for (const file of result.results) {
console.log(file.bank_name, file.nsf_count, file.mca_daily_obligation);
}Real-time pipeline streaming
Watch documents process in real time. No polling.
for await (const event of client.events.stream(dealId)) {
switch (event.event) {
case "stage":
console.log(`Stage: ${event.data}`); // "classifying" → "extracting" → "screening" → "scoring"
break;
case "complete":
console.log("Analysis complete");
break;
}
}Auto-pagination
Forget page math. Iterate over thousands of records with a single loop.
for await (const deal of client.deals.listAll({ status: "ready" })) {
console.log(deal.business_name, deal.health_grade);
// Typed as DealSummary — full autocompletion
}Error handling that doesn't suck
Every error is a typed class with the context you need to debug. No parsing strings.
import { NotFoundError, RateLimitError, ValidationError } from "@lendworks/lendiq";
try {
await client.deals.get(dealId);
} catch (err) {
if (err instanceof NotFoundError) {
// err.statusCode === 404
} else if (err instanceof RateLimitError) {
// err.retryAfter — seconds until you can retry
} else if (err instanceof ValidationError) {
// err.body — full validation error details
}
// Every error has err.requestId for instant support correlation
}Webhook verification in one line
import { verifySignature } from "@lendworks/lendiq/webhooks";
// HMAC-SHA256 with constant-time comparison. Timing attacks don't apply.
verifySignature(requestBody, headers["x-webhook-signature"], "whsec_...");Built for production
Configuration
const client = new LendIQ({
apiKey: "liq_live_...", // required
baseUrl: "https://iq.lend.works", // default
timeout: 30_000, // default (ms)
maxRetries: 2, // default
logger: console, // optional debug logging
});25 resources. Full API coverage.
Every endpoint in the LendIQ API has a typed method in this SDK.
| | Resource | What it does |
|-|----------|-------------|
| Core | client.deals | CRUD, decision, evaluate, notes, stats, analytics, batch |
| | client.documents | Upload, bulk upload, status, reprocess, triage, classify |
| | client.transactions | List, correct, corrections history |
| | client.exports | Deal and document CSV/PDF exports |
| | client.rulesets | Underwriting criteria CRUD, versioned, set default |
| Intelligence | client.instant | Free-tier instant PDF analysis (sub-2s, no persistence) |
| | client.lvl | Business validation runs, call queue, SAM entities |
| | client.samProfiles | SAM.gov search profiles, watchers, automated triggers |
| | client.reviews | Document review queue, approve/correct workflow |
| Real-time | client.events | SSE streams for deals, org events, batch progress |
| | client.webhooks | Webhook config, test, delivery logs, retry |
| | client.notifications | In-app notifications and preferences |
| | client.push | Web push subscriptions |
| Platform | client.team | Invite, update, deactivate members |
| | client.keys | API key management |
| | client.shares | Public deal share links |
| | client.ingest | Bulk CRM ingest with batch tracking |
| | client.crm | Provider config, field mapping, bidirectional sync |
| | client.integrations | Slack, Teams, SMTP notification channels |
| | client.admin | Health, usage, error logs, DLQ, pipeline settings |
| | client.usage | Metering and processing time analytics |
| | client.oauth | Client credentials token exchange |
Plus 5 sub-resources on every deal:
client.deals.comments.list(dealId); // threaded discussion
client.deals.assignments.create(dealId); // assign reviewers
client.deals.docRequests.create(dealId); // request missing docs
client.deals.timeline.list(dealId); // full activity history
client.deals.users.search({ q: "jane" }); // find team membersRetry behavior
| Method | Rate limit (429) | Server error (5xx) | Connection error | |--------|:---:|:---:|:---:| | GET / DELETE | Retry | Retry | Retry | | POST / PUT / PATCH | — | — | Retry |
Exponential backoff with jitter. 500 ms base, 30 s cap. Honors Retry-After.
We ship fast
This SDK is actively maintained by the LendIQ engineering team. We release weekly, respond to issues within 24 hours, and treat SDK quality with the same rigor as our core platform.
If something isn't right, open an issue. We'll fix it.
License
MIT — use it however you want.
Get your API key and start analyzing statements in minutes.
Built with care by the LendIQ team.
