Tax reconciliation
What is being compared
For every order, the engine holds two numbers: what Shopify collected at checkout, and what the engine says was owed based on your registrations, rates and tax classes. Reconciliation is the verdict on the difference.
A per-line tolerance of 0.02 in the transaction currency absorbs cross-rounding between two independent engines — that is a rounding difference, not a discrepancy.
The six verdicts
| Verdict | Meaning | Typical cause |
|---|---|---|
| Match | Within tolerance | Healthy |
| Over | Shopify collected more than owed | A stale rate, or a rate override that has not propagated |
| Under | Shopify collected less than owed | A rate change you applied here but not in Shopify |
| Unregistered | Tax was charged where you have no registration | Missing registration, or a registration whose active dates have lapsed |
| Not charged | The engine says taxable, Shopify collected nothing | Almost always an unmapped product tax class |
| Unresolved | The engine could not resolve the jurisdiction | Incomplete address data |
Unresolved is the one to take seriously. It is not "small" — it is unknown. The engine emits it when it could not determine what was owed at all, which means the delta is zero by construction. That is why unresolved can never be automatically demoted to immaterial: doing so would let a period finalise with an unknown liability silently treated as nil.
Dispositions
A disposition is what a human — or a governed rule — decided about a verdict.
| Disposition | Meaning |
|---|---|
| Immaterial | Below your materiality policy. Never blocks a close |
| Resolved | Dispositioned with a typed resolution |
| Waived | Accepted as-is. May require a second approver |
| Reopened | A recompute changed the money after a resolution |
| Superseded | Replaced by a newer revision of the order |
The verdict is preserved on the row regardless of the disposition. A disposition that overwrites its verdict makes historical questions unanswerable — which is precisely the sort of question an auditor asks.
Cause clustering
At real order volume, a flat list of five thousand discrepancies is not a worklist. Rows are grouped by cause into readable cluster keys:
rate_low | india_gst | 29@18%
unmapped_product | us_sales_tax | CA
Keys are readable rather than hashed, because they appear in logs, in suppression
scopes and in support conversations. Working a cluster fixes hundreds of rows at
once — a cluster of unmapped_product is one tax-class mapping, not five hundred
individual decisions.
Root-cause detection is helped by two fields carried on every computed line: the product ID, and whether the tax class came from a real mapping or from the fallback. Both are descriptive and deliberately excluded from the idempotency hash, so adding them did not invalidate existing computations.
Materiality policy
Your materiality policy decides what is too small to be worth anyone's time.
| Setting | What it does |
|---|---|
| Absolute minimum | Amounts below this are immaterial |
| Relative threshold | A percentage of the order |
| Block statuses | Which verdicts block a period close — default under, not charged, unresolved |
| Waive approval threshold | Above this amount, a waiver needs a second approver |
| Exposure alert threshold | When total exposure raises an alert |
Over-collection is a customer-refund problem, not a filing problem — you are not under-declaring anything. Blocking a close on it is what drove merchants to bulk-waive, and bulk-waiving is worse than having no gate at all. It remains visible and workable; it just does not stop you filing.
Policy amounts are authored in your chosen currency but compared on a normalised anchor. A ₹1 floor enforced as if it were $1 would be roughly eighty times too permissive. Where a policy amount cannot be converted, the built-in floor applies — which is conservative, meaning more rows stay blocking, never fewer.
Suppression rules
A suppression rule silences a known, understood cause. The argument for rules over waiving is simple: revoking a rule reopens the rows it suppressed; a waiver cannot be undone that way.
Rules are scoped by cause, regime, jurisdiction and amount, and are FX-anchored like policy amounts. A rule whose threshold cannot be anchored is skipped rather than applied at the wrong scale — silently applying a ₹-scale threshold to a USD anchor would suppress far more than intended.
Rules can carry an expiry, and expired rules are swept nightly.
Separation of duties on waivers
Above your waive-approval threshold, a waiver needs a second person.
The control is on identity, not on permission. Holding both the requesting and the approving permission does not let one person do both — the approver must be a different user. And where user identity is not available (RBAC not yet configured, so every actor collapses to one account), the request is refused before staging rather than being frozen pending forever.
Order edits and supersession
When an order is edited in a way that changes what tax was owed, the engine recomputes and marks the prior revision superseded.
Supersession is applied to both the reconciliation row and the underlying computation. That second half matters: statutory returns, evidence packs, amendments, e-invoice reconciliation and nexus turnover all sum computations over a date window, so marking only the reconciliation would fix the worklist while double-counting the edited order on the return itself.
Not every edit triggers a recompute. A tax signature and an order signature are compared first, so fulfilment and tag edits do not recompute — but an address change does, because it moves what you owe even when what Shopify collected has not changed.
Sticky resolution
A resolution stays resolved. Shopify redelivers order webhooks on any non-2xx
response, and persistence returns successfully on a deduplicated write — so
naive logic flips a resolved row back to under on every redelivery while
leaving the resolver's name attached.
Only a real change in the money (more than half a cent) reopens a resolved row, and when it does, the disposition fields are cleared properly so later verdict changes can still land.
Working the tab
| Feature | What it does |
|---|---|
| Filters | Verdict, disposition, regime, jurisdiction, period, owner, materiality |
| Aging | How long discrepancies have been open |
| Drill-down | The full computation behind a row |
| Assignment | Give a row or a cluster an owner |
| Bulk resolve | Disposition a selection at once |
| Saved views | Your filter combinations, kept |
| Export | CSV or JSON of the current filtered set |
| Trends | Exposure over time, and open-versus-closed |
Exposure snapshots are written nightly so the trend is real history rather than a recomputation of the current state.
Filing gate
Open reconciliations in your policy's blocking set prevent a period from being finalised. That is the point of the tab: the return should not be prepared over discrepancies nobody has looked at.
The gate reports blockers and warnings separately, and tells you which cluster is responsible — so unblocking a close is usually one fix, not a hundred.
Plan tiers
| Capability | Free | Starter | Pro | Agency | Enterprise |
|---|---|---|---|---|---|
| Verdicts, worklist, drill-down | — | — | ✓ | ✓ | ✓ |
| Cause clustering | — | — | ✓ | ✓ | ✓ |
| Materiality policy | — | — | ✓ | ✓ | ✓ |
| Suppression rules | — | — | ✓ | ✓ | ✓ |
| Assignment, bulk actions, saved views | — | — | ✓ | ✓ | ✓ |
| Separation of duties on waivers | — | — | ✓ | ✓ | ✓ |
| Exposure trend and snapshots | — | — | ✓ | ✓ | ✓ |
Best practices
- Work clusters, not rows. One unmapped product tax class can account for a four-figure row count.
- Write a suppression rule instead of waiving. It is reversible, it is scoped, and it documents the decision.
- Never bulk-waive to unblock a close. You will be waiving the one real under-collection along with the noise.
- Set materiality deliberately. Too low and the tab is unusable; too high and the gate stops protecting you.
- Investigate unresolved first. It is the only verdict that means "we do not know", and it cannot be demoted away.
See also
- Tax overview — how computation and rates work
- Registrations & nexus — the source of unregistered verdicts
- Filing & close — the gate this tab feeds
- Approval queues — the wider maker-checker pattern