LedgereeStart free trial
Features

Every scenario we handle -- not a highlight reel.

GST-correct bookkeeping for a Shopify seller is genuinely fiddly: place of supply, B2B vs B2C, exports under an LUT, returns that shouldn’t net against sales, multiple GST rates in one day. This page is long on purpose -- it's the real list of what's actually built, including the edge cases, not a marketing summary of them.

01

GST place-of-supply & tax split

The core mechanic everything else builds on -- get this wrong and every downstream number is wrong too.

Ship-to state, not billing state

Place of supply for goods is the customer's ship-to state -- a gift order, a different delivery address on file, or a centrally-billed corporate purchase never changes this.

Per-fulfillment ship-from state

The seller-side state is resolved from the specific warehouse that actually fulfilled that order, not a single shop-wide constant -- a genuinely multi-warehouse seller gets the right split even when different orders ship from different states on the same day.

Same state -> CGST+SGST, different state -> IGST

Each half of the applicable rate for intra-state, full rate as IGST for inter-state -- computed per fulfillment, then grouped for posting.

Multiple GST rates within one state-day

A state's daily aggregate can span 5%, 12%, 18%, 28% items in the same day -- each rate gets its own Sales + CGST/SGST(or IGST) line-group within the one voucher, never blended into a single number.

Credit notes use the return date's state

A return posts against the state the return date resolves to -- not silently re-using the original shipment's state -- and never nets against the original Sales entry.

02

B2B orders & GSTIN handling

The moment an order carries a buyer GSTIN, it needs to become a completely different kind of invoice -- not a variant of the same one.

Full B2B deep dive

Three ways to capture a GSTIN

Shopify's checkout has no native GSTIN field -- Ledgeree reads it from a checkout note attribute, an order or company metafield, or Shopify's native B2B/Wholesale company (Shopify Plus), configurable per shop.

Matched by GSTIN, never by name

Customer names vary and typo across orders ("Acme Pvt Ltd" vs "ACME Private Limited") -- the one reliable identifier is the GSTIN, so party-ledger lookup is always keyed on it, checked before ever creating a new ledger.

Auto-created Sundry Debtor / Contact

The first order from a new B2B customer creates their dedicated ledger (name + GSTIN + state) on the fly -- idempotent, so a hundred repeat orders from the same customer never create a hundred ledgers.

Never folded into the B2C aggregate

B2B orders are excluded from the standard state-day gateway/website aggregate entirely and post against the customer's own ledger -- unlike at least one competing Shopify-to-Zoho connector that reportedly drops the captured GSTIN and books every buyer as a plain consumer.

One voucher per fulfillment, never aggregated

Unlike the B2C daily aggregate, every B2B fulfillment gets its own voucher -- so a tax-credit invoice always maps to exactly one real shipment, never a blended multi-order total.

Its own Sales / Sales Return ledger pair

B2B sales and returns post to dedicated ledgers, kept separate from ordinary retail Sales/Sales Return -- your B2C and B2B revenue never mix in one account.

Configurable GSTIN-source-not-enabled fallback

If auto-ledger-creation is switched off, a captured GSTIN is simply ignored and the order falls back to plain B2C -- a deliberate escape hatch, not a silent failure.

03

Export orders

Zero-rated, but not a simple 'set GST to 0%' toggle -- exports have their own invoicing rules and their own failure modes.

Full export deep dive

Automatic detection by ship-to country

Any order shipping outside India is treated as an export -- no manual flagging per order.

Zero-rated under your LUT, blocked without one

Every line item is posted at 0% GST regardless of its normal domestic rate -- but only once a valid LUT (Letter of Undertaking) number is configured; without one, the export order is blocked (not silently posted at the wrong rate).

LUT financial-year staleness handling

A LUT is filed per financial year and goes stale every April 1st. Ledgeree records which FY your LUT covers, blocks an export order whose FY doesn't match, and nudges you every January-March to file the next year's LUT before the current one expires.

One voucher per shipment, never aggregated

Like B2B, export orders are never folded into a daily aggregate -- a Shipping Bill (customs) is issued per physical shipment, so one voucher always maps to exactly one shipping bill, never several blended together.

Its own export Sales / Sales Return ledger pair

Kept out of your domestic Sales accounts entirely, same principle as B2B.

Shipping Bill number & port code, recorded after the fact

A Shipping Bill doesn't exist until customs actually clears the shipment, days after the order syncs -- so Ledgeree lets you record the Shipping Bill number, date, and port code against the already-posted voucher once you have them, for your Rule 46 compliance records.

Foreign-currency total captured for your records

When a customer is charged in a foreign currency, that currency and total are recorded alongside the INR figures your books actually need (already correctly converted by Shopify's own payment processing) -- so you have both figures on file without a manual note.

Skip toggle if you invoice exports manually

Don't want export orders synced at all? A single toggle excludes them from sync entirely, with no blocking errors generated for orders you've chosen to handle yourself.

04

Returns & credit notes

A return is not a reversal -- your books need to show what actually happened, when it happened.

Same-day returns never post at all

If an order is returned before its shipment's daily aggregate has even posted, it's excluded before ever reaching your books -- no Sales entry, no credit note, no cleanup needed.

Next-day-or-later returns become real Sales Return vouchers

Posted against the return date's own state as their own daily aggregate -- gross sales and returns both stay visible on their own lines, exactly what a GST return expects, instead of silently netting against the original entry.

Dedicated Sales Return ledger, never the Sales ledger

Returns never reverse into the Sales account directly -- always their own ledger, so a glance at Sales alone never overstates true net revenue.

05

Party ledger granularity

How finely your B2C sales get broken out by payment method or courier -- a bookkeeping-depth choice, not a correctness one.

Single ledger (default)

Every B2C sale posts against one default party/clearing ledger -- simplest books, right for most sellers.

Per-gateway ledgers

Split B2C sales by payment gateway (Razorpay, COD, etc.) into their own ledgers -- useful when you reconcile gateway settlements separately.

Per-gateway + per-COD-carrier ledgers

COD orders further split by the courier/tracking company handling cash collection -- for sellers who reconcile COD remittances by courier.

Graceful fallback, never a blocked sync

An unmapped gateway or carrier falls back to the next level up (carrier -> gateway -> shop default) automatically -- routing granularity is a bookkeeping preference, never allowed to block a real sync.

06

Product mapping & GST rates

Configuring GST% shouldn't mean filling in a spreadsheet row for every SKU you sell.

Three-tier GST rate resolution

Set a shop-wide default GST rate, override it per Shopify product type, or override it per individual SKU -- resolved in that order, so you only configure exceptions, not every product.

HSN/SAC code per SKU

Mapped alongside each SKU, mandatory on a compliant tax invoice -- captured once per product, never re-entered per order.

Blocks, never guesses, on missing configuration

If a SKU truly has no resolvable GST rate (no per-SKU, no product-type, no shop default), the order is blocked with a clear error rather than posted at an invented rate.

07

Itemized billing (optional)

Post one lump Sales figure per day, or go all the way to per-SKU inventory lines in Tally -- your choice.

Off by default: one Sales figure per state/day/rate

The simplest, fastest-to-reconcile posting shape -- right for sellers who don't need per-product inventory tracking inside Tally itself.

On: every order line item becomes its own inventory line

Turns on real Stock Item-level posting in Tally (ALLINVENTORYENTRIES), for sellers who want product-level inventory movement tracked directly in their books.

Auto-mapped against your real Tally Stock Item list

A one-click action fetches your actual Stock Item master list from Tally and matches Shopify SKUs to it by name -- no manual typing of item names into a spreadsheet.

Hard block on an unmapped SKU, never a silent guess

If itemized billing is on and a SKU doesn't match a real Stock Item, the push is blocked with a clear error -- Ledgeree deliberately never auto-creates a Stock Item master on your behalf; you map or create it, then it flows.

08

Voucher numbering & multi-company

Invoice sequences are expected to be gap-free and explainable -- not an accident of retry timing.

Tally's own auto-numbering, or an app-controlled sequence

Default lets Tally number vouchers itself; switch to app-controlled numbering for a custom prefix/suffix/padding and your own counter.

Monthly or financial-year counter resets

An app-controlled sequence can restart every calendar month or every FY (1st April) -- configurable per voucher type.

A number is only consumed once Tally confirms the push

The counter never increments before a push is confirmed successful -- so a failed or retried push can never burn a real invoice number that never actually appears in Tally.

Multi-company / FY-rollover routing

For sellers who create a new Tally company every financial year, vouchers route to the correct company automatically based on a configurable naming pattern -- no manual company-switching.

Multi-instance / multi-port Tally routing

Running more than one Tally instance (or company on different ports) on the same machine or network -- Ledgeree probes and posts to the right one automatically.

09

Reliability & safety guards

The parts you never see until something would otherwise go quietly wrong.

Won't post real vouchers to an unlicensed Tally

If your Tally instance is running in demo/educational mode, a voucher write is refused outright -- so a licensing gap gets caught immediately, not discovered later as vouchers that silently never actually saved.

No cloud round-trip for Tally data

A small local relay agent talks to your Tally Prime installation directly over your own network -- your ledger and voucher data reaches Tally without needing to pass through a third-party server that also has to read your books.

Cap reached? Pause & prompt, never silent overage billing

At 80% of your plan's shipment cap you get a warning; at 100%, new fulfillments are still captured and cached -- never dropped -- while sync pauses until you upgrade, then flushes through automatically in order.

Automatic retry with backoff, then a clear failure log

A failed push retries automatically; if it keeps failing, sync pauses and the real ERP error message is logged -- not just "something went wrong."

Reconciliation view

A dedicated view compares Shopify's own totals against what actually posted in Tally/Zoho, to catch sync drift -- separate from payment/settlement reconciliation, which is out of scope.

10

Tally Prime or Zoho Books

One canonical order model, two very different ERPs underneath.

All integrations

Tally Prime: local relay agent, no cloud API required

Tally has no cloud API of its own -- the relay agent bridges your local Tally installation to Ledgeree's sync engine.

Zoho Books: direct cloud API, no local agent needed

Zoho's own REST API is called directly -- GST itself is computed by Zoho from each line's tax percentage, so the same canonical order model drives both adapters without duplicating tax logic.

Same GST correctness either way

Place-of-supply splits, B2B GSTIN handling, export zero-rating, and return handling are identical regardless of which ERP you connect -- the adapter changes, the correctness doesn't.

The flow

From fulfillment to booked voucher

  1. 01

    Connect

    Install from the Shopify App Store, pick Tally Prime or Zoho Books, and pair the local relay agent (Tally) or authorize your org (Zoho) in a couple of minutes.

  2. 02

    Map once

    Tell Ledgeree which Shopify location maps to which warehouse/state, and your GST rates per product or product type. Most of this only needs setting up once.

  3. 03

    Ship orders as usual

    The moment an order is fulfilled, it's captured. Nothing posts on unfulfilled or pre-ship edits -- only what actually shipped.

  4. 04

    Wake up to booked vouchers

    Each day's shipments post as correctly GST-split vouchers in your books, with returns credit-noted separately -- ready for your accountant, not a pile of CSVs.

Don’t run Tally or Zoho at all?

Ledgeree Books is the standalone answer.

Sole proprietors and partnerships without any accounting software get a read-only daybook, a running GST-liability tracker, and a downloadable GSTR-1/3B-ready export -- no relay agent, no ERP required.

See Ledgeree Books

See it against your own orders.

A 5-day free trial is enough to watch a real day’s shipments post correctly.

Start free trial