Guide · Node.js · SDK · India · GST Compliance

Indian Business Compliance — GSTIN Validation

India's GST system uses 15-character GSTIN numbers that encode the state, PAN, entity type, and a checksum. Here's how to validate GSTINs, extract embedded business metadata, and build a GST compliance check into your onboarding flow.

1. What is GSTIN and why validate it

GSTIN (Goods and Services Tax Identification Number) is a 15-character alphanumeric identifier assigned to every registered GST taxpayer in India. It was introduced with India's landmark GST reform of 2017, replacing a fragmented state-level tax system with a unified national system.

Any business with annual turnover above ₹40 lakh (₹20 lakh for services in most states) must register and collect GST. When onboarding Indian business partners, vendors, or customers, validating their GSTIN is essential for:

  • Input Tax Credit (ITC) eligibility — you can only claim ITC against invoices from GST-registered suppliers with valid GSTINs
  • GST Rule 36(4) compliance — limits ITC to suppliers who have filed their GSTR-1 returns
  • Fraud prevention — fake GSTINs are used in GST invoice fraud; validation catches structural anomalies
  • Vendor due diligence — cross-referencing the embedded PAN confirms the legal entity identity
⚠️Claiming ITC against invoices from invalid or cancelled GSTINs results in ITC reversal plus 18% interest and potential penalties from GSTN. Pre-validation at onboarding is far cheaper than post-assessment corrections.

2. The 15-character GSTIN structure

Every GSTIN encodes several pieces of business information:

PositionCharactersMeaningExample
1–227State code (01–37)27 = Maharashtra
3–12AAPFU0939FPAN of the registered entity10-character PAN
131Entity number (1–9, A–Z)Multiple registrations in same state
14ZDefault 'Z'Always Z in current format
15VCheck character (alphanumeric)Weighted checksum

Example: 27AAPFU0939F1ZV = Maharashtra (27) + PAN AAPFU0939F + entity 1 + Z + check V.


3. Validating with the API

The endpoint validates the full 15-character GSTIN and extracts the embedded metadata:

Example response

{
  "valid": true,
  "gstin": "27AAPFU0939F1ZV",
  "stateCode": "27",
  "stateName": "Maharashtra",
  "pan": "AAPFU0939F",
  "entityNumber": "1",
  "entityType": "Firm",
  "checkChar": "V"
}

4. What to check in your code

1

valid === true — the check character and overall format pass validation

2

stateCode and stateName — verify the registration state matches the supplier's declared operating state

3

pan — the embedded PAN identifies the legal entity; cross-reference with the provided PAN for KYC

4

entityType — "Firm", "Individual", "Company", etc. for KYC categorization and appropriate verification workflow


5. Code example — single and batch validation

import { createClient } from '@isvalid-dev/sdk';

const iv = createClient({ apiKey: process.env.ISVALID_API_KEY });

async function validateGSTIN(gstin) {
  const result = await iv.gstin(gstin);
  return {
    valid: result.valid,
    stateCode: result.stateCode ?? null,
    stateName: result.stateName ?? null,
    pan: result.pan ?? null,
    entityType: result.entityType ?? null,
    entityNumber: result.entityNumber ?? null,
    checkChar: result.checkChar ?? null,
  };
}

// ── Single validation ───────────────────────────────────────────────────────
const vendor = await validateGSTIN('27AAPFU0939F1ZV');
if (!vendor.valid) {
  console.error('Invalid GSTIN — reject invoice, do not claim ITC');
} else {
  console.log(`✓ ${vendor.stateName} | PAN: ${vendor.pan} | Entity: ${vendor.entityType}`);
}

// ── Batch validation for ITC reconciliation ─────────────────────────────────
const vendorGSTINs = [
  '27AAPFU0939F1ZV',  // Maharashtra
  '29GGGGG1314R9Z6',  // Karnataka
  '19AABCT3518Q1ZV',  // West Bengal
];

const results = await Promise.all(
  vendorGSTINs.map(gstin => validateGSTIN(gstin))
);

results.forEach((r, i) => {
  const gstin = vendorGSTINs[i];
  if (!r.valid) {
    console.log(`GSTIN ${gstin}: ✗ INVALID — withhold ITC`);
  } else {
    console.log(`GSTIN ${gstin}: ✓ ${r.stateName} | ${r.entityType} | PAN: ${r.pan}`);
  }
});
For month-end ITC reconciliation, batch all vendor GSTINs with Promise.all — validates the entire vendor list in a single parallel round-trip.

6. cURL example

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/gstin?value=27AAPFU0939F1ZV"

7. Handling edge cases

State code mismatch

Supplier claims to be in Maharashtra (27) but the GSTIN starts with 29 (Karnataka). This could indicate the supplier operates from a different state — verify before approving.

if (gstinResult.valid && gstinResult.stateCode !== expectedStateCode) {
  logger.warn(`State mismatch: GSTIN state=${gstinResult.stateName}, declared=${expectedState}`);
  return { status: 'review_required', reason: 'GSTIN state does not match declared state' };
}

Multiple GSTINs for the same PAN

Large enterprises can have multiple GSTINs for the same PAN (one per state). The entity number (position 13) differentiates them. This is valid and expected.

// Same PAN, different states — all valid for ITC purposes
// Detect multiple registrations by grouping by PAN
const byPan = results.reduce((acc, r) => {
  if (r.valid && r.pan) {
    acc[r.pan] = acc[r.pan] || [];
    acc[r.pan].push(r.stateCode);
  }
  return acc;
}, {});
// { 'AAPFU0939F': ['27', '29'] } → same entity, 2 state registrations

Format valid but registration cancelled

GSTIN format validation confirms the checksum, not the active registration status. A structurally valid GSTIN could belong to a cancelled registration. For high-value vendor relationships, verify active status on the GSTN portal.

// API validates format/checksum — for active registration status,
// consider periodic re-verification against GSTN portal
if (gstinResult.valid) {
  vendor.gstinVerifiedAt = new Date();
  vendor.gstinNextVerify = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // re-check in 30 days
}

8. Summary checklist

Extract and cross-reference the embedded PAN — state code + PAN is the key for ITC reconciliation
Validate GSTIN at onboarding and periodically re-check — registrations can be cancelled
Check stateCode matches supplier's declared state — mismatch is a red flag for fake GSTINs
Batch validate vendor GSTINs for ITC reconciliation — Rule 36(4) limits credit to filing suppliers
Do not accept GST invoices from invalid GSTINs — ITC claims will be rejected by GSTN
Do not treat checksum validity as active registration — format valid ≠ currently registered

See also

Validate Indian GST registrations at scale

Free tier includes 100 API calls per day. GSTIN validation with state code and PAN extraction included. No credit card required.