KintsugiKintsugi

Migrating from Avalara/TaxJar to Kintsugi

Migrating tax providers is mostly a mapping exercise plus one judgment call. The mapping is small: four concerns, four replacements. The judgment call is how much you want to find out before the old system is switched off. This guide covers both, then the data you need to bring with you.

This page maps your integration to the Tenanted API, release 2026-07-21. Send Api-Key: <key> and Api-Version: 2026-07-21 on every request. Paths carry no /v1 prefix, and every field is camelCase.

Cut over at the start of a filing period and keep the old system's records. A period split across two engines is the one thing that makes a return genuinely hard to reconcile.

Understanding Key Differences

Three differences change how you build, rather than just which URL you call.

API Endpoint Mapping

Find the call you make today in the left two columns and read across.

AvalaraTaxJarKintsugi
Tax calculationQuote tax for a cart
POST/api/v2/transactions/createDocumentType: SalesOrderPOST/v2/taxesPOST/tax-estimations
All three quote without recording. Avalara does it on the same endpoint that records, switched by document type: a type ending in Order is a temporary estimate that is not preserved. TaxJar and Kintsugi use a separate call that stores nothing.
Transaction recordingCommit the completed sale
POST/api/v2/transactions/createDocumentType: SalesInvoicePOST/v2/transactions/ordersPOST/transactions
This is the call that changes your liability, so if you port one thing exactly, port this one. An Avalara type ending in Invoice is the recorded counterpart of the row above.
Customer managementBuyers and their exemptions
POST/api/v2/companies/{companyId}/customersPOST/v2/customersPOST/customers
Key it on the customer ID you already use, so the mapping stays obvious during a parallel run. Exemptions are their own object in Kintsugi: POST /exemptions carries the customerId, and the certificate is uploaded to the exemption.
Product managementCatalog and tax categories
POST/api/v2/companies/{companyId}/itemsGET/v2/categoriesRead-only listPOST/products
TaxJar has no catalog to export: it takes a product_tax_code per line item, so this row is a build rather than a migration. Kintsugi wants its own productCategory and productSubcategory, listed by GET /products/categories.
Endpoints map cleanly; tax codes do not. Avalara tax codes and TaxJar product_tax_code values have no Kintsugi equivalent, every product you create needs a productCategory and productSubcategory, and a pair the catalog does not recognize returns 400. Budget a classification pass over the catalog before you rely on Kintsugi's rates.

Kintsugi paths are verified against the spec that generates this site's API Reference. Competitor paths are current as of publication and taken from Avalara's and TaxJar's own SDKs; check them against your provider's reference before you write the mapping into code, since only they control those.

Migration Strategy

All three approaches end in the same place. They differ in how much you find out before the old system is gone.

Option ABig bangSwitch everything on one date.
How it goes
Point every call at KintsugiTurn the old system offYou learn what broke in production
RiskHighestTimeShortest
Option BParallel runRun both, compare, then switch.
How it goes
Call both, charge the old oneDiff the amounts, chase the gapsSwitch once the diff is explainable
RiskLowTimeMedium
Option CGradual rolloutMove one slice at a time.
How it goes
Start with one region or stateThen one product lineWiden until nothing is left
RiskLowestTimeLongest
Whichever you pick, cut over at the start of a filing period and keep the old system's records. A period split across two engines is the one thing that makes a return hard to reconcile.

We recommend the parallel run for anything already in production. It is the only option that lets you compare real amounts on real orders before the old system stops being your safety net, and the cost is a few weeks of double-calling rather than a rewrite.

What to Bring With You

Nexus thresholds are measured over rolling windows, so Kintsugi needs history to tell you where you already have obligations. Starting cold means starting with an empty exposure map.

Products and customers

Create these first: each transaction item names its product by externalProductId. Creates are idempotent on externalId and source, so a batch job can retry a failed request without leaving a duplicate. Store the Kintsugi id against your own record as you go.

Exemption certificates

An exemption is its own object. POST /exemptions carries the customerId it belongs to, along with the exemptionType, the startDate, and the buyer's registration details such as fein and salesTaxId. The certificate itself is a PDF of up to 10 MB, uploaded to the exemption with POST /exemptions/{exemptionId}/certificates. To move many at once, POST /exemptions/bulk creates up to 100 in one all-or-nothing request.

Historical transactions

Sync enough history to cover each state's nexus measurement window, and send each transaction's real date: it decides which filing period the transaction lands in. For a bulk backfill, CSV upload is usually faster than replaying records through the API.

Registrations

Record where you are already registered with POST /registrations, sending the registrationDate each permit takes effect. Kintsugi calculates tax where a registration is active, so a missing registration reads as a state you do not collect in.

Keep externalId values identical to the ones your old integration used. This is what makes a parallel run comparable order by order, and what makes reconciliation possible afterwards.

Common Migration Challenges

Validation Checklist

Before cutover:

  • Estimation implemented, with address validation ahead of it
  • Transaction creation implemented, keyed on your existing order IDs, with the 202 handled as accepted rather than finished
  • Customers synced, with exemptions and certificates attached
  • Catalog synced, every product classified against Kintsugi's taxonomy
  • Historical transactions backfilled across each state's measurement window
  • Existing registrations recorded with their effective dates
  • Api-Version: 2026-07-21 sent on every request
  • Retry logic in place, and error logging that keeps each error's requestId
  • Parallel-run diffs explained at the line level, not just the total
  • Rollback plan documented, with the old system's records retained

Post-Migration

Stop maintaining tax rules

Kintsugi tracks jurisdiction rule changes against your product categories, so a rate or taxability change needs nothing from you. Update a product only when your own classification changes.

Estimate freely

Because estimates record nothing, you can call the endpoint every time the cart or the address changes, then create the transaction once payment clears. See Integrating Kintsugi's API for where each call belongs.

Next Steps

API Reference

Request formats and response structures in the API Reference.

Support

Migrating a large or unusual integration? Our Support Team has done this before.