Flowise + Lekha: Build Financial Document AI Agents
Step-by-step guide to integrating Lekha's financial document API with Flowise to build no-code AI agents for Indian fintech use cases.
Flowise lets you build LLM-powered agents visually — drag-and-drop nodes, no boilerplate. Lekha turns any Indian financial document (bank statement, salary slip, ITR, CIBIL) into structured JSON. Together, they let you ship production-grade financial document agents in hours instead of weeks.
This guide walks you through integrating the two: setting up Flowise, wiring in Lekha as a custom tool, and building two real-world agent flows — a loan pre-screening agent and a KYC verification agent.
What You'll Build
Both agents run entirely inside Flowise with Lekha handling the heavy lifting of document extraction.
Prerequisites
Setting Up Flowise
If you don't have Flowise running yet, the fastest path is:
npm install -g flowise
npx flowise start
Or with Docker:
docker run -d -p 3000:3000 flowiseai/flowise
Open http://localhost:3000 and you're in. Flowise stores your flows locally by default — no cloud account required.
How Lekha Fits into a Flowise Flow
Flowise agents call tools to take actions. A tool is any HTTP endpoint or JavaScript function that accepts parameters and returns a result. Lekha's /extract endpoint is a natural fit: it accepts a document (as base64 or a URL) and returns structured JSON.
You have two options for wiring Lekha into Flowise:
We'll use the Custom Tool approach since it lets the agent decide _when_ to call Lekha and with _which_ document.
Building the Lekha Custom Tool Server
Create a new directory and install dependencies:
mkdir lekha-flowise-tool && cd lekha-flowise-tool
npm init -y
npm install express multer node-fetch
Create server.ts:
import express from "express";
import multer from "multer";
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.use(express.json());
const LEKHA_API_KEY = process.env.LEKHA_API_KEY!;
const LEKHA_BASE_URL = "https://api.lekhadev.com";
// Tool manifest — Flowise reads this to discover available tools
app.get("/tools", (_req, res) => {
res.json([
{
name: "extract_bank_statement",
description:
"Extract transactions, balances, and account info from an Indian bank statement PDF. Returns structured JSON with monthly summaries and transaction list.",
parameters: {
type: "object",
properties: {
document_url: {
type: "string",
description: "Publicly accessible URL to the bank statement PDF",
},
password: {
type: "string",
description: "PDF password if the document is encrypted (optional)",
},
},
required: ["document_url"],
},
},
{
name: "extract_salary_slip",
description:
"Extract gross salary, net take-home, deductions, PAN, and employer details from an Indian salary slip PDF.",
parameters: {
type: "object",
properties: {
document_url: {
type: "string",
description: "Publicly accessible URL to the salary slip PDF",
},
},
required: ["document_url"],
},
},
{
name: "extract_cibil_report",
description:
"Extract credit score, active loans, payment history, and DPD (days past due) from a CIBIL credit report PDF.",
parameters: {
type: "object",
properties: {
document_url: {
type: "string",
description: "Publicly accessible URL to the CIBIL report PDF",
},
},
required: ["document_url"],
},
},
]);
});
// Generic extraction handler
async function extractDocument(
documentUrl: string,
docType: string,
password?: string,
) {
const response = await fetch(${LEKHA_BASE_URL}/v1/extract, {
method: "POST",
headers: {
Authorization: Bearer ${LEKHA_API_KEY},
"Content-Type": "application/json",
},
body: JSON.stringify({
document_url: documentUrl,
document_type: docType,
...(password && { password }),
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(Lekha API error: ${error.error?.message ?? "Unknown"});
}
const result = await response.json();
return result.data;
}
// Tool execution endpoints
app.post("/tools/extract_bank_statement", async (req, res) => {
try {
const { document_url, password } = req.body;
const data = await extractDocument(
document_url,
"bank_statement",
password,
);
res.json({ success: true, data });
} catch (err: unknown) {
const message = err instanceof Error ? err.message : "Extraction failed";
res.status(500).json({ success: false, error: message });
}
});
app.post("/tools/extract_salary_slip", async (req, res) => {
try {
const { document_url } = req.body;
const data = await extractDocument(document_url, "salary_slip");
res.json({ success: true, data });
} catch (err: unknown) {
const message = err instanceof Error ? err.message : "Extraction failed";
res.status(500).json({ success: false, error: message });
}
});
app.post("/tools/extract_cibil_report", async (req, res) => {
try {
const { document_url } = req.body;
const data = await extractDocument(document_url, "cibil_report");
res.json({ success: true, data });
} catch (err: unknown) {
const message = err instanceof Error ? err.message : "Extraction failed";
res.status(500).json({ success: false, error: message });
}
});
app.listen(4000, () => {
console.log("Lekha Flowise tool server running on port 4000");
});
Start the server:
LEKHA_API_KEY=lk_live_your_key npx ts-node server.ts
Configuring the Tool in Flowise
http://localhost:4000/toolsNow in the canvas, drag in an Agent node and connect your Lekha tool under Allowed Tools.
Flow 1: Loan Pre-Screening Agent
This agent accepts a bank statement URL and salary slip URL, then returns a structured pre-screening decision.
System Prompt
You are a loan pre-screening assistant for an Indian NBFC.
Given a bank statement and salary slip:
- Extract both documents using the available tools
- Calculate: average monthly credit, net take-home salary, debt-to-income ratio
- Check for: salary credits appearing in bank statement, bounced EMIs, irregular income
- Return a JSON decision: { eligible: boolean, score: number (0-100), reasons: string[] }
Rules:
- Net monthly income must exceed ₹25,000
- Average bank credits must be within 20% of declared salary
- No more than 2 EMI bounces in the last 6 months
- Debt-to-income ratio must be below 50%
Testing the Flow
Send a chat message:
Please pre-screen this applicant:
Bank statement: https://your-storage.com/bank-statement.pdf
Salary slip: https://your-storage.com/salary-slip.pdf
The agent calls extract_bank_statement and extract_salary_slip in parallel (tool-call step), then reasons over the JSON to produce a decision. A typical response looks like:
{
"eligible": true,
"score": 78,
"reasons": [
"Net take-home ₹52,000 exceeds ₹25,000 threshold",
"Salary credit of ₹52,000 matches declared salary (within 5%)",
"Zero EMI bounces in last 6 months",
"Debt-to-income ratio: 32% (below 50% threshold)"
]
}
Flow 2: KYC Cross-Verification Agent
This agent verifies that the PAN and income details on a salary slip match what appears in the CIBIL report.
System Prompt
You are a KYC verification assistant. You have access to document extraction tools.
Given a salary slip and CIBIL report, verify:
- PAN number matches across both documents
- Full name matches (allow minor spelling variations)
- Declared income is consistent with CIBIL-reported EMI obligations
- No adverse accounts (written-off, settled) on CIBIL
Return: { verified: boolean, mismatches: string[], risk_flags: string[] }
Why This Works Better Than Manual Checks
Manual KYC cross-checks require downloading documents, opening them side-by-side, and typing values into a form. With Lekha extracting both documents to structured JSON, the agent can compare fields programmatically — PAN is a string match, name similarity uses fuzzy logic, and income-vs-EMI is arithmetic. The entire flow runs in under 10 seconds.
Deploying to Production
When you're ready to go beyond localhost:
1. Deploy the tool server to a container (Fly.io, Railway, or any VPS):# Dockerfile
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "dist/server.js"]
2. Use Lekha's embed endpoint for document upload — your users can upload directly without exposing your cloud storage URLs:
// Accept a file upload, send to Lekha, never touch disk
app.post(
"/tools/extract_from_upload",
upload.single("document"),
async (req, res) => {
const formData = new FormData();
formData.append(
"document",
new Blob([req.file!.buffer], { type: "application/pdf" }),
req.file!.originalname,
);
formData.append("document_type", req.body.document_type);
const response = await fetch(${LEKHA_BASE_URL}/v1/extract, {
method: "POST",
headers: { Authorization: Bearer ${LEKHA_API_KEY} },
body: formData,
});
const result = await response.json();
res.json(result);
},
);
Documents are processed in-memory and never stored — DPDP compliant by default.
3. Add Flowise's built-in auth to protect your agent endpoint before going public.When to Use Flowise vs. Code
| Scenario | Flowise | Code (TypeScript SDK) | | ------------------------------ | -------------------- | --------------------- | | Internal tool for ops team | ✅ Fast to build | Overkill | | Prototyping a new agent flow | ✅ Visual iteration | Slower | | Customer-facing production API | Possible but verbose | ✅ Better control | | Complex branching logic | Limited | ✅ Full flexibility | | CI/CD, versioning | ❌ JSON export only | ✅ Git-native |
Flowise is excellent for internal tools and prototypes. Once you've validated the logic, translating to a TypeScript service using the Lekha REST API gives you full control — check the Lekha API docs for the full extraction schema.
Try It in the Playground
Don't have documents ready? Test Lekha's extraction directly at lekhadev.com/playground — upload any Indian financial document and see the structured JSON output in seconds.
FAQ
Does Flowise support file uploads natively so users can upload directly in chat?Flowise supports file uploads in its chat widget (v2.1+). Enable it under Chatflow Settings → File Upload. The file arrives as a base64 string in the tool input — update your tool server to decode it and pass it to Lekha's multipart endpoint.
How do I handle password-protected bank statement PDFs?Add a password field to your tool schema and pass it through to Lekha's API. Prompt the agent to ask the user for the password when it encounters an encrypted PDF. Lekha handles decryption server-side before extraction.
Yes — modern LLMs (GPT-4o, Claude Sonnet) support parallel tool calls. If you ask the agent to extract a bank statement and a salary slip at the same time, it issues both tool calls in one step and waits for both results. Flowise handles this automatically.
Is there a cost to running Lekha extractions through Flowise?Flowise itself is open-source and free to self-host. Lekha charges per extraction — see the pricing page for current rates. The free tier includes enough credits to prototype comfortably before scaling.
Ready to build your own financial document agent? Sign up for a free Lekha API key and follow along — the tool server code above is the only backend you need.