If your business turnover crossed ₹5 crore in any year since 2017-18, you’re legally obliged to e-invoice every B2B sale through GSTN’s Invoice Registration Portal (IRP). The threshold has crept down from ₹500 Cr in 2020 to ₹100 Cr, ₹50 Cr, ₹10 Cr, and finally ₹5 Cr by August 2023 — and a lot of mid-size Indian businesses got caught flat-footed.

The good news: the GSTN API contracts are stable, the sandbox is genuinely usable, and you can integrate this in 2-3 weeks from scratch if you know what you’re doing. The bad news: the GSTN docs are written like a government circular and almost every team gets stuck on one of four predictable issues. This guide is the playbook we wish we’d had on our first integration.

पहले Do you even need to e-invoice?

Check your aggregate turnover for any year since FY 2017-18. If it exceeded ₹5 crore in any of those years, you’re in scope. Verify at einvoice1.gst.gov.in/Others/EinvEnabled — type your GSTIN and the portal tells you yes/no.

In scope = e-invoice for:

  • B2B sales (any registered buyer)
  • Exports (including SEZ supplies, deemed exports)
  • Debit and credit notes for the above

Not in scope (yet, in 2026):

  • B2C sales (unless invoice value > ₹500 Cr — which is essentially nobody)
  • Banking, insurance, financial services
  • Passenger transport, multiplex screening
  • Government and goods transport agencies

रास्ता GSP / ASP vs direct API — pick your path

Two integration paths:

Path 1: Direct GSTN API. You implement the calls yourself against https://einvoice1.gst.gov.in/api (production) or https://einvoice1-trial.nic.in/api (sandbox). Free. Full control. Slower onboarding because you handle AES encryption, version updates, retry logic, error mapping.

Path 2: Via a GST Suvidha Provider (GSP) / Application Service Provider (ASP). Companies like Cygnet, ClearTax, IRIS, GSTHero, MasterGST wrap the direct API with a cleaner REST surface, handle the encryption quirks, often add a friendly dashboard. Costs ₹2-10/invoice depending on volume tier.

Our default for a developer team: go direct. The savings compound and you get full visibility into what’s happening. Use a GSP only when (a) you have no engineering team, or (b) you’re volume-low enough that the per-invoice cost is trivial and you’d rather pay than maintain.

सैंडबॉक्स Sandbox first — always

Register at einvoice1-trial.nic.in using your real GSTIN. Within a day or two you’ll get credentials by email:

  • Client ID — identifies your application
  • Client Secret — secret half of the credential pair
  • GSTIN — your own; identifies the seller
  • Username — you create this
  • Password — you create this

Store these in your secrets manager. Never commit them.

कूट The actual integration — step by step

Step 1. Authenticate (get an access token)

POST to /eivital/v1.04/auth. The catch: your username and password are AES-256 encrypted using a public key the sandbox provides separately. Headers include the Client ID and Client Secret in plaintext.

// Laravel pseudocode
$encryptedUser = $this->aesEncrypt($username, $appKey);
$encryptedPass = $this->aesEncrypt($password, $appKey);

$response = Http::withHeaders([
    'client_id'     => $clientId,
    'client_secret' => $clientSecret,
    'gstin'         => $gstin,
])->post('https://einvoice1-trial.nic.in/eivital/v1.04/auth', [
    'UserName' => $encryptedUser,
    'Password' => $encryptedPass,
    'AppKey'   => base64_encode(random_bytes(32)),
    'ForceRefreshAccessToken' => false,
]);

// Response gives you AuthToken and Sek (session encryption key)
$authToken = $response->json('Data.AuthToken');
$sek = $response->json('Data.Sek');

The token is valid for 6 hours. Cache it (Redis works). The Sek (Session Encryption Key) is used to encrypt payloads from here on.

Step 2. Build the invoice payload

Schema v1.1 is current in 2026. The payload structure:

{
  "Version": "1.1",
  "TranDtls": { "TaxSch": "GST", "SupTyp": "B2B" },
  "DocDtls": { "Typ": "INV", "No": "INV-2026-1042", "Dt": "18/05/2026" },
  "SellerDtls": {
    "Gstin": "29ABCDE1234F1Z5",
    "LglNm": "Antarix Technology Pvt Ltd",
    "Addr1": "Bengaluru",
    "Loc": "Bengaluru",
    "Pin": 560008,
    "Stcd": "29"
  },
  "BuyerDtls": {
    "Gstin": "29XYZAB5678C1Z3",
    "LglNm": "Buyer Company Pvt Ltd",
    "Addr1": "Mumbai",
    "Loc": "Mumbai",
    "Pin": 400001,
    "Stcd": "27",
    "Pos": "27"
  },
  "ItemList": [
    {
      "SlNo": "1",
      "PrdDesc": "Custom software development",
      "IsServc": "Y",
      "HsnCd": "998314",
      "Qty": 1,
      "Unit": "OTH",
      "UnitPrice": 850000,
      "TotAmt": 850000,
      "AssAmt": 850000,
      "GstRt": 18,
      "IgstAmt": 0,
      "CgstAmt": 76500,
      "SgstAmt": 76500,
      "TotItemVal": 1003000
    }
  ],
  "ValDtls": {
    "AssVal": 850000, "CgstVal": 76500, "SgstVal": 76500,
    "IgstVal": 0, "TotInvVal": 1003000
  }
}

Common payload mistakes:

  • Date format: DD/MM/YYYY not ISO. Trips everyone the first time.
  • Place of Supply (Pos): always the buyer’s state code, even if you’re in the same state.
  • State codes are 2-digit GSTIN-derived (29 = Karnataka, 27 = Maharashtra), not 3-letter ISO.
  • HSN code: 6-digit minimum if turnover > ₹5 Cr (8-digit for exports). The GSTN portal validates these.
  • Service vs Goods: IsServc: "Y" for services. Affects rounding rules.

Step 3. Encrypt the payload & submit

The payload is encrypted using the Sek from auth. POST to /eicore/v1.03/Invoice:

$encryptedPayload = $this->aesEncrypt(json_encode($invoiceData), $sek);

$response = Http::withHeaders([
    'client_id'     => $clientId,
    'client_secret' => $clientSecret,
    'gstin'         => $gstin,
    'AuthToken'     => $authToken,
])->post('https://einvoice1-trial.nic.in/eicore/v1.03/Invoice', [
    'Data' => $encryptedPayload,
]);

// Success response, decrypted using Sek, gives you:
$irn          = $decrypted['Irn'];           // 64-char hash
$ackNo        = $decrypted['AckNo'];         // 18-char ack number
$ackDt        = $decrypted['AckDt'];         // timestamp
$signedQRCode = $decrypted['SignedQRCode'];  // base64 string
$signedInvoice= $decrypted['SignedInvoice']; // signed by GSTN, optional to store

Step 4. Render IRN + QR on your invoice PDF

The legal invoice you give your buyer must show:

  • IRN: the 64-character hash printed visibly
  • QR code: render the SignedQRCode as a QR image (libraries: endroid/qr-code in PHP, qrcode in Node, qrcode in Python). When scanned, the QR validates against GSTN.
  • AckNo & AckDt: printed near the IRN

Step 5. Link e-Way Bill (if shipping goods)

If your invoice involves transporting goods worth > ₹50,000, you also need an e-Way Bill. Two options:

  • Include EwbDtls in the original invoice payload — GSTN generates both IRN and EWB in one call
  • Generate IRN first, then call /ewaybillapi/v1.03/ewayapi with the IRN to create EWB separately

गलतियाँ The four errors that derail most teams

1. AES encryption mismatch

GSTN uses AES-256 in ECB mode (yes, ECB — not CBC, not GCM). Padding is PKCS#7. Keys must be 32 bytes (not 24, not 16). Most cryptography libraries default to CBC; you have to explicitly request ECB. The first error symptom is “Invalid Auth Token” even when you’re sure the token is fresh — it’s actually the decryption of the response failing silently.

2. Duplicate IRN errors (2102)

If you accidentally submit the same invoice twice, GSTN returns error 2102 with the existing IRN. Don’t treat this as an error — treat it as “already done” and store the returned IRN. Always implement an idempotent onSubmitInvoice handler.

3. Sandbox version drift

GSTN updates API versions (v1.03 → v1.04) without strict deprecation. We’ve seen teams write against v1.03 schema and break six months later. Pin the API version in your code, set a calendar reminder every 6 months to review release notes at the einvoice1 documentation portal.

4. Time zone in timestamps

Everything is IST. If your server is UTC and you send a timestamp without conversion, GSTN rejects it for “future date” or “past date.” Always format dates with IST offset before sending.

वास्तुकला Production architecture — the outbox pattern

Don’t call the GSTN API synchronously from your invoice-creation endpoint. The API is occasionally slow (3-8s during business hours), occasionally down, and you don’t want your “Create Invoice” button to spinning forever or fail because GSTN had a hiccup.

Pattern we use:

1. User creates invoice → INSERT into invoices (status='draft', irn=null)
2. Job dispatched to einvoice_queue → fires GSTN API call
3. On success: UPDATE invoices SET irn=?, qr=?, status='issued'
4. On failure: store error, retry with exponential backoff (1m, 5m, 15m, 1h, 6h)
5. Cron sweeps stuck invoices > 24h old → alert admin
6. PDF generation reads invoice with IRN → renders official copy

Add a dashboard for ops showing GSTN API latency, success rate, error breakdown. We use Sentry for errors and a simple Laravel Telescope dashboard for queue health.

लागत What this costs to build & run

  • One-time integration: 60-120 engineering hours for a clean direct integration. ~₹90,000 - ₹1.8 lakh from a senior team.
  • GSTN API costs: Free for direct integration. ₹2-10/invoice via a GSP.
  • Ongoing maintenance: ~30-50 hours/year for schema updates and bug fixes. ₹40-70K/year.
  • Production credentials: Free, but requires a digital signature for the application.

सलाह Production rollout — final checklist

  1. Apply for production credentials at einvoice1.gst.gov.in — separate from sandbox, ~5 working day turnaround
  2. Move your encryption keys + credentials to your secrets manager — never in code
  3. Set up monitoring: GSTN API latency, IRN issuance success rate, queue depth
  4. Add a manual “retry IRN” button in your admin so ops can poke stuck invoices
  5. Build a daily reconciliation report: count of invoices issued vs IRNs received
  6. Document the IRN/QR fields on your PDF template — auditors will check
  7. Plan for the e-Way Bill flow if you ship physical goods
  8. Subscribe to GSTN’s release notes (mailing list) for upcoming schema changes

e-Invoice integration isn’t hard — it’s tedious, easy to get wrong, and almost everyone underestimates the encryption-quirks rabbit hole. Allocate three solid weeks, build the outbox pattern from day one, and your future self at year-end audits will thank you.

If you need help

We do GST API integration and custom ERPs end-to-end — including the e-Invoice + e-Way Bill flow, IRN reconciliation, PDF generation with QR, and ongoing support for GSTN schema updates. Free written quote within 24 hours. Tell us about your billing flow.

Karan Mehta leads platform engineering at Antarix Technology. 13 years building back-end systems — previously at Cred and AWS. He’s shipped GST e-Invoice integrations for nine Indian businesses across SaaS, e-commerce and manufacturing. Reach him on WhatsApp or info@antarixtech.com.