Skip to main content

GSTIN Verification: A Format Check Is Not a Check

D

DL Minds Team

â€ĸ 10 min read
Share:
⚡ Quick Summary
  • A GSTIN carries a mod-36 checksum, so an offline validator catches typos and fabricated numbers instantly, for free, with no network call.
  • It cannot tell you the registration exists. A string can pass the checksum perfectly and have never been issued to anyone.
  • The four things only a lookup answers: does it exist, is it still active, whose legal name is on it, and have they been filing.
  • Use both. Format check on every keystroke at the edge; verification lookup once at onboarding and again before money moves.
  • Cache the result, but treat status and filing history as perishable. Legal name is stable; registration status is not.

Almost every Indian B2B application eventually grows a GSTIN field. An ERP vendor master, a billing system that has to raise a tax invoice, a marketplace onboarding sellers, a fintech running KYB. And almost every one of them ships the same thing first: a regular expression.

That regex is not wrong. It is just doing a much smaller job than the team thinks it is doing, and the gap between those two jobs is where the money gets lost.

What the 15 characters actually mean

A GSTIN is not an opaque identifier. It is composed, and each segment is independently meaningful:

PositionLengthWhat it is
1–22State code. Tells you which state or union territory issued the registration.
3–1210The holder's PAN. This is the part that ties the GSTIN to a legal entity.
131Entity code — which registration this is for that PAN within that state.
141Currently always Z. Reserved, not meaningful today.
151Checksum character, computed from the preceding fourteen.

Two consequences fall straight out of that structure. First, one company can hold many GSTINs — one per state it is registered in — all sharing the same PAN in positions 3 to 12. If your schema assumes one GSTIN per customer, it is wrong for anyone operating in more than one state. Second, because position 15 is derived, a mistyped GSTIN is almost always detectably invalid without asking anyone.

The checksum, in twelve lines

The algorithm treats the alphanumeric characters as base-36 digits: 0–9 map to 0–9 and A–Z map to 10–35. Each of the first fourteen characters is multiplied by a weight that alternates 1, 2, 1, 2 across the string. For each product you add the quotient and the remainder of division by 36, sum all fourteen, and the check character is whatever brings that sum up to the next multiple of 36.

const CHARSET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

function isWellFormedGstin(gstin) {
  if (!/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/.test(gstin)) {
    return false;
  }

  let sum = 0;
  for (let i = 0; i < 14; i++) {
    const product = CHARSET.indexOf(gstin[i]) * ((i % 2) + 1);
    sum += Math.floor(product / 36) + (product % 36);
  }

  return CHARSET[(36 - (sum % 36)) % 36] === gstin[14];
}

That is genuinely useful. It runs in microseconds, needs no network, costs nothing, and rejects the overwhelming majority of bad input — transposed digits, a dropped character, a number somebody invented to get past your form. Put it in the browser and run it again on the server. There is no reason not to.

âš ī¸

What it does not do: the checksum is arithmetic over the string. It has no knowledge of the GST database. You can sit down and construct a 15-character string that satisfies every rule above and has never been issued to any taxpayer in India. Your validator will pass it.

The four questions a format check cannot answer

This is the whole argument, so it is worth being concrete. A well-formed GSTIN leaves all four of these open:

1
Does this registration exist?

A valid checksum proves arithmetic, not issuance. The only way to know a GSTIN was ever granted is to look it up.

2
Is it still active?

Registrations get cancelled and suspended. A GSTIN that verified cleanly when you onboarded the vendor eighteen months ago may not be active today, and nothing about the number itself changes when that happens.

3
Whose name is on it?

The single highest-value field in practice. Your vendor typed a company name into a form and typed a GSTIN into the next box. Only a lookup tells you whether those two things refer to the same legal entity.

4
Have they been filing?

An active registration that has not filed a return in a year is a different risk from an active registration filing on time every month — and the difference lands on your input tax credit, not theirs. We cover that in detail in vendor GST verification and your input tax credit.

What a verification lookup returns

A verification call goes out to live registration data and comes back with the things the string cannot carry. Using our own GSTIN API as the concrete example, a single authenticated GET against /api/get-taxpayer-info/{gstin} returns roughly four groups of fields:

  • Identity — the legal business name on the registration, plus the principal place of business, so you can match both against what the vendor told you.
  • Status — whether the registration is currently active, and the date it was originally granted.
  • Filing history — recent GSTR filing records. This is the field that predicts credit problems downstream.
  • E-invoicing and e-way bill status — whether the taxpayer is in scope for e-invoicing, and their e-way bill activity.

The shape is boring on purpose: one call, one x-api-key header, JSON back. The API documentation has the full field list and a bulk endpoint that takes a job of up to 10,000 numbers if what you actually need is to clean an existing vendor master rather than check one at a time.

💡

If you only need one number right now, there is a free GST number search that does the same lookup in a browser, no integration required. Useful for spot-checking before you decide whether any of this belongs in code.

Where to put each check in your application

The two checks are not alternatives and they do not belong in the same place. Format validation is free and instant, so it goes everywhere. Verification costs a fraction of a rupee and a network round trip, so it goes where a wrong answer is expensive.

MomentFormat checkVerification lookup
User typing into a formYes — inline, on blurNo
Form submit / API writeYes — server side, alwaysNo
Vendor or customer onboardingYesYes — and store the result
Bulk import of a vendor masterYes — filter firstYes — as a bulk job
Raising a tax invoiceYesYes if the cached status is stale
Periodic vendor re-checkPointlessYes — this is the whole point

Note the ordering on bulk import. Running the format check first over a ten thousand row spreadsheet costs nothing and typically removes a meaningful slice of the rows before you pay to verify any of them. Cheap checks go first; that principle is not specific to GST.

Caching: what is stable and what rots

Every verification result has a shelf life, and the fields do not share one. Treating the whole response as a single cache entry with a single TTL is the most common design mistake here.

  • Legal name and registration date — effectively immutable. Cache indefinitely; you are storing history, not state.
  • Principal address — changes rarely. Months is fine.
  • Registration status — the one that bites. A vendor's registration can be cancelled between your invoice and your return. Re-check on a schedule, and always before a large payment.
  • Filing history — updates monthly by nature. Anything older than a filing cycle is telling you about the past.

A practical pattern: store the full response with a fetched-at timestamp, serve identity fields from cache forever, and re-fetch when status or filing data is older than your risk tolerance. For most teams that is monthly for active vendors and on-demand before any payment run.

Five mistakes worth avoiding

  • Assuming one GSTIN per customer. Multi-state vendors have several. Model it as a collection keyed by state from day one; retrofitting this later means touching every invoice.
  • Verifying once and never again. Onboarding-only verification tells you about the day you onboarded. Registrations get cancelled afterwards, and nobody sends you a notification.
  • Blocking checkout on a live lookup. If the upstream is slow, your form is slow. Validate format synchronously, verify asynchronously, and flag the record rather than holding the user hostage.
  • Firing thousands of synchronous requests for a bulk job. This is how you get rate limited halfway through and end up with a half-verified master and no record of where you stopped. Submit a job, poll it, collect results.
  • Storing only a boolean. "Verified: true" throws away the legal name, the status and the timestamp — exactly the fields you will want when someone asks why you paid this vendor. Store the response.

Common questions

Can I verify a GSTIN without an API? Yes, manually, one number at a time on the GST portal or with a free lookup tool. That is fine for occasional checks. It stops being fine the moment the checks need to happen inside a workflow, on a schedule, or across more rows than a person will sit through.

Is the checksum algorithm official? It is the standard mod-36 scheme the GSTIN is constructed with, and it is widely implemented. Test your implementation against real known-good numbers before trusting it — an off-by-one in the weighting produces a validator that rejects perfectly valid GSTINs, which is worse than having none.

Does a valid GSTIN mean the vendor is legitimate? No. It means a registration exists and, if you check status, that it is active. Whether the counterparty is who they claim to be is a name-match question, which is why the legal name field matters more than the boolean.

How often should I re-verify? There is no universal answer, but tie it to exposure rather than the calendar: monthly for vendors you transact with regularly, before any unusually large payment, and immediately if a filing gap appears.

What does verification cost? On GSTIN API it is ₹0.50 per verification, ₹0.40 above 2,500 credits, with 20 free credits on signup and no charge for invalid or non-existent numbers. Current rates are on the pricing page. At those numbers the cost is rarely the deciding factor — the deciding factor is usually whether anyone owns the process.

Should I build this myself? The format check, yes — it is twelve lines and it is above. The lookup is the part where building means sourcing live data, handling upstream failures and running it forever, which is why we turned it into a product instead of rewriting it per client.

✅ Bottom Line

Format validation and verification answer different questions, and shipping only the first is the default failure mode. Validate the shape everywhere, because it is free. Verify against live data at onboarding, before money moves, and on a schedule after that, because that is the only thing that tells you the registration exists, is active, and belongs to the company on your invoice. Store the whole response, not a boolean, and let the different fields expire at different rates.

â„šī¸
Engineering guidance, not tax advice. This post is about where to put a check in an application. What your filings actually require is a question for your own advisor.
Need GST verification inside a system you already run?
GSTIN API is our own product and it is built to be embedded. We also build the ERP, billing and vendor onboarding systems it plugs into.
See GSTIN API →
D

DL Minds Team

Digital marketing and web development expert at DL Minds. Passionate about helping businesses grow through innovative technology solutions and strategic digital marketing.

Enjoyed this article?

Subscribe to our newsletter to get more insights and tips delivered straight to your inbox.