GST API Integration: From API Key to Production
A framework-agnostic integration guide — auth, endpoints, response shape, error handling, retries, caching and the tests to write before you ship.
The first GST verification call takes about five minutes. Everything that makes the integration survive contact with production — the error taxonomy, the retry policy, the cache, the bulk path, the tests — takes the rest of the day. This guide is that rest of the day, written to be framework-agnostic: the decisions here apply whether you are in Laravel, Django, Spring or a Lambda.
The shape of the integration
Strip away the language and framework and every GST verification integration is the same five stages. Getting them in the right order is most of the design work:
- Normalise the input — trim, uppercase, strip spaces and hyphens.
- Validate the format and check digit offline. Reject failures without a call.
- Check the cache. Return a stored record if it is fresh enough for this decision.
- Call the endpoint with the key, a timeout and a bounded retry policy.
- Persist the result with a timestamp, and store what you verified, not just that you did.
Teams that skip stages two and three end up paying for lookups on obvious typos and re-verifying the same vendor forty times a day. Teams that skip stage five discover during an audit that they can prove a check happened but not what it returned.
Authentication and the API key
Authentication is a single header. The key identifies your account and meters your usage, so treat it as a credential rather than a configuration value.
async function verifyGSTIN(gstin) {
const response = await fetch(
`https://gstinapi.com/api/get-taxpayer-info/${gstin}`,
{ headers: { 'x-api-key': 'YOUR_API_KEY' } }
);
return response.json();
}
const result = await verifyGSTIN('27AAAPL1234C1ZV');
console.log(result.taxpayer_data.name, result.taxpayer_data.status);
function verifyGSTIN(string $gstin): array
{
$curl = curl_init("https://gstinapi.com/api/get-taxpayer-info/{$gstin}");
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: YOUR_API_KEY'],
]);
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response, true);
}
$result = verifyGSTIN('27AAAPL1234C1ZV');
echo $result['taxpayer_data']['name'];
import requests
def verify_gstin(gstin: str) -> dict:
url = f"https://gstinapi.com/api/get-taxpayer-info/{gstin}"
headers = {"x-api-key": "YOUR_API_KEY"}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
result = verify_gstin("27AAAPL1234C1ZV")
print(result["taxpayer_data"]["name"], result["taxpayer_data"]["status"])
Three rules that prevent the expensive mistakes:
- Read it from the environment or a secret manager. Not a constant, not a config file in the repository, not a comment in a Postman collection you share with the team.
- Never ship it to a client. A key in a mobile binary or a browser bundle is public — extractable in minutes and billed to you. Browser and app lookups must go through your own backend, which holds the key and applies your own per-user limits.
- Rotate on a schedule and on suspicion. Rotation should be a configuration change you have practised, not an incident you improvise through.
The endpoint and the response
One GET request with the GSTIN in the path returns the taxpayer record. The fields that matter for almost every workflow:
| Field | What it tells you | Changes? |
|---|---|---|
| Legal name | Registered entity name — match against your master data | Rarely |
| Trade name | Operating name, often differs from legal name | Occasionally |
| Status | Active, cancelled or suspended — the gating field | Yes, and it matters |
| Registration date | When registration took effect | No |
| Constitution | Company, LLP, proprietorship and so on | Rarely |
| Jurisdiction | State and centre offices for the registration | Rarely |
| Filing history | Whether returns are being filed and how recently | Monthly |
The exact field names and types are in the API documentation, and how to verify a GST number using an API walks a full response field by field. Two response behaviours worth designing for now rather than discovering later: optional fields are genuinely optional, so a cancelled registration may carry a cancellation date that an active one does not; and status is the field your business logic should gate on, not the mere presence of a record. A cancelled GSTIN returns a perfectly valid response — it is just one you should usually refuse to transact against. The nuance is in what suspended status actually means.
Validate offline before you spend a call
A GSTIN is fifteen characters with fixed structure and a modulus-36 check digit. That means a typo is detectable locally, in microseconds, for nothing — and in real forms a meaningful share of submitted numbers are typos.
Put the check in two places: at the input boundary for immediate user feedback, and immediately before the network call as a guard. The algorithm is worked through with a full example in the GSTIN check digit algorithm, with ready implementations for Python and Node and TypeScript, and the correct regular expression — along with the two errors nearly every copy-pasted one contains — in the GSTIN regex explained.
Error handling that survives production
The defining decision in this integration is the error taxonomy, because getting it wrong produces failures that are both expensive and silent.
| Class | Examples | Retry? | What to do |
|---|---|---|---|
| Permanent — input | Malformed GSTIN, bad checksum, not found | Never | Surface to the user, record the outcome |
| Permanent — account | Invalid key, credits exhausted | Never | Alert an operator; this is not a user error |
| Transient — throttle | 429 rate limited | Yes, with backoff | Honour any retry hint; slow the whole worker |
| Transient — upstream | 5xx, gateway timeout | Yes, bounded | Backoff with jitter, cap attempts, then queue |
| Transient — network | Connection reset, DNS failure | Yes, bounded | Same as upstream; log for pattern detection |
The failure mode to design against is retrying permanent errors. A nightly job that re-attempts three thousand non-existent GSTINs with three retries each spends nine thousand calls to learn nothing, every night, until someone reads the invoice. Mark permanent failures as resolved and stop asking. The specific codes you will encounter are catalogued in the GST API error codes guide.
Retries, timeouts and idempotency
Set an explicit timeout. Most HTTP clients default to something unreasonable — sixty seconds, or none at all — and a request with no timeout is a worker that never comes back. A few seconds is generous for a lookup that normally returns in well under a second.
Retry with exponential backoff and jitter, capped at two or three attempts. Jitter matters more than it appears: without it, a batch that hits a rate limit retries in lockstep and hits it again, converting one throttle into a sustained one. Verification lookups are reads, so they are naturally idempotent — retrying is safe, which is exactly why bounding it is your responsibility rather than the protocol's.
For anything user-facing, decide what happens when all retries fail. Blocking a signup because a third-party API is briefly unavailable is usually the wrong trade; recording the GSTIN as pending and verifying asynchronously is usually the right one. Where uptime characteristics matter to that decision, we published measurements in uptime and latency benchmarks.
Caching: what to store and for how long
A single blanket TTL is wrong in both directions — too short for fields that never change, too long for the one field your decision depends on. Cache by field lifetime instead:
- Effectively permanent: legal name, registration date, constitution, jurisdiction, state code. Cache indefinitely and refresh opportunistically.
- Changes and matters: registration status. A day is reasonable for routine workflows; verify fresh for a large payment or a new supplier relationship.
- Changes monthly: return filing history. Align refresh with your own reconciliation cycle rather than checking it continuously.
Store the full record with the timestamp of retrieval, and let the caller decide what staleness it can tolerate rather than baking one answer into the cache layer. That also gives you the audit trail: being able to show what you knew and when you knew it is what makes a verification defensible later. Note that stored GSTIN data may be personal data depending on the entity type — retention and handling are covered in storing GSTIN data under the DPDP Act.
Going from one lookup to thousands
The single-lookup integration does not scale by being called in a loop. Four changes turn it into something that can process a supplier master:
- Bound concurrency with a worker pool rather than firing every request at once. Unbounded parallelism trips rate limits immediately and turns a fast job into a slow one.
- Make it resumable. Persist each result as it arrives and track progress. Every long batch eventually dies at seventy percent, and restarting from zero is both slow and billable.
- Deduplicate the input. Supplier masters contain the same GSTIN many times over. Deduplicate before dispatch, not after.
- Back off globally, not per request. When one worker is throttled, all of them should slow down — otherwise the pool keeps the limit saturated.
The throughput numbers and pool sizing are in bulk GSTIN verification throughput, and the CSV-driven version of this workflow is in bulk GST verification by CSV upload. For an ongoing supplier book, a periodic re-check beats an annual sweep — daily vendor monitoring covers that pattern.
What to test before you ship
Do not call the live API from your test suite. It is slow, it costs money, it fails when the network does, and it makes your CI depend on a third party. Record real responses once and replay them as fixtures.
The cases worth covering:
- An active registration — the happy path, asserting your parser reads every field you depend on.
- A cancelled registration — proving your business logic actually gates on status.
- A well-formed GSTIN that does not exist — the not-found path.
- A malformed GSTIN — asserting it is rejected offline and never reaches the network.
- A 429 — asserting backoff engages and the attempt cap holds.
- A timeout — asserting the worker recovers rather than hanging.
- A response missing an optional field — asserting you do not crash on a null.
For structurally valid inputs to test validators against without spending calls, generate them from the checksum algorithm or take them from test GSTIN numbers for testing.
Pre-production checklist
- API key read from a secret store, absent from source control and from any client bundle.
- Offline format and checksum validation ahead of every call.
- Explicit timeout set on the HTTP client.
- Permanent and transient errors handled separately, with retries only on the latter.
- Exponential backoff with jitter and a hard attempt cap.
- Results cached with a retrieval timestamp and a field-appropriate freshness policy.
- Bulk paths bounded, deduplicated and resumable.
- Usage alerting set below your expected ceiling.
- Test suite running against recorded fixtures, not the live API.
- Retention policy decided for stored taxpayer data.
With that in place the integration is done, and the remaining work is stack-specific. Starting points exist for Python, Node.js, Laravel, Java, PHP, .NET, Go and Rails, plus no-code routes via Zapier, Google Sheets and Power Automate. If you have not yet decided which access route you need at all, start with GST API for developers.
Frequently asked questions
Frequently asked questions
A note on accuracy. GST rules change often. This article reflects our understanding as of 15 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 developer integration guides
Browse every guide in the GST API blog.