Skip to main content
Public invoice and bill creation does not calculate tax. The DualEntry UI always calculates tax first, then creates the record with the tax result on each line. API clients must follow the same flow. This guide shows how to call the V2 tax calculator, map its result onto invoice line items, and create the invoice: POST /public/v2/taxes/calculate/ → map tax fields → POST /public/v2/invoices/. The same flow applies to bills using vendor_id in place of customer_id.
A shipping address on the invoice alone does not add tax. Pass the buyer address on the calculate call as transaction_buyer_address instead. The shipping_address you send on the invoice itself is for fulfillment only and has no effect on the tax calculation.

Prerequisites

  • V2 API (/public/v2/...)
  • X-API-KEY header with your organization’s API key (authenticating your requests)
  • The company is set up for the correct tax regime (GST, VAT, or US sales tax)
  • The customer (or vendor) has is_taxable set to true when tax should apply

Step 1: Resolve IDs

Look up the company, customer or vendor, and item IDs the calculate call needs:

Step 2: Calculate tax

Send the resolved IDs and item lines to the calculate endpoint:
Required:
  • company_id
  • customer_id (money-in, e.g. invoices) or vendor_id (money-out, e.g. bills), not both
Usually also send:
  • items: each with item_id, quantity, and unit_price (item_id may be null for a vendor expense line)
  • transaction_buyer_address: the destination address, required for US sales tax
  • transaction_date and currency_code: required for US sales tax
  • supply_date: filters VAT/GST rates by their validity window
The response type is one of: For GST and VAT, the first calculate call often returns available_rates. Pick a rate, send it on the line as selected_gst_tax_rate_id or selected_vat_rate_id, then calculate again with that rate selected.

Step 3: Map the result onto each invoice line

Copy each field from the calculator response onto the matching field in the invoice line’s tax object: Also carry the line amount over: calculator unit_price → invoice line rate.

Step 4: Create the invoice

Send the mapped tax fields on each line when you create the invoice:
Use the real values returned by your calculate call. The numbers above are examples only. You may still send shipping_address on the invoice for fulfillment; it does not replace the calculate step.

Canada GST example (two calculate calls)

GST and VAT regimes need a second calculate call once a rate is selected. Call A: list available rates Calculate without a selected rate first to see what DualEntry offers for this address:
This returns type: "GST" with data.place_of_supply ("ON") and data.available_rates listing candidate rate IDs. Pick one (for example, the Ontario HST rate) from available_rates or from GET /public/v2/gst-tax-rates/. Call B: calculate again with the selected rate Add the chosen rate ID to the line and calculate again to get the final tax amounts:
Each returned line now has tax_code, tax_rate, tax_amount, and selected_gst_tax_rate_id set. Map those onto the invoice as in Step 3, then create the invoice using the values from call B.

US sales tax

  1. Send transaction_buyer_address (include region and postal_code), transaction_date, and currency_code on calculate.
  2. The response type is SALES_TAX.
  3. Copy tax_code, tax_rate, and tax_amount onto the line’s tax object.
  4. Create the invoice.
If the buyer address is missing, calculate returns type: "NONE" with a reason. Fix the address and calculate again before creating the invoice.

VAT

  1. The first calculate call returns available_rates.
  2. Send selected_vat_rate_id on the line and calculate again.
  3. Set the invoice line’s tax.vat_rate_id from the same selected_vat_rate_id.
  4. Create the invoice.

If calculate returns an error

The calculate endpoint returns errors for a few common mistakes: Fix the request and calculate again. A NONE result is not itself an error: it means DualEntry could not determine tax for this request, and the reason field says why.

Checklist before go-live

  • Call calculate before creating the invoice or bill
  • Pass the buyer/shipping address on calculate as transaction_buyer_address
  • For GST/VAT, select a rate from available_rates and calculate a second time
  • Copy every mapped tax field onto each line’s tax object
  • Confirm the invoice response shows items[].tax with the expected code, rate, and amount
This guide covers the calculate-then-create flow. Browse the individual V2 resources in the V2 API reference, including the calculate tax reference, GST rates, and product tax codes.
Last modified on September 16, 2026