Taxes

Calculate the tax for a transaction before you create the record.

On create and update, DualEntry keeps the tax you send on each line unless you set auto_calculate_tax to required. That setting calculates native US sales tax using DualEntry's tax engine, and Avalara US sales tax, VAT, and GST, then replaces the line tax.

On a record create or update with auto_calculate_tax set to required, a result that is DualEntry's own VAT or GST fails with 422. A calculation that cannot finish also fails with 422.

Use this endpoint to preview the tax, to check the amounts after you choose a VAT or GST rate, or to copy the result onto lines you save yourself.

Required:

  • company_id
  • customer_id or vendor_id, and not both

Usually also send:

  • items, with item_id, quantity, and unit_price on each line
  • transaction_buyer_address, transaction_date, and currency_code for US sales tax
  • supply_date, to keep the VAT and GST rates that are valid on that date

The response type is SALES_TAX, VAT, GST, or NONE. NONE is still HTTP 200, and the body gives the reason, such as a missing buyer address.

Copy each result line onto items[].tax, and onto expenses[].tax when the record has expenses:

  • tax_code to tax.code
  • tax_rate to tax.rate
  • tax_amount to tax.amount
  • is_taxable to tax.is_taxable
  • tax_exempt_amount to tax.tax_exempt_amount
  • tax_metadata to tax.tax_metadata
  • selected_vat_rate_id to tax.vat_rate_id
  • selected_gst_tax_rate_id to tax.gst_tax_rate_id

For native Canada GST and VAT, the first response includes available_rates. Choose one and send it on the next call as selected_vat_rate_id or selected_gst_tax_rate_id. On a record line without auto_calculate_tax, send that rate as tax.vat_rate_id or tax.gst_tax_rate_id.

When a write sets auto_calculate_tax to required on a customer transaction, DualEntry reads shipping_address, then billing_address, then the address saved on the customer. If you send neither address, DualEntry copies the customer's saved address to billing_address and shipping_address.

On a vendor record write with auto_calculate_tax set to required, DualEntry reads ship_from_address and ship_to_address, then the addresses saved on the vendor and the company. The write stores only the ship addresses you sent. For a vendor preview on this endpoint, send transaction_ship_from_address and transaction_ship_to_address instead.

For US sales tax on this endpoint, send transaction_buyer_address. DualEntry uses that field and does not fall back to the address saved on the customer.

This endpoint is part of API v2.

post/public/v2/taxes/calculate/

Request

  • Base URL: https://api.dualentry.com
  • URL: https://api.dualentry.com/public/v2/taxes/calculate/
  • Auth: none declared

Headers

Idempotency-Keystring

Optional. A unique value (a UUID works well) identifying this operation. If the request is repeated with the same key, the original response is replayed instead of the operation running again, so a retry cannot create a duplicate record. Results are replayable for 48 hours. Reusing a key with a different request body returns 422.

Request body

company_idinteger required

Company ID

customer_idinteger nullable

Customer ID (money-in records)

vendor_idinteger nullable

Vendor ID (money-out records)

record_type'invoice' | 'cash_sale' | 'customer_credit' | 'sales_order' | 'bill' | 'direct_expense' | 'vendor_credit' | 'purchase_order'
transaction_datestring date nullable

Transaction date — required for sales tax

supply_datestring date nullable

Tax point / date of supply — filters VAT and GST rates by valid_from / valid_to

currency_code'AED' | 'AFN' | 'ALL' | 'AMD' | 'ANG' | 'AOA' | 'ARS' | 'AUD' | 'AWG' | 'AZN' | 'BAM' | 'BBD' | 'BDT' | 'BGN' | 'BHD' | 'BIF' | 'BMD' | 'BND' | 'BOB' | 'BRL' | 'BSD' | 'BTN' | 'BWP' | 'BYN' | 'BZD' | 'CAD' | 'CDF' | 'CHF' | 'CLF' | 'CLP' | 'CNY' | 'COP' | 'CRC' | 'CUP' | 'CVE' | 'CZK' | 'DJF' | 'DKK' | 'DOP' | 'DZD' | 'EGP' | 'ERN' | 'ETB' | 'EUR' | 'FJD' | 'FKP' | 'GBP' | 'GEL' | 'GHS' | 'GIP' | 'GMD' | 'GNF' | 'GTQ' | 'GYD' | 'HKD' | 'HNL' | 'HTG' | 'HUF' | 'IDR' | 'ILS' | 'INR' | 'IQD' | 'IRR' | 'ISK' | 'JMD' | 'JOD' | 'JPY' | 'KES' | 'KGS' | 'KHR' | 'KMF' | 'KPW' | 'KRW' | 'KWD' | 'KYD' | 'KZT' | 'LAK' | 'LBP' | 'LKR' | 'LRD' | 'LSL' | 'LYD' | 'MAD' | 'MDL' | 'MGA' | 'MKD' | 'MMK' | 'MNT' | 'MOP' | 'MRU' | 'MUR' | 'MVR' | 'MWK' | 'MXN' | 'MYR' | 'MZN' | 'NAD' | 'NGN' | 'NIO' | 'NOK' | 'NPR' | 'NZD' | 'OMR' | 'PAB' | 'PEN' | 'PGK' | 'PHP' | 'PKR' | 'PLN' | 'PYG' | 'QAR' | 'RON' | 'RSD' | 'RUB' | 'RWF' | 'SAR' | 'SBD' | 'SCR' | 'SDG' | 'SEK' | 'SGD' | 'SHP' | 'SLL' | 'SOS' | 'SRD' | 'STN' | 'SVC' | 'SYP' | 'SZL' | 'THB' | 'TJS' | 'TMT' | 'TND' | 'TOP' | 'TRY' | 'TTD' | 'TWD' | 'TZS' | 'UAH' | 'UGX' | 'USD' | 'UYU' | 'UZS' | 'VES' | 'VND' | 'VUV' | 'WST' | 'XAF' | 'XAG' | 'XAU' | 'XCD' | 'XDR' | 'XOF' | 'XPD' | 'XPF' | 'XPT' | 'YER' | 'ZAR' | 'ZMW' | 'ZWL'

Example request

{
  "company_id": 1,
  "customer_id": 1,
  "credit_source": {
    "record_id": 1
  },
  "transaction_buyer_address": {
    "postal_code": "94105",
    "city": "San Francisco",
    "line1": "123 Main St",
    "line2": "Suite 100"
  },
  "transaction_ship_from_address": {
    "postal_code": "94105",
    "city": "San Francisco",
    "line1": "123 Main St",
    "line2": "Suite 100"
  },
  "transaction_ship_to_address": {
    "postal_code": "94105",
    "city": "San Francisco",
    "line1": "123 Main St",
    "line2": "Suite 100"
  },
  "transaction_date": "2025-08-29",
  "supply_date": "2025-08-29",
  "items": [
    {
      "discount_type": "PERCENTAGE",
      "discount_value": "10.00",
      "item_id": -1,
      "quantity": "1.000000",
      "unit_price": "100.000000"
    },
    {
      "item_id": -2,
      "quantity": "2.000000",
      "record_level_discount_amount": "5.00",
      "selected_vat_rate_id": 1,
      "unit_price": "50.000000"
    }
  ]
}

Response

OK

type'SALES_TAX' | 'VAT' | 'GST' | 'NONE' required

Example response

{
  "data": {
    "items": [
      {
        "tax_rate": "0.2000",
        "tax_amount": "20",
        "amount_with_tax": "120",
        "tax_exempt_amount": "0"
      }
    ],
    "total_tax_amount": "20",
    "total_with_tax": "120",
    "destination": {
      "postal_code": "94105",
      "city": "San Francisco",
      "line1": "123 Main St",
      "line2": "Suite 100"
    }
  }
}

Changes

    • warning

      added the new CW enum value to the //// response property for the response status

    • warning

      added the new NO enum value to the //// response property for the response status

    • warning

      added the new ZA enum value to the //// response property for the response status