Skip to content

Tax

Who computes the tax, and can you override it? The messiest area of the three APIs. QuickBooks in the United States computes tax itself and will not let you create rates; everywhere else you carry your own. And rounding rules differ enough that re-deriving tax from rate times base is always wrong.

Concepts
8
Divergences
3
Structural
1

Endpoints

Xero

GET /TaxRates

Rates with TaxComponents[] for compound tax

QBO

SELECT * FROM TaxCode / TaxRate

Plus the TaxService endpoint outside the US

NetSuite

taxcode, taxgroup, taxtype, nexus

Jurisdiction model

The same concept in three vocabularies

Read across a row. Where a cell is absent, the concept has nowhere to live in that system — which is a design constraint, not a gap to paper over.

NativeNative
— A field or object exists for it
PartialPartial
— Exists with a caveat that changes what you can build
DerivedDerived
— Not stored — you compute it
AbsentAbsent
— Nothing in the API
Tax fields compared across Xero, QuickBooks Online and NetSuite
ConceptXeroQBONetSuite
Rate object
Native

TaxRate

TaxComponents[] express compound rates

Native

TaxCode to TaxRate

Many-to-many via TaxRateDetail

Native

taxcode / taxgroup

Line reference
Native

TaxType

The rate code, e.g. "OUTPUT2"

Native

TaxCodeRef

Native

taxcode

Inclusive / exclusive
Native

LineAmountTypes on the document

Partial

GlobalTaxCalculation

Non-US only

Native

Per-nexus configuration

Can you create rates via the API?The row that decides whether your tax UI is editable.
Native

Yes

Partial

US: no

Automated sales tax computes rates from addresses. Non-US: yes

Native

Yes

Computed tax on the document
Native

TotalTax + per-line TaxAmount

Native

TxnTaxDetail.{TotalTax, TaxLine[]}

Native

taxtotal + per-line

Overriding the computed tax
Native

Per-line TaxAmount

Partial

TxnTaxDetail override

Honoured inconsistently under automated sales tax

Native

Line-level override

Jurisdiction model
Partial

A flat list of rates

Partial

Resolved from addresses

US automated sales tax

Native

Nexus per subsidiary and address

Reporting / return support
Partial

Reports endpoints

Partial

TaxSummary report

Native

Tax reports, SuiteTax

What actually differs, and what you do about it

A difference stated without a response is trivia. Each of these carries the handling.

Structural

QuickBooks US is a different product from QuickBooks elsewhere

QBO

Under automated sales tax you cannot create tax rates through the API, and the tax on a transaction is computed by Intuit from the addresses on it. Amounts you send may be silently replaced. Outside the US, GlobalTaxCalculation and explicit tax codes behave the way Xero's do.

Do — Expose canCreateTaxRates as a capability. The tax UI is read-mostly where it is false, and the write path does not promise a tax amount it cannot guarantee.

Sharp edge

Compound tax survives only as a list

Xero · QBO · NetSuite

Xero's TaxComponents and QBO's TaxLine both express 'this 13% is 5% federal plus 8% provincial'. A canonical taxAmount scalar throws that away — and the components are exactly what a tax return needs.

Do — Model tax as { code, name, components: [{ name, rate, amount }], total }. The scalar is a computed property of the breakdown, not the storage.

Sharp edge

Never re-derive tax from rate times base

Xero · QBO · NetSuite

Rounding differs per system and per jurisdiction: per line or per document, half-up or half-even. Recomputing produces a number that is right most of the time and off by a cent on the invoices someone is looking at.

Do — Store the source's amount. If you display a rate, display the source's rate. Where you must compute — a preview before a write — mark it as an estimate until the source answers.

The type the components consume

tax.ts
type TaxComponent = { name: string; rate: string; amount: Money };

type TaxBreakdown = {
  code?: string;                 // the source's tax code, verbatim
  name?: string;
  /** Compound and multi-jurisdiction tax, kept whole. A return needs these. */
  components: TaxComponent[];
  total: Money;                  // as computed by the source, never by us
  mode: "exclusive" | "inclusive" | "none";
  computedBy: "source" | "estimate";
};

What this changes in the interface

The payoff. Every difference above that reaches the surface, and what the component does about it.

Tax may not be editable
The tax field is disabled with an explanation where the source computes it, rather than accepting input the write will discard.
Compound tax has parts
The tax total is expandable into its components in the document detail. One number with no breakdown is not enough to file anything.

Where the accounting is explained

What consumes this payload

The normalised object above is what the components read. These are the surfaces it feeds, the words for the concepts in it, and the document that explains the accounting.

Compared acrossXero docsQuickBooks Online docsNetSuite docs

Works in your QuickBooks Online or Xero file

Get your books closed every month

Lopifi is building AI bookkeeping that keeps your books closed on US GAAP as transactions happen, with a CPA review every quarter, for $200 a month. We’re not open yet.

$200/month when we open. No card now.