Billing and receivables / A4
GST tax invoice HTML template for India
An Indian tax invoice with GSTIN for both parties, HSN codes per line, and tax split into CGST and SGST or charged as IGST depending on the place of supply.
When this document is the right one
A registered supplier in India issues an invoice to another registered person. The document has prescribed particulars and a prescribed set of copies, and getting the tax split wrong is not a formatting error, it changes which government is paid.
Why each part is there
The fields are visible in the markup. What is not visible is why they are present, which is the part that gets removed first when someone adapts a template for their own use.
- The place of supply, stated explicitly. It is what decides whether the tax is CGST plus SGST or IGST, and the two are never both shown.
- GSTIN for supplier and recipient, with the state and its numeric code, because the first two digits of a GSTIN are the state.
- An HSN or SAC code on every line, at the digit length the supplier's turnover requires.
- A copy marking. The original is for the recipient, the duplicate for the transporter and the triplicate for the supplier, and only one of them is the original.
- The amount in words as well as figures, which is conventional to the point of being expected.
- A signature block, physical or digital, on behalf of the supplier.
The template
A complete file. Doctype, stylesheet, body: paste it into a renderer unchanged and it produces a finished A4 page. Replace the sample data and the styling holds.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tax invoice KA/2026/1187</title>
<style>
@page { size: A4; margin: 12mm; }
* { box-sizing: border-box; }
body { margin: 0; font: 9pt/1.4 Arial, sans-serif; color: #000; }
.sheet { border: 1px solid #000; }
.title { text-align: center; padding: 2mm; border-bottom: 1px solid #000;
font-weight: 700; letter-spacing: 0.06em; }
.title small { display: block; font-weight: 400; font-size: 7.5pt; letter-spacing: 0; }
.top { display: grid; grid-template-columns: 1fr 1fr; }
.top > div { padding: 3mm; }
.top > div:first-child { border-right: 1px solid #000; }
.kv { display: grid; grid-template-columns: 34mm 1fr; gap: 0.8mm 2mm; font-size: 8.5pt; }
.kv span:first-child { color: #333; }
address { font-style: normal; }
.addr-row { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid #000; }
.addr-row > div { padding: 3mm; }
.addr-row > div:first-child { border-right: 1px solid #000; }
h2 { margin: 0 0 1.5mm; font-size: 8pt; text-transform: uppercase; }
table { width: 100%; border-collapse: collapse; border-top: 1px solid #000; }
thead { display: table-header-group; }
th, td { border: 1px solid #000; padding: 1.6mm; font-size: 8pt; }
th { background: #eee; text-align: left; }
tr { break-inside: avoid; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
/* CGST and SGST for a supply inside the state, IGST for one across state
lines. Never both. The place of supply above decides which applies. */
.tax-split { break-inside: avoid; }
.foot { display: grid; grid-template-columns: 1fr 70mm; border-top: 1px solid #000;
break-inside: avoid; }
.foot > div { padding: 3mm; }
.foot > div:first-child { border-right: 1px solid #000; }
.words { font-size: 8.5pt; }
.sign { text-align: right; padding-top: 16mm; font-size: 8.5pt; }
</style>
</head>
<body>
<div class="sheet">
<div class="title">TAX INVOICE<small>Original for recipient</small></div>
<div class="top">
<div>
<strong>Anantha Instruments Pvt Ltd</strong>
<address>44/2 Hosur Road, Bommanahalli<br>Bengaluru 560068, Karnataka</address>
<div class="kv" style="margin-top:2mm">
<span>GSTIN</span><span>29AAFCA4471J1ZP</span>
<span>State</span><span>Karnataka, code 29</span>
</div>
</div>
<div>
<div class="kv">
<span>Invoice number</span><span>KA/2026/1187</span>
<span>Invoice date</span><span>14 May 2026</span>
<span>Place of supply</span><span>Karnataka (29)</span>
<span>Reverse charge</span><span>No</span>
<span>Transport doc</span><span>LR 88213, 12 May 2026</span>
</div>
</div>
</div>
<div class="addr-row">
<div>
<h2>Bill to</h2>
<address><strong>Vidyut Controls</strong><br>
12 Industrial Layout, Peenya<br>Bengaluru 560058, Karnataka</address>
<div class="kv" style="margin-top:2mm"><span>GSTIN</span><span>29AACCV1188K1ZR</span></div>
</div>
<div>
<h2>Ship to</h2>
<address><strong>Vidyut Controls, Unit 2</strong><br>
Plot 61, KIADB Phase 3<br>Bengaluru 560058, Karnataka</address>
</div>
</div>
<table>
<thead>
<tr>
<th>#</th><th>Description</th><th>HSN</th>
<th class="num">Qty</th><th class="num">Rate</th>
<th class="num">Taxable</th>
<th class="num">CGST 9%</th><th class="num">SGST 9%</th>
<th class="num">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Digital pressure transmitter DPT-200</td><td>9026</td>
<td class="num">10</td><td class="num">7,400.00</td>
<td class="num">74,000.00</td>
<td class="num">6,660.00</td><td class="num">6,660.00</td>
<td class="num">87,320.00</td>
</tr>
<tr>
<td>2</td><td>Mounting bracket, stainless</td><td>7326</td>
<td class="num">10</td><td class="num">480.00</td>
<td class="num">4,800.00</td>
<td class="num">432.00</td><td class="num">432.00</td>
<td class="num">5,664.00</td>
</tr>
<tr class="tax-split">
<td colspan="5"><strong>Total</strong></td>
<td class="num"><strong>78,800.00</strong></td>
<td class="num"><strong>7,092.00</strong></td>
<td class="num"><strong>7,092.00</strong></td>
<td class="num"><strong>92,984.00</strong></td>
</tr>
</tbody>
</table>
<div class="foot">
<div class="words">
<strong>Amount in words</strong><br>
Rupees Ninety Two Thousand Nine Hundred Eighty Four only.
<p style="margin:3mm 0 0">Certified that the particulars given above are true
and correct, and that the amount indicated represents the price actually charged.</p>
</div>
<div class="sign">
For Anantha Instruments Pvt Ltd
<div style="height:14mm"></div>
Authorised signatory
</div>
</div>
</div>
</body>
</html>The layout decision worth understanding
The whole document sits inside a single ruled box with internal dividers rather than using whitespace to separate sections. That is not a stylistic choice: this format is read alongside handwritten and pre-printed versions of the same document, and the ruled grid is what makes it recognisable as the same thing.
The mistake people make adapting it
Showing CGST, SGST and IGST columns all at once and leaving the ones that do not apply as zero. It looks thorough and it is wrong: the place of supply determines which apply, and showing all three suggests the system does not know which case it is in.
Rendering it
The page box is declared in the template's own CSS as A4, so the size travels with the markup rather than living in the code that calls the renderer. A4 is also one of the six named formats the API accepts, so it can be passed in the request options instead if that suits your setup better.
curl -X POST https://api.pdfpipe.xyz/v1/pdf \
-H "Authorization: Bearer $PDFPIPE_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<!doctype html>...",
"options": { "format": "A4" }
}' \
--output invoice-gst.pdfFrequently asked
Can I use this template commercially?
Yes. Copy it, change it, ship it. It is sample markup written to be taken, and the sample data in it is invented, so replace the names and the numbers before anyone sees it.
Why is the page size in the CSS rather than in the API call?
Because a indian gst tax invoice is a A4 document, and that is a property of the document rather than of the code that renders it. Declaring it in the page box means the size cannot be lost between the template and the call, which is the usual way a document ends up on the wrong paper.
Will it look the same in every renderer?
The layout will, because it uses ordinary CSS. The page break behaviour will not: break-inside and break-after are implemented differently by browser engines and by dedicated print engines, and some of the paged media specification is not implemented in browser renders at all. That difference is documented per property in the paged CSS reference.
Other templates
Documents from the same part of a business, and one from each of the other groups.
HTML invoice template with CSS
The standard commercial invoice: a demand for payment with line items, a tax figure, and terms that say when the money is due.
EU VAT invoice HTML template
A cross-border invoice inside the EU, with both parties' VAT identification numbers, tax broken out per rate, and a reverse charge statement.
Commercial invoice template for customs
The customs document that travels with an international shipment: what the goods are, what they are worth, where they were made, and under what terms they move.
Proforma invoice HTML template
A document shaped like an invoice that is deliberately not one: it commits nobody to pay and exists so the buyer can raise an order, open a credit, or clear an import.
Payment receipt HTML template
Proof that a payment was made: the amount, the payment reference, the method, and what it was for.
Quotation HTML template with CSS
A priced proposal with a validity date, a scope, optional items kept out of the headline total, and somewhere to sign.
Packing slip HTML template
The document that goes in the box: what was ordered, what was actually shipped, and no prices at all.
Every template
The full set, grouped by what part of a business produces the document.
A4 page size for PDF generation
A4 is the default page for business documents everywhere except North America, and the default this API uses when no format is given.
Paste the template into the playground and get the PDF back. No signup, no key.