The GST API Python package

gstin-toolkit is the official Python client for GSTIN API. It validates any Indian GST number offline — format, modulus-36 check digit, state, embedded PAN — and verifies it against the live government register when you give it a key.

pip install gstin-toolkit
View on PyPI Source on GitHub MIT · Python 3.9+ · zero dependencies

Both layers in ten lines

from gstin_api import is_valid_gstin, parse_gstin, GstinApiClient

is_valid_gstin("27AAACR5055K1Z7")     # True — format + check digit, offline
parse_gstin("27AAACR5055K1Z7").state  # 'Maharashtra'

# Reads GSTINAPI_API_KEY from the environment. One credit per lookup.
taxpayer = GstinApiClient().lookup("27AAACR5055K1Z7")

taxpayer.legal_name                   # 'RELIANCE INDUSTRIES LIMITED'
taxpayer.status                       # 'Active' — what a checksum cannot tell you
# None instead of an object means no registration exists. That is not billed.

What it exports

Offline — no key, no network, no quota

Export What it does
is_valid_gstin(value) True when the string is a well-formed GSTIN and its check digit matches.
gstin_rejection_reason(value) Why it failed, phrased for a form error — or None when it passed.
normalize_gstin(value) Trims, strips spaces and upper-cases, so pasted input stops being a support ticket.
parse_gstin(value) State, embedded PAN, PAN holder type, entity code and check digit as a typed dataclass.
explain_gstin(value) The same breakdown as human-readable rows — what the CLI prints.
state_for_code(code) The state behind the first two digits, including whether it charges SGST or UTGST.
build_gstin(...) Constructs a structurally valid GSTIN — for fixtures, not for pretending a business exists.

Online — one credit per resolved lookup

Export What it does
client.lookup(gstin) The register record, or None when nothing is registered against that number.
client.verify(gstin) Never raises for a bad number or a missing registration — puts the outcome in a message field.
client.verify_many(list) The same, across a list, at a paced rate.
Exceptions are typed: InvalidGstinError, AuthenticationError, InsufficientCreditsError, RateLimitError, ServiceError and TransportError, so an except block can tell a typo apart from an outage.

The full reference, including every field on the returned taxpayer dataclass, is in the package README and in the API documentation. Django, Flask and Pydantic recipes are in validating a GSTIN in Python.

Frequently asked questions

The official package is gstin-toolkit. Install it with pip install gstin-toolkit and import it as gstin_api. It validates GSTIN format and the modulus-36 check digit offline with no API key, and calls the GSTIN API service for live taxpayer details when you supply one.
The distribution name gstin-api was already claimed on PyPI when the library was released, so the package is distributed as gstin-toolkit. The module inside it kept the name gstin_api. Run pip install gstin-toolkit, then write from gstin_api import is_valid_gstin. Importing gstin_toolkit raises ModuleNotFoundError.
Yes. is_valid_gstin, gstin_rejection_reason, normalize_gstin, parse_gstin and the state helpers all run locally with no network call, no key and no quota. Only GstinApiClient reaches the register, and only those calls cost a credit.
It ships a py.typed marker, so mypy and Pyright read its annotations instead of treating it as untyped. It supports Python 3.9 and above and has zero runtime dependencies.
Yes — the offline validators are plain functions with no framework coupling, so they drop into a Django validator, a Flask request handler or a Pydantic field validator unchanged. The Python guide on the blog has working snippets for each.

Also available for Node.js

npm install @dlminds/gstin-api — the same API surface, tested against the same corpus, so the two cannot disagree about a number.