Schedule icon
Write icon
Queries icon
If icon
Log icon
SlackIncomingWebhook icon

Validate GSTINs in Your Vendor Master Before They Break Invoices and Input Tax Credit

Audit vendor GSTINs on a schedule with DuckDB. Catch bad check digits, wrong state codes, invalid PANs, duplicates and billing state mismatches.

Categories
BusinessData

A single mistyped character in a vendor's GSTIN is enough to put an invoice on the wrong return, to show up as a mismatch in GSTR-2B, and to put the input tax credit on that purchase at risk. This blueprint audits the whole vendor master on a schedule and tells you exactly which records to fix and why, before the next payment run. Every check runs locally in DuckDB: no GST portal credentials, no paid API, and no vendor data leaving your Kestra instance.

How it works

  1. sample_vendor_master (io.kestra.plugin.core.storage.Write) writes a 14-row vendor master that contains one example of every problem. It is used only when the vendor_file input is empty, so the flow runs out of the box.

  2. validate_gstins (io.kestra.plugin.jdbc.duckdb.Queries) loads the CSV through inputFiles, normalises each GSTIN (trims spaces, removes dashes, upper-cases it) and runs these checks:

    • length is 15 characters, and the structure is 2 digits + 10-character PAN + entity number + Z + check digit;
    • the state code is one of the GST state and union territory codes (01 to 38, 97, 99);
    • the PAN holder type (4th character of the PAN) is valid;
    • the 13th character is not 0 and the 14th character is Z;
    • the check digit matches the Luhn mod 36 checksum over the first 14 characters;
    • the same GSTIN is not attached to two vendor records;
    • the registration state matches the vendor's billing state (warning), and vendors without a GSTIN are flagged (warning).

    The full per-vendor result is written to gstin_report.csv with outputFiles, and the final SELECT returns the summary row through fetchType: FETCH_ONE, available as outputs.validate_gstins.outputs[0].row.

  3. route_findings (io.kestra.plugin.core.flow.If) logs every error and warning when at least one GSTIN is invalid, and a nested If posts the same findings to Slack when notify_slack is true. A clean audit is logged as well.

  4. The errors block logs a failed audit loudly, because an audit that silently does not run looks the same as a clean vendor master.

  5. The weekly_vendor_audit Schedule trigger (Monday 07:00 IST, shipped disabled) runs the audit before the week's purchase invoices are booked.

What you get

  • outputs.gstin_report: CSV with vendor_id, vendor_name, gstin_raw, gstin, status (ERROR, WARNING or OK), issues, notes, gstin_state, billing_state and pan, sorted with errors first.
  • outputs.audit_summary: JSON with total_vendors, ok_count, warning_count, error_count, error_details and warning_details.
  • Plain-language reasons such as "Check digit is M but should be F (typo in the GSTIN?)" or "GSTIN is registered in Uttar Pradesh but the billing state is Bihar (IGST vs CGST/SGST may be wrong)".
  • With the sample data: 7 errors (a bad check digit, a 14-character GSTIN, the same GSTIN on two vendor records, unknown state code 40, an invalid PAN holder type, a 14th character that is not Z), 2 warnings (state mismatch, no GSTIN) and 5 valid vendors, including a lower-case GSTIN with spaces that is normalised, a Ladakh (38) registration, and the same PAN registered in two states.

Who it's for

  • Accounts payable and finance operations teams in India who maintain vendor masters in an ERP, Tally, or a spreadsheet export.
  • Data teams that load vendor data into a warehouse and want a quality gate before it feeds invoicing or GST reconciliation.
  • Anyone onboarding vendors in bulk who wants mistakes caught on day one instead of in the GSTR-2B mismatch report.

Why orchestrate this with Kestra

A one-off script can validate a CSV once. Kestra runs the same audit every week, keeps the report from every run in the execution history, branches on the result, and can alert the people who fix vendor records. Because the input is just a file, the same flow can be triggered when a new vendor export lands in S3, SFTP or Google Drive, or called as a subflow from an onboarding process.

Prerequisites

  • Nothing for the demo: the sample vendor master is built in.
  • For your own data: a CSV export of the vendor master with the columns vendor_id, vendor_name, gstin and billing_state (the state or union territory name, for example Tamil Nadu).

Inputs

  • vendor_file (FILE, optional): your vendor master CSV. When empty, the built-in sample is used.
  • notify_slack (BOOL, default false): post the findings to Slack when at least one GSTIN is invalid.

Secrets

  • SLACK_WEBHOOK_URL: Slack incoming webhook URL. Only needed when notify_slack is true.

Quick start

  1. Save the flow and run it with the default inputs.
  2. Open the logs of log_errors and download gstin_report from the Outputs tab to see the result for the sample vendors.
  3. Run it again and upload your own vendor export as vendor_file.
  4. Optional: add the SLACK_WEBHOOK_URL secret and set notify_slack to true.
  5. Replace the input with your real source and set disabled: false on weekly_vendor_audit.

Common pitfalls

  • These checks prove a GSTIN is well formed, not that it is active. A cancelled or suspended registration still passes, so pair this audit with a periodic status check on the GST portal (or your GSP's API) for high-value vendors.
  • Pass the billing state as a name, not a code. Common older names (Orissa, Pondicherry, Chattisgarh) are mapped automatically. Andhra Pradesh registrations can carry either code 28 or 37, and both are accepted.
  • Spreadsheets sometimes strip leading zeros, turning 09ABCDE... into 9ABCDE.... The length check catches it; keep the column as text when exporting.

How to extend

  • Read the vendor master straight from your ERP or warehouse (Postgres, MySQL, BigQuery, Snowflake) instead of a file, and write report back to a table.
  • Trigger the audit when a new export lands, with the S3, SFTP or Google Drive triggers.
  • Wrap the alert in a ForEach over the failing vendors to open one ticket per vendor in Jira or ServiceNow.
  • Add an active-status check for new vendors through your GST Suvidha Provider's API before they are approved.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.