Explainer 8 min read

SGST vs UTGST: Which One Applies, and the Delhi Trap

Why some union territories charge UTGST and three charge SGST instead, the full code-by-code list, and how to get it right in a tax engine.

Written and reviewed by the GSTIN API team Last reviewed

On an intra-state supply the tax splits into two halves. The central half is always CGST. The local half is SGST where the region has its own legislature, and UTGST where it does not. That is the whole rule, and it is not the rule most tax engines implement.

Most implement "union territory means UTGST", which is wrong for three of them. This article gives the correct test, the complete code-by-code list, and the reason a boolean flag will never get you there.

"does it have a legislature?"', 'Delhi (07), Puducherry (34) and Jammu and Kashmir (01) are union territories that levy SGST, because each has a legislature.', 'UTGST applies in Chandigarh (04), Dadra and Nagar Haveli and Daman and Diu (26), Lakshadweep (31), Andaman and Nicobar (35) and Ladakh (38).', 'The rate never changes. 18% is 9% + 9% whether the second half is SGST or UTGST — only the head and the ledger differ.', 'The reliable implementation is a lookup table keyed by the two-digit state code, not an is_union_territory flag.', ]" />

The rule in one sentence

When the place of supply falls in the same state or union territory as the supplier, the supply is intra-state and two levies attach to it simultaneously. CGST is levied by the Union under the CGST Act, 2017 on every such supply, everywhere in India, without exception. The other half depends on who has the power to tax locally.

A state has a legislature, so it has its own SGST Act, and it levies SGST. A union territory without a legislature has no state government to pass such an Act, so the UTGST Act, 2017 supplies the missing half and the levy is called UTGST — Union Territory Goods and Services Tax. Same rate, same base, same line on the invoice, different statute and different collecting authority.

If the place of supply is in a different state or union territory from the supplier, none of this matters: the supply is inter-state, the Centre levies IGST alone, and there is no local half to label. The general shape of that choice is covered in CGST, SGST and IGST compared, and the determination itself sits in the place of supply rules. This article is only about the second half of the intra-state case.

The Delhi trap

Here is where systems break. Delhi, Puducherry and Jammu and Kashmir are union territories, and all three levy SGST, not UTGST — because each has a legislature of its own and therefore its own SGST Act.

Delhi is the expensive one, because Delhi is where the invoices are. A tax engine that carries an is_union_territory boolean and branches on it will label every intra-Delhi supply as UTGST, and it will do so silently and consistently, on every invoice, until somebody downstream notices. Puducherry and Jammu and Kashmir fail the same way for the same reason; they are simply lower volume.

The correct test is not a property of the territory's constitutional category. It is whether that particular territory has a legislature, which is a fact about nine specific jurisdictions and cannot be derived from anything else in the record. In practice that means a hardcoded list — and a list is fine. It changes only when Parliament reorganises a territory, which has happened twice since GST began and both times with advance notice.

Every code, and what it levies

All 41 codes in the published table, with the local half each one attracts on an intra-state supply. The first two digits of any GSTIN carry this code, so you can read the answer straight off the supplier's number — see the GSTIN format for the rest of the fifteen characters, or the GST state code list for the jurisdictional detail behind each row.

Code Name Kind Local half Note
01Jammu and KashmirUnion territorySGSTHas a legislature. Union territory since 31 Oct 2019; kept its state-era code
02Himachal PradeshStateSGST
03PunjabStateSGST
04ChandigarhUnion territoryUTGSTNo legislature
05UttarakhandStateSGST
06HaryanaStateSGST
07DelhiUnion territorySGSTHas a legislature — the classic misclassification
08RajasthanStateSGST
09Uttar PradeshStateSGST
10BiharStateSGST
11SikkimStateSGST
12Arunachal PradeshStateSGST
13NagalandStateSGST
14ManipurStateSGST
15MizoramStateSGST
16TripuraStateSGST
17MeghalayaStateSGST
18AssamStateSGST
19West BengalStateSGST
20JharkhandStateSGST
21OdishaStateSGST
22ChhattisgarhStateSGST
23Madhya PradeshStateSGST
24GujaratStateSGST
25Daman and DiuUnion territoryUTGSTLegacy — merged into 26 on 26 Jan 2020, no longer issued
26Dadra and Nagar Haveli and Daman and DiuUnion territoryUTGSTNo legislature. Absorbed 25
27MaharashtraStateSGST
28Andhra Pradesh (before bifurcation)StateSGSTLegacy — replaced by 36 and 37, no longer issued
29KarnatakaStateSGST
30GoaStateSGST
31LakshadweepUnion territoryUTGSTNo legislature
32KeralaStateSGST
33Tamil NaduStateSGST
34PuducherryUnion territorySGSTHas a legislature
35Andaman and Nicobar IslandsUnion territoryUTGSTNo legislature
36TelanganaStateSGST
37Andhra PradeshStateSGSTThe post-bifurcation code
38LadakhUnion territoryUTGSTNo legislature. Separated from 01 in 2019
96Other CountrySpecial—Not a place. No intra-state tax applies
97Other TerritorySpecial—Not a place. No intra-state tax applies
99Centre JurisdictionSpecial—Not a place. No intra-state tax applies
The local half of an intra-state supply, by GST state code. Six codes levy UTGST; three union territories levy SGST.

Two things worth pulling out of that table. First, six codes levy UTGST and one of them is legacy, so a live UTGST engine deals with five active territories — a small enough set that there is no excuse for getting it wrong. Second, 96, 97 and 99 are not geographic jurisdictions and should never be handed to a "which local half?" branch at all. Treat them as a separate kind and let the caller decide what to do, rather than defaulting them to SGST because they are not on the UTGST list.

On the invoice and in the return

A tax invoice for an intra-state or intra-territory supply shows the two halves as separate line amounts, each with its own rate and its own value: CGST first, then either SGST or UTGST. A single consolidated "GST" line is not a compliant tax invoice, and the invoice format rules set out the rest of the required particulars.

Getting the label wrong on a printed invoice is a presentation defect. It is not free — a recipient whose own accounting system expects SGST from a Delhi supplier will raise a query, and somebody will spend an afternoon on it — but it is fixable in isolation.

The return is the serious case. Once the amounts are filed, they sit under the wrong head in the ledgers, and both parties inherit the problem: your liability is reported against a levy you did not incur, and the recipient's credit lands somewhere their own set-off logic did not expect. Correcting it means amending the filed data rather than reprinting a document. The cheapest place to fix a head is before it is filed, and the cheapest way to do that is to stop deriving it by hand.

Input tax credit works the same way

For credit purposes UTGST behaves exactly as SGST does. Credit of UTGST is set off against UTGST liability first and then against IGST, and — as with SGST — it can never be used against CGST. The bar is structural: the central half and the local half belong to different authorities, and letting one pay the other would move revenue between them with nothing to settle it.

The full sequence, including the order in which IGST credit must be exhausted first, is in the input tax credit rules. Nothing in it changes because the local half is called UTGST rather than SGST. If your set-off logic already handles SGST correctly, it handles UTGST correctly, provided the credit was recorded under the right head in the first place — which brings the problem back to classification.

Getting it right in code

Do not store an is_union_territory boolean and branch on it. It is the right answer to the wrong question, and it fails on exactly the three highest-volume territories. Store a lookup table keyed by the two-digit state code and read the levy straight out of it.

Our libraries ship that table. Both are MIT-licensed and dependency-free, on PyPI and npm:

from gstin_api import state_for_code, UTGST_CODES

state_for_code("04").intra_state_tax   # 'UTGST'  -- Chandigarh
state_for_code("07").intra_state_tax   # 'SGST'   -- Delhi, a union territory
state_for_code("27").intra_state_tax   # 'SGST'   -- Maharashtra

state_for_code("07").kind              # 'union_territory'
state_for_code("99").kind              # 'special'  -- not a place
state_for_code("25").legacy            # True       -- still parses, never issued

# The first two digits of a GSTIN are the state code.
supplier = "07AABCU9603R1ZP"
state_for_code(supplier[:2]).intra_state_tax   # 'SGST'

sorted(UTGST_CODES)   # ['04', '25', '26', '31', '35', '38']

The Node and TypeScript package exposes the same table:

import { stateForCode, isUtgstState, UTGST_CODES } from '@dlminds/gstin-api';

stateForCode('04')?.intraStateTax;   // 'UTGST'
stateForCode('07')?.intraStateTax;   // 'SGST'

isUtgstState('04');   // true
isUtgstState('07');   // false  <- the Delhi trap, handled

const gstin = '07AABCU9603R1ZP';
const localHalf = stateForCode(gstin.slice(0, 2))?.intraStateTax;   // 'SGST'

Worked through: a supplier holding GSTIN 07AABCU9603R1ZP makes a supply where the place of supply is also in Delhi. Code 07, intra-territory, so the halves are CGST and SGST — despite Delhi being a union territory. At a notional 18%, that is 9% CGST and 9% SGST; the GST calculator does the arithmetic, and how to calculate GST covers the inclusive-price case. Rates move with GST Council notifications, so confirm the live rate for your own HSN before invoicing.

Both packages also expose allStates() for the full table and a search helper for name-to-code lookups, which is what the state code finder runs on. If you want the levy resolved server-side alongside a live registry check, the API documentation covers the endpoints, and GST number search answers a single number in the browser. The fifteenth character's arithmetic, if you are validating as well as classifying, is in the GSTIN checksum algorithm.

Two codes that changed

Two codes are no longer issued but still appear in historic invoices, archived returns and vendor master data. A parser that rejects them as malformed will fail on real records.

Code Was What happened Now
25Daman and DiuMerged with Dadra and Nagar Haveli on 26 January 2020 into a single union territoryNew registrations carry 26
28Andhra Pradesh, before bifurcationTelangana was given 36; the remainder of Andhra Pradesh moved to 37Neither state issues 28
Retired codes. Recognise them on read; never assign them on write.

Both changes are reorganisations of territory, not of tax policy, and both landed with enough notice to plan for. The lesson for a tax engine is the same one the Delhi trap teaches: the mapping from a code to a levy is data, it changes on its own schedule, and it belongs in a table you can update rather than in a condition you have to rewrite.

Frequently asked questions

They are the same half of the same tax, levied by different authorities under different statutes. On an intra-state or intra-territory supply the notified rate splits into a central half, always CGST, and a local half. Where the region has its own legislature that local half is SGST, levied under that region's own SGST Act. Where it does not, the local half is UTGST, levied under the UTGST Act, 2017. The rate, the base and the position on the invoice are identical; only the head and the collecting authority differ.
SGST. Delhi is a union territory, but it has its own legislature and its own SGST Act, so an intra-Delhi supply attracts CGST plus SGST. Puducherry and Jammu and Kashmir are in the same position. This is the single most common error in tax engines, because a system that branches on "is this a union territory?" will map all three to UTGST and be wrong every time.
The union territories without a legislature of their own: Chandigarh (state code 04), Dadra and Nagar Haveli and Daman and Diu (26), Lakshadweep (31), the Andaman and Nicobar Islands (35) and Ladakh (38). The legacy code 25, Daman and Diu, also sat in this group before the 2020 merger and still appears in historic records.
No. The split changes the label and the ledger, never the amount. A supply notified at 18% carries 9% CGST plus 9% of the local half whether that half is SGST or UTGST. A customer in Chandigarh and a customer in Delhi pay exactly the same total on the same goods at the same rate.
No. UTGST behaves exactly like SGST for credit purposes: it can be set off against UTGST liability first and then against IGST, and it can never be used against CGST. The bar is structural, because the two levies belong to different authorities, and there is no reconciliation route around it.
It is no longer issued. Daman and Diu merged with Dadra and Nagar Haveli on 26 January 2020 into a single union territory carrying code 26, and no new GSTIN begins with 25. It still appears in historic invoices, archived returns and vendor master data, so parsers must keep recognising it rather than rejecting it as malformed.

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 tool

Build it into your product

One REST call, JSON back. Get an API key and 20 free verification credits in under a minute.

Start free