How to Cut Your GST Verification API Bill by 70%
Four techniques that remove most of the calls in a GSTIN verification pipeline: deduplication, offline pre-validation, caching, and scheduled re-checks.
Almost every large GST verification bill is not a pricing problem. It is a call-volume problem wearing a pricing problem's clothes. The team negotiating a lower per-call rate is optimising the small term; the interesting term is the number of calls, and in most pipelines that number is several times larger than it needs to be.
This page covers four techniques that remove calls — deduplication, offline pre-validation, caching, and re-checking on a cadence rather than on every read. None of them changes what you learn about a supplier. They only change how many times you pay to learn it.
Where the calls actually go
Before optimising anything, count. In every over-priced pipeline we have seen described, the volume sits in one of four places, and they are worth separating because each has a different fix:
| Source | What it looks like | Fix |
|---|---|---|
| Repeated GSTINs | The same supplier on 40 invoice lines, verified 40 times | Deduplicate on the normalised value |
| Malformed rows | Truncated numbers, PANs pasted into the wrong column, half-typed entries | Format and checksum check, offline |
| Re-reads | A verification fired on every page view, every export, every reconciliation pass | Cache, then read from your own database |
| Genuine change detection | Sweeping the active supplier list for cancellations | Nothing — this is the call you are actually paying for |
The last row is the only one that buys information. Everything above it is arithmetic you can do yourself. If you have never measured the split, log the GSTIN of every verification for a week and count distinct values against total calls — the ratio is usually the whole story, and it is the number that decides whether any of the rest of this page is worth your afternoon.
1. Deduplicate before you loop
Vendor masters, invoice exports and ERP extracts all repeat the same GSTIN, often many times over. A supplier billing you weekly appears on fifty-two rows a year, and every one of those rows carries the same fifteen characters. Verified naively, that is fifty-two credits for one fact.
The subtlety is what you deduplicate on. Human-entered and system-exported GSTINs arrive dressed
up in whitespace, hyphens and mixed case, and a naive set() treats each variation as a
separate number:
" 27-AAACR 5055 K1Z7 " -> one call
"27aaacr5055k1z7" -> another call
"27AAACR5055K1Z7" -> a third call
Three credits, one GSTIN. Normalise first — uppercase, then strip everything that is not a letter or a digit — and deduplicate on that:
import re
def normalise(gstin: str) -> str:
return re.sub(r"[^0-9A-Z]", "", gstin.upper())
unique = {normalise(row["gstin"]) for row in rows}
Our client libraries do this inside the batch helpers, so you do not have to remember: pass the raw column
straight from your export to verify_many in Python or verifyMany in Node, and the
same GSTIN appearing five times costs one credit. Both are MIT-licensed and dependency-free —
PyPI and
npm.
const { results, lookedUp, skipped } = await client.verifyMany(gstins, {
concurrency: 8,
});
// gstins.length may be 50,000.
// lookedUp is what you were actually billed for.
Watch lookedUp against the length of the input you handed in. That single ratio tells you, on
the first run, whether deduplication alone has already solved your problem.
2. Validate offline first
A GSTIN that fails its own checksum cannot possibly correspond to a registration, because no such number was ever issued. Sending it upstream spends a credit to be told what arithmetic already knew, in a hundred milliseconds rather than a microsecond.
The format check is a fifteen-character pattern; the check digit is a modulus-36 Luhn variant that catches every single-character typo. Together they need no network, no credit and about twenty lines of code, and they remove exactly the rows that would have failed anyway.
Our clients enforce this before the wire: a single verify call with a malformed argument
raises InvalidGstinError without a request ever leaving the process, and the batch helpers put
malformed rows straight into skipped rather than spending a credit on them. That is the point
of the distinction between validation and verification, laid out in full in
validation vs verification: the free check exists to
make the paid one cheap, not to replace it.
3. Cache, with a TTL you can defend
Taxpayer data upstream refreshes a few times a day, not continuously. Verifying the same GSTIN twice inside a minute is therefore not just two credits for one fact — it is two credits for one fact that could not have changed in between. A short cache is free money and free accuracy at once.
The right time-to-live depends on what the answer is being used for, not on a general principle:
| Use case | Suggested TTL | Reasoning |
|---|---|---|
| Interactive lookup someone is watching | Minutes to an hour | Covers refreshes, back-button navigation and the second person checking the same supplier this morning |
| Vendor-master refresh | Hours | The run itself takes hours; a GSTIN touched twice within one run should cost once |
| Bulk reconciliation over historic invoices | A day or more | You are asking about a past period. Today's status at 9am and at 5pm is the same answer |
| Immediately before a payment run | No cache | This is the moment the answer has to be current. Pay the credit |
Three rules make the difference between a cache that saves money and one that creates incidents:
- Cache successes only. Storing a timeout, a
502or a429converts a thirty-second blip into hours of confidently wrong answers served from your own infrastructure. Errors should be retried with backoff, not memorised — see rate limits, retries and webhooks. - Cache "no registration found" briefly, if at all. A GSTIN that does not resolve today may be issued next week, and a long negative cache means you keep rejecting a supplier who has since registered.
- Key on the normalised GSTIN. The same normalisation as the deduplication step, or the cache will miss on exactly the variations deduplication was written to collapse.
4. Re-check on a schedule, not on every read
This is the expensive one, and it is usually invisible in the code that causes it. A verification call wired into a supplier detail page, an invoice line renderer, or a report that iterates rows will multiply your bill by the number of times anyone looks at anything — while adding no information at all, because a GST registration status changes on the order of once in its lifetime, not once per page view.
The correct shape is to treat verification as an event that writes a fact into your own database, and every read afterwards as a database read:
- At onboarding. Verify once when a supplier is created, and store the result with a
verified_attimestamp. - Before a high-value payment. Re-verify at the decision point, where the answer being current is worth an actual credit. This is the pattern described in vendor GST verification in accounts payable.
- On a sweep. Re-verify the active supplier list on a cadence. Monthly is a common compromise; weekly or daily is right for high-risk or high-value counterparties — see automated daily vendor GSTIN monitoring.
- Everywhere else, read your own row. Display the stored status alongside its
verified_atdate so the reader can see how fresh it is, rather than silently implying it is live.
A worked example
Here is the arithmetic end to end. Every figure below is an assumption, labelled as such — the point is the shape of the funnel and the fact that you can redo it with your own numbers, not the specific percentages.
| Step | Assumption | Calls remaining |
|---|---|---|
| Raw export | A vendor and invoice extract | 50,000 |
| Deduplicate on the normalised value | Assume 12,000 distinct GSTINs | 12,000 |
| Drop malformed rows offline | Assume 3% fail format or checksum | 11,640 |
| Skip cached, unchanged entries | Assume 60% still fresh from last month's run | 4,656 |
Two reductions fall out of that table, and they answer different questions:
- 4,656 against 50,000 is a 90.7% reduction. This is the honest number if your current pipeline verifies every row of the export. It is driven overwhelmingly by the duplication rate — the 50,000 to 12,000 step alone is 76% of the saving.
- 4,656 against 12,000 is a 61.2% reduction. This is the number if you already deduplicate, and it is driven almost entirely by the cache hit rate. The 3% pre-validation step contributes a little over half a percentage point here.
The headline 70% sits between those two, which is exactly the point: it is not a promise, it is a range. If your export has no duplicates, the first saving disappears. If you verify each GSTIN once and never again, the cache saving disappears. If your data is clean, pre-validation saves you almost nothing. Put your own duplication rate, malformed-row percentage and cache hit rate into the same four lines and you will get your own figure — and if that figure is small, you have learnt something useful, which is that your bill is not made of waste.
Two savings that are not worth it
Both of these do reduce the bill. Both of them cost more than they save, which is a different thing, and being clear about the difference is the reason to trust the four techniques above.
Skipping verification for small invoices
The reasoning sounds thrifty: why spend a credit checking a counterparty on a ₹4,000 invoice? Because fraud is not correlated with invoice size. A fabricated or cancelled GSTIN on a small invoice is exactly as fabricated as on a large one, and a small invoice is precisely where someone testing whether your controls work would start. An input tax credit reversal, with interest and the time spent reconciling it, costs considerably more than a lookup.
Verify the counterparty, not the transaction value. A supplier verified once at onboarding and swept monthly covers all of their invoices, large and small, for the price of the sweep — which is the whole argument of the cadence section, applied to the case where it feels expensive.
Caching for months, or never re-checking
A cancelled registration you last checked in March is not information. It is a liability that reads like information, which is worse than having no answer at all, because nobody thinks to question it. The saving from stretching a TTL from a day to a quarter is small — most of the cache benefit is captured in the first few hours — and the exposure grows the entire time.
Two related traps in the same family:
- Do not cache errors. Repeated for emphasis, because it is the most common way a cache causes an incident rather than preventing one.
- Do not share a cache across tenants in a multi-tenant product without checking your provider's terms first. Serving one customer an answer that another customer's credit paid for is a commercial arrangement, not a technical optimisation, and it is worth being sure it is one you are allowed to make.
And scraping the portal instead
Worth naming, because it comes up whenever someone is looking at a bill. Driving the public GST portal with a headless browser to avoid per-call costs is rate-limited, CAPTCHA-guarded, fragile against markup changes nobody announces, and outside what the portal's terms contemplate. The engineering time to keep it alive usually exceeds the API spend it was meant to replace within a couple of months — the full comparison is in GST API vs portal scraping.
Frequently asked questions
The mechanics of a batch run are in the bulk GSTIN verification guide and bulk verification from a CSV upload; how the credit model itself works is in GST API pricing explained and on the pricing page. If you want to check the arithmetic against one number before writing any of this, the free GST number search and the API documentation are the fastest route, and a free account gets you enough credits to measure your own duplication rate.
A note on accuracy. GST rules change often. This article reflects our understanding as of 8 September 2026 and is general information, not tax or legal advice. For the authoritative position, check gst.gov.in and cbic-gst.gov.in, or speak to a qualified tax professional about your specific situation.
Check a GSTIN right now, free
Five lookups a day, no account required. Status, filing history, e-invoicing and jurisdiction.
Free GST search toolBuild it into your product
One REST call, JSON back. Get an API key and 20 free verification credits in under a minute.
Start freeMore on pricing & cost
Browse every guide in the GST API blog.