GST Invoice Parser: Extract Structured Data for AI Agents
Parse Indian GST invoices with AI. Extract GSTIN, HSN codes, line items, and tax breakdowns into structured JSON for fintech agents and compliance automation.
GST compliance is mandatory for over 14 million registered businesses in India. Every purchase invoice, return filing, and ITC reconciliation involves structured data locked inside PDFs — data that AI agents need to read, verify, and act on.
Lekha's GST invoice parser extracts GSTIN, invoice numbers, line items, HSN codes, and tax breakdowns from any Indian GST document in under three seconds. The response is clean, typed JSON with amounts as numbers and dates in ISO 8601 — ready for your database, workflow engine, or downstream agent without any cleanup.This guide walks through building a GST compliance agent: parsing invoices, validating GSTINs, verifying tax calculations, and reconciling ITC against GSTR-2A.
What's Inside a GST Invoice?
A well-formed Indian GST invoice carries more fields than most developers expect. Here's a quick reference:
| Field | Description | | --------------- | --------------------------------------------------------------------------- | | GSTIN | 15-digit taxpayer identification (2 state + 10 PAN + entity + Z + checksum) | | IRN | Invoice Reference Number (mandatory for e-invoices above ₹5 crore turnover) | | HSN / SAC Code | Harmonized System / Service Accounting Code per line item | | Taxable Value | Pre-tax amount — the base for GST calculation | | CGST / SGST | Central and State GST — applies to intra-state supplies | | IGST | Integrated GST — applies to inter-state and import supplies | | Reverse Charge | Whether buyer or seller is liable to pay tax | | ITC Eligibility | Whether the buyer can claim input tax credit | | E-Way Bill | Logistics reference for goods over ₹50,000 |
A single invoice can carry 30+ line items, each with its own HSN code, tax rate, and exemption status. Manually extracting this into a database is slow, error-prone, and completely unscalable for any business handling more than a handful of invoices per day.
Why Vision AI Outperforms Template Parsing for GST
Indian GST invoices come in thousands of formats. Tally, Zoho Books, Busy, QuickBooks India, Marg, and hundreds of custom ERP implementations all generate different layouts. Template-based OCR breaks when:
Vision AI reads documents the way a human accountant does — semantically, not positionally. Lekha's extraction pipeline is trained on real Indian GST documents across all major accounting platforms and handles both digital PDFs and scanned images with equal accuracy.
Quick Start: Parse Your First GST Invoice
Install the Lekha SDK and send a document:
npm install @lekhadev/sdk
or
bun add @lekhadev/sdk
import Lekha from "@lekhadev/sdk";
import { readFileSync } from "fs";
const lekha = new Lekha({ apiKey: process.env.LEKHA_API_KEY });
const pdfBuffer = readFileSync("./invoice.pdf");
const result = await lekha.extract({
document: pdfBuffer,
type: "gst_invoice",
});
console.log(result.data);
The response is structured JSON — no post-processing needed:
{
"supplier": {
"name": "Acme Components Pvt Ltd",
"gstin": "27AABCA1234F1Z5",
"address": "Plot 14, MIDC, Pune, Maharashtra 411019"
},
"buyer": {
"name": "TechStart Solutions Pvt Ltd",
"gstin": "07AACCT5678G1ZP",
"address": "Floor 3, Sector 44, Gurugram, Haryana 122003"
},
"invoice": {
"number": "INV-2024-00847",
"date": "2024-03-15",
"due_date": "2024-04-14",
"irn": "a1b2c3d4e5f6...",
"place_of_supply": "Haryana",
"reverse_charge": false
},
"line_items": [
{
"description": "Industrial Grade PCB Assembly",
"hsn_code": "8534",
"quantity": 500,
"unit": "NOS",
"unit_price": 120,
"taxable_value": 60000,
"igst_rate": 18,
"igst_amount": 10800,
"cgst_rate": 0,
"cgst_amount": 0,
"sgst_rate": 0,
"sgst_amount": 0,
"total": 70800
}
],
"totals": {
"taxable_value": 60000,
"igst": 10800,
"cgst": 0,
"sgst": 0,
"total_tax": 10800,
"grand_total": 70800,
"itc_eligible": true
}
}
Amounts are always numbers (never "Rs. 70,800"), dates are always ISO 8601, and supply type (intra vs inter-state) is resolved automatically from the GSTINs and place of supply.
Building a GST Compliance Validation Agent
Here's a complete agent that parses invoices and flags compliance issues before they reach your accounting team:
import Lekha from "@lekhadev/sdk";
import { readFileSync } from "fs";
const lekha = new Lekha({ apiKey: process.env.LEKHA_API_KEY });
interface ComplianceResult {
invoice_number: string;
supplier_gstin: string;
gstin_valid: boolean;
tax_calculation_correct: boolean;
itc_claimable: boolean;
flags: string[];
total_amount: number;
}
async function validateGSTInvoice(
pdfBuffer: Buffer,
): Promise {
const result = await lekha.extract({
document: pdfBuffer,
type: "gst_invoice",
});
const { supplier, invoice, line_items, totals } = result.data;
const flags: string[] = [];
// Validate GSTIN format (15-char: 2 state + 10 PAN + 1 entity + Z + checksum)
const gstinRegex =
/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/;
const gstin_valid = gstinRegex.test(supplier.gstin);
if (!gstin_valid) flags.push("Invalid supplier GSTIN format");
// Verify tax arithmetic across all line items
const computed_tax = line_items.reduce(
(sum: number, item: any) =>
sum +
(item.igst_amount ?? 0) +
(item.cgst_amount ?? 0) +
(item.sgst_amount ?? 0),
0,
);
const tax_calculation_correct = Math.abs(computed_tax - totals.total_tax) < 1;
if (!tax_calculation_correct)
flags.push(
Tax mismatch: computed ₹${computed_tax}, invoice states ₹${totals.total_tax},
);
// Flag items missing HSN/SAC codes (mandatory for B2B above ₹5L)
const missing_hsn = line_items.filter((item: any) => !item.hsn_code);
if (missing_hsn.length > 0)
flags.push(${missing_hsn.length} line item(s) missing HSN/SAC code);
// Flag reverse charge without acknowledgement
if (invoice.reverse_charge && !totals.reverse_charge_acknowledged)
flags.push("Reverse charge liability not acknowledged");
return {
invoice_number: invoice.number,
supplier_gstin: supplier.gstin,
gstin_valid,
tax_calculation_correct,
itc_claimable: totals.itc_eligible,
flags,
total_amount: totals.grand_total,
};
}
// Process a batch of purchase invoices
const invoiceFiles = ["inv_001.pdf", "inv_002.pdf", "inv_003.pdf"];
const results = await Promise.all(
invoiceFiles.map((file) => validateGSTInvoice(readFileSync(file))),
);
const flagged = results.filter((r) => r.flags.length > 0);
console.log(Processed ${results.length} invoices. Flagged: ${flagged.length});
flagged.forEach((r) => {
console.log([${r.invoice_number}] ${r.flags.join(" | ")});
});
Running this over a month's purchase invoices before filing takes seconds and surfaces errors — wrong GSTIN checksum, tax rounding discrepancies, missing HSN codes — that would otherwise cause GSTR-2A mismatches.
ITC Reconciliation: Matching Invoices to GSTR-2A
The most painful part of GST compliance for finance teams is ITC reconciliation — cross-referencing your purchase invoices against the GSTR-2A auto-populated from your suppliers' filings. Lekha parses both, making it straightforward to automate:
async function reconcileITC(
purchaseInvoiceBuffers: Buffer[],
gstr2aBuffer: Buffer,
) {
// Parse all purchase invoices and the GSTR-2A concurrently
const [invoiceResults, gstr2aResult] = await Promise.all([
Promise.all(
purchaseInvoiceBuffers.map((buf) =>
lekha.extract({ document: buf, type: "gst_invoice" }),
),
),
lekha.extract({ document: gstr2aBuffer, type: "gst_return" }),
]);
// Build a lookup map: supplier GSTIN → GSTR-2A entry
const supplierMap = new Map(
gstr2aResult.data.entries.map((e: any) => [e.supplier_gstin, e]),
);
const reconciliation = invoiceResults.map((result) => {
const inv = result.data;
const gstr2aEntry = supplierMap.get(inv.supplier.gstin);
return {
invoice_number: inv.invoice.number,
supplier: inv.supplier.name,
gstin: inv.supplier.gstin,
claimed_itc: inv.totals.total_tax,
available_itc: gstr2aEntry?.tax_amount ?? 0,
matched: gstr2aEntry !== undefined,
discrepancy: gstr2aEntry
? inv.totals.total_tax - gstr2aEntry.tax_amount
: inv.totals.total_tax,
};
});
const totalClaimed = reconciliation.reduce((s, r) => s + r.claimed_itc, 0);
const totalAvailable = reconciliation.reduce(
(s, r) => s + r.available_itc,
0,
);
return {
reconciliation,
summary: {
total_invoices: invoiceResults.length,
matched: reconciliation.filter((r) => r.matched).length,
unmatched: reconciliation.filter((r) => !r.matched).length,
total_itc_claimed: totalClaimed,
total_itc_available: totalAvailable,
net_discrepancy: totalClaimed - totalAvailable,
},
};
}
Unmatched entries mean either the supplier hasn't filed their GSTR-1 yet, or they used a different GSTIN. Knowing this before filing day — rather than discovering it during a GST audit — saves significant penalty exposure.
Common Use Cases
Accounts payable automation — Extract invoice data automatically, match against purchase orders, and route for approval without any keyboard entry. Reduces AP processing time from days to minutes. Vendor compliance screening — During vendor onboarding, verify GSTIN format and check that the state code matches the supplier's billing address before adding them to your vendor master. Expense management — Parse employee expense invoices to separate GST-eligible and exempt costs, compute reimbursable amounts, and flag personal expenses with no valid GSTIN. E-commerce seller analytics — Aggregate GST collected across thousands of B2C invoices by HSN code to generate filing summaries and identify your highest-liability product categories. Audit preparation — Generate a structured, machine-readable ledger of all GST transactions for a financial year, ready for upload to GST department portals or CA review.Test with the Lekha Playground
Before writing a single line of integration code, try your own invoices at lekhadev.com/playground. Upload a PDF, choose gst_invoice as the document type, and see the extracted JSON in real time — no API key needed.
Full API reference and supported field schemas are at lekhadev.com/docs.
FAQ
Does Lekha support both B2B and B2C GST invoices? Yes. Lekha extracts data from all GST invoice types: B2B (business-to-business with buyer GSTIN), B2C (retail without buyer GSTIN), export invoices with or without IGST payment, and bills of supply for exempt or composition dealers. Can Lekha parse e-invoices generated by the IRP with QR codes? Yes. E-invoices registered on the Invoice Registration Portal include an IRN (Invoice Reference Number), a signed QR code, and sometimes an e-way bill number. Lekha extracts all of these fields alongside the standard invoice data. What if an invoice covers both intra-state and inter-state line items? Lekha handles mixed-supply invoices by extracting the tax type (CGST+SGST or IGST) at the line-item level, not just at the document level, so each row carries its own applicable tax correctly. Is document data stored by Lekha after extraction? No. Lekha is DPDP-compliant — documents are processed entirely in memory and never written to disk or persistent storage. The extracted JSON is returned to you and nowhere else. See the full policy at lekhadev.com/privacy.Ready to automate GST invoice processing? Sign up at lekhadev.com and get your API key in 60 seconds. The free tier includes 50 extractions per month — enough to validate your entire use case before committing.