The e-invoice JSON schema is the standard structure (form GST INV-01) in which invoice data is sent to the Invoice Registration Portal. It groups data into sections such as transaction details, document details, seller, buyer, item list and value totals, plus optional dispatch, ship-to, payment, reference, export and e-way bill details. Each field has a defined name, format and validation.
Every e-invoice is ultimately a structured data file. The Invoice Registration Portal (IRP) does not read your PDF or your template; it reads a JSON document built to a standard schema notified as form GST INV-01. This guide explains that schema in plain terms — what each section holds, which fields are mandatory, and how a real invoice maps into it — so that rejection messages make sense and your master data is set up correctly.
What is the e-invoice JSON schema?
JSON (JavaScript Object Notation) is a simple text format of named fields and values. The e-invoice schema is the agreed list of those names, the order they are grouped in, the data type and length of each, and which ones are mandatory. It was designed so that any software — a small billing app or a large ERP — produces data the IRP can validate in the same way.
The schema is published on the e-invoice portal along with validation rules and sample files. If you are new to e-invoicing, read what is e-invoicing first; for how the file is submitted, see how to generate IRN.
What are the main sections of the e-invoice JSON?
The schema groups data into sections. The short names below are the keys used in the JSON.
| Section (key) | What it holds | Mandatory? |
|---|---|---|
| Version | Schema version number | Yes |
| TranDtls | Tax scheme, supply type, reverse charge flag | Yes |
| DocDtls | Document type, number, date | Yes |
| SellerDtls | Supplier GSTIN, legal name, address, PIN, state | Yes |
| BuyerDtls | Buyer GSTIN, name, address, PIN, state, place of supply | Yes |
| DispDtls | Dispatch-from address if different from seller | Conditional |
| ShipDtls | Ship-to address if different from buyer | Conditional |
| ItemList | One entry per line item | Yes |
| ValDtls | Invoice-level totals | Yes |
| PayDtls | Payment terms and bank details | Optional |
| RefDtls | Preceding invoice reference, remarks, period | Conditional |
| AddlDocDtls | Supporting document URLs or references | Optional |
| ExpDtls | Export details: port, shipping bill, currency, country | Conditional |
| EwbDtls | Transporter and vehicle details for an e-way bill | Optional |
Transaction and document details
TranDtls identifies the kind of supply. The tax scheme is "GST". The supply type uses codes:
| Code | Meaning |
|---|---|
| B2B | Supply to a registered person |
| SEZWP | Supply to SEZ with payment of tax |
| SEZWOP | Supply to SEZ without payment of tax |
| EXPWP | Export with payment of tax |
| EXPWOP | Export without payment of tax |
| DEXP | Deemed export |
Flags in this section also record whether reverse charge applies and whether the supply is through an e-commerce operator.
DocDtls holds the document type — INV (invoice), CRN (credit note) or DBN (debit note) — the document number and the document date in DD/MM/YYYY format. The document number follows the GST rule of up to 16 characters, using letters, digits and the "/" and "-" characters; see GST invoice number series rules.
Seller and buyer details
Both sections carry GSTIN, legal name, trade name (optional), address lines, location, PIN code and state code. The IRP checks that:
- Each GSTIN is valid and active.
- The PIN code belongs to the state code given.
- The state code matches the first two digits of the GSTIN for registered parties.
BuyerDtls also includes Pos, the place of supply state code. Pos decides whether CGST+SGST or IGST should appear, and the IRP checks that tax heads match. For exports, the buyer GSTIN is "URP", and the state code and Pos use the code meant for "other country".
Item list: where most errors live
ItemList is an array — one object per line. Key fields include:
| Field | Meaning |
|---|---|
| SlNo | Line serial number |
| PrdDesc | Description |
| IsServc | "Y" for service, "N" for goods |
| HsnCd | HSN or SAC code |
| Qty, Unit | Quantity and unit code (e.g. NOS, KGS) |
| UnitPrice | Rate per unit |
| TotAmt | Quantity × unit price |
| Discount | Line discount |
| AssAmt | Taxable value (TotAmt − Discount) |
| GstRt | GST rate |
| IgstAmt / CgstAmt / SgstAmt | Tax amounts |
| CesAmt and related | Cess, if any |
| TotItemVal | Line total including tax |
| BchDtls | Batch number, expiry and warranty dates (optional) |
The IRP recalculates several of these values. If AssAmt does not equal TotAmt minus Discount, or tax amounts do not match rate × value within a small tolerance, the invoice is rejected. HSN codes must exist in the IRP's master; services must use SAC codes beginning with 99. See HSN code digits on invoice.
Value details
ValDtls carries invoice totals: AssVal (total taxable value), CgstVal, SgstVal, IgstVal, CesVal, any other charges, round-off and TotInvVal (total invoice value). These must equal the sum of the item lines, adjusted for invoice-level discount, other charges and round-off.
Worked example: mapping an invoice to JSON
A Pune electrical supplier bills a registered Pune factory (both in Maharashtra, state code 27):
| Item | HSN | Qty | Rate | Value |
|---|---|---|---|---|
| Copper wire coils | 854449 | 100 | ₹450 | ₹45,000 |
| Miniature circuit breakers | 853620 | 50 | ₹1,600 | ₹80,000 |
| Taxable value | ₹1,25,000 | |||
| CGST 9% | ₹11,250 | |||
| SGST 9% | ₹11,250 | |||
| Total | ₹1,47,500 |
A trimmed JSON for this invoice looks like:
{
"Version": "1.1",
"TranDtls": { "TaxSch": "GST", "SupTyp": "B2B" },
"DocDtls": { "Typ": "INV", "No": "PS/26-27/0921", "Dt": "14/10/2026" },
"SellerDtls": { "Gstin": "27AAAAA0000A1Z5", "LglNm": "Seller name", "Addr1": "Bhosari MIDC", "Loc": "Pune", "Pin": 411026, "Stcd": "27" },
"BuyerDtls": { "Gstin": "27BBBBB1111B1Z3", "LglNm": "Buyer name", "Pos": "27", "Addr1": "Chakan MIDC", "Loc": "Pune", "Pin": 410501, "Stcd": "27" },
"ItemList": [
{ "SlNo": "1", "IsServc": "N", "HsnCd": "854449", "Qty": 100, "Unit": "NOS", "UnitPrice": 450, "TotAmt": 45000, "AssAmt": 45000, "GstRt": 18, "CgstAmt": 4050, "SgstAmt": 4050, "TotItemVal": 53100 },
{ "SlNo": "2", "IsServc": "N", "HsnCd": "853620", "Qty": 50, "Unit": "NOS", "UnitPrice": 1600, "TotAmt": 80000, "AssAmt": 80000, "GstRt": 18, "CgstAmt": 7200, "SgstAmt": 7200, "TotItemVal": 94400 }
],
"ValDtls": { "AssVal": 125000, "CgstVal": 11250, "SgstVal": 11250, "IgstVal": 0, "TotInvVal": 147500 }
}
Check the arithmetic the way the IRP does: line 1 tax is ₹45,000 × 9% = ₹4,050 each for CGST and SGST, line total ₹53,100; line 2 tax is ₹80,000 × 9% = ₹7,200 each, line total ₹94,400. Totals: ₹1,25,000 taxable, ₹11,250 CGST, ₹11,250 SGST, ₹1,47,500 overall. GSTINs, names and HSN codes here are placeholders for illustration; a real file must use real values.
The rates shown follow the current GST structure for these items as an illustration — always confirm the rate for your exact HSN with the GST calculator or your adviser.
Conditional sections: when to fill them
- DispDtls — when goods leave from a warehouse or address other than the seller's principal place.
- ShipDtls — when goods are delivered to an address other than the buyer's billing address.
- RefDtls — for credit and debit notes, to reference the original invoice number and date.
- ExpDtls — for exports: port code, shipping bill details if known, foreign currency and country code.
- EwbDtls — when you want the IRP to generate an e-way bill too: transporter ID, mode, distance, vehicle number and type.
How should you test JSON before going live?
- Use the sandbox environment offered by the e-invoice system to submit test files without creating real IRNs.
- Test one plain B2B invoice, one inter-state invoice, one credit note with a preceding-invoice reference and, if relevant, one export and one SEZ invoice.
- Include a multi-line invoice with discounts and decimal rates to test rounding.
- Read every validation message and fix the source data, not the test file.
- Repeat after any software upgrade or schema version change.
How does the IRP respond to a valid JSON?
When a JSON passes validation, the IRP returns its own response rather than your file back. The sample response published on the e-invoice portal shows the main elements:
| Response field | What it is |
|---|---|
| AckNo | Acknowledgement number from the IRP |
| AckDt | Acknowledgement date and time |
| Irn | The 64-character Invoice Reference Number |
| SignedInvoice | The invoice data, digitally signed by the IRP |
| SignedQRCode | The signed data used to print the QR code |
Your software should store all of these against the invoice. The acknowledgement time matters for the 24-hour cancellation window, and the signed QR code is what you print on the invoice. The IRP's QR code procedure explains that the signed QR code is a JWT with three parts separated by dots — header, data and signature — which is why it can be verified offline.
Why your stored copy matters
If an IRN is later questioned, the signed invoice is the proof of what was registered. Keep it with the invoice PDF rather than relying on fetching it from the portal again later. Retrieval tools on the portals may only look back a limited period, so your own archive is the safe copy.
Schema version field
The Version field tells the IRP which schema structure your file follows. Use the version your IRP currently specifies in its published schema and API documentation; if your software sends an old version string, update the software rather than editing the field by hand.
Common mistakes with the e-invoice JSON
- Numbers sent as text where the schema expects numeric values, or vice versa.
- Totals not matching lines, usually because of rounding done only at invoice level.
- Wrong state code for the PIN code, especially for ship-to addresses.
- Using an outdated schema version in an old offline tool.
- Leaving RefDtls empty on credit notes, losing the link to the original invoice.
- Free-typing unit codes instead of using the standard unit list.
- Invoice numbers longer than 16 characters or with disallowed symbols.
For a broader list with fixes, see e-invoice common errors. Billing Software by Betterwork builds this JSON from the invoice and applies the same arithmetic checks before submission, so most schema errors are caught before they reach the IRP.
Key takeaways
- The e-invoice JSON (INV-01) has mandatory sections for transaction, document, seller, buyer, items and totals.
- Supply-type codes (B2B, SEZWP, SEZWOP, EXPWP, EXPWOP, DEXP) and document types (INV, CRN, DBN) drive validation.
- The IRP recalculates line and invoice values, so rounding and arithmetic must be consistent.
- Conditional sections cover dispatch, ship-to, references, exports and e-way bill data.
- Keep your software or offline tool on the latest schema version.
This guide is general information, not tax advice. Rules last checked on 20 October 2026; confirm with your tax professional for your situation.
