This integration connects FreshBooks to your Avalara AvaTax account, calculating real-time sales tax on every FreshBooks invoice and committing the transaction to Avalara when the invoice is paid.
If you haven't already, pay the setup fee to receive your AvaTax for FreshBooks portal credentials. The portal (our integration) is how you'll connect FreshBooks to Avalara. If you have any questions, please email us at avataxforfreshbooks@taxiom.com.
Two ways to learn the integration
Take the short walkthrough, or scroll down to the written guide for step-by-step detail on every feature.
Prefer reading? Skip to the written guide ↓
Prefer to have us walk you through this on a live call? Add our Guided Setup add-on ($299) — two calls with our team, up to 45 minutes each. Add Guided Setup — $299
Jump to a section:
1. Install & Connect FreshBooks 2. Configure Your Ship-From Address 3. Your First Tax Calculation 4. Estimates 5. When Transactions Commit to Avalara 6. Credit Notes & Refunds 7. Item Tax Code Mapping 8. Exemptions & Customer Codes 9. Multiple Ship-From Locations 10. Recurring Invoices & Templates 11. Validating Customer Addresses 12. Overriding Avalara's Tax Calculation 13. Transactions Log & Errors Log 14. Self-Serve Admin & Receipts 15. Frequently Asked Questions 16. Troubleshooting & SupportThe integration is built around FreshBooks Invoices and extends to Estimates, Credit Notes, and Recurring Templates. Every time you create or update one of these in FreshBooks, the integration calculates tax through Avalara (or, for estimates, calculates without posting to filings) and writes the result back onto each line. The pattern is:
Once you understand that pattern, everything else in this guide is configuration and edge cases.
Before you begin, you'll need:
Sign in to avataxforfreshbooks.taxiom.com with the credentials you received. If you haven't set your password yet, use the link from the welcome email to set one.
From the dashboard, click Connect FreshBooks. You'll be redirected to FreshBooks to authorize the app. Review the scopes and approve. You'll land back on the integration portal once the install completes.
In the sidebar, click Avalara Credentials. Enter your Account ID, License Key, and Company Code, choose Production or Sandbox, and click Save. The portal validates the credentials against Avalara and confirms when successful.
Avalara allows only one active license key per account at a time. If you rotate the key in Avalara, any other system using the old key will need to be reconnected.
Avalara needs to know where you're shipping from to calculate origin-based tax correctly. The integration uses the following lookup order:
Tax calculations cannot run without a complete ship-from address — Avalara needs an origin to determine which jurisdiction's rates to apply. If you ship from multiple warehouses, see Section 9.
An incomplete ship-from address (missing state, ZIP, or country) is the #1 cause of "tax did not calculate" errors. Always verify the business address in FreshBooks before sending invoices.
Once connected, tax calculation is fully automatic. The flow:
The whole round trip usually takes a few seconds. Refresh the invoice in FreshBooks and you'll see the tax populated on each line.
Tax calculation not what you expected?
If tax calculation didn't work, check the client's shipping address — that's usually the cause. Avalara requires at minimum City, State, ZIP, and Country. You'll see an error in the Transactions log if the integration ran into an issue.
Your Avalara settings dictate the tax that comes back; the integration just sends over the transaction. If the amount looks off, check three things – which states you have turned on for tax calculation (Nexus) in AvaTax, your Item-to-Avalara-tax-code mapping, and whether you have an exemption for the customer in Avalara.
Avalara controls the tax assessment; this integration just connects FreshBooks to Avalara. See Section 15 — Frequently Asked Questions for a deeper answer.
The integration uses the client's shipping address (the s_* fields on the FreshBooks client record). If no shipping address is set, it falls back to the primary/billing address (the p_* fields). This matches FreshBooks' own behavior on invoices.
Recommended: discount the line item price as you enter it, rather than using the discount field at the end of the invoice. If you are giving a customer 10% off a $500 item, enter the line at $450. Tax is then calculated directly on the discounted line price — exactly what the customer pays — and the Avalara transaction mirrors your FreshBooks invoice line for line, with no distributed amounts to reconcile.
If you do use FreshBooks' invoice-level discount field, the integration still handles it: the discount amount is sent to Avalara at the document level and spread proportionally across the lines, per Avalara's discount handling rules, on both invoices and credit notes. Tax is still calculated on the after-discount total, but because the discount is distributed across lines rather than tied to a specific one, the per-line amounts in Avalara will not match the line prices shown in FreshBooks, and per-line rounding can produce a one-cent difference from FreshBooks' displayed tax. For the cleanest records, build the discount into the line item price.
The integration calculates tax on FreshBooks Estimates the same way it does on invoices — webhook fires, ship-to address resolves, Avalara returns the tax, and the rate is written to each line. The buyer who receives the estimate sees the full quoted price including tax.
Estimates never post a billing-eligible transaction to Avalara. Under the hood, estimates are calculated as Avalara SalesOrders — Avalara's purpose-built "non-filing" transaction type. They never count toward your liability reports and never appear in your filings. The Avalara transaction document code uses an EST- prefix (e.g. EST-12345) so it's easy to distinguish from real invoices.
FreshBooks lets you convert an accepted estimate into an invoice with one click. When that happens:
invoice.create webhook with the new invoice's estimateid field set to the original estimate.EST- SalesOrder in Avalara so there's no orphan record.The tax amount on the converted invoice is freshly calculated, not copied from the estimate. So if the customer's address, item tax codes, or jurisdictional rates changed between estimate-issued and invoice-issued, the invoice will reflect the current state — not the stale estimate state.
If you delete an estimate in FreshBooks (declined, expired, or just cleanup), the integration voids the matching EST- SalesOrder in Avalara automatically.
Tax calculation is one step; committing the transaction is what makes it count toward your Avalara filing reports. Here's how the integration handles it:
The default behavior above can be changed from the Taxiom portal under Sync Settings. The three options are:
The Avalara document code is the FreshBooks invoice ID. Open the invoice in FreshBooks and the ID is the last segment of the URL (for example OdQg3j-1234567 → document code 1234567). Use it in the Avalara Transactions search to find the matching record. Estimates are prefixed with EST- and credit notes with CN-.
If you use cash-basis tax accounting, commit-on-paid is exactly what you want. If your accountant uses accrual-basis recognition and you want commits to happen on invoice send instead, email avataxforfreshbooks@taxiom.com — we can adjust this for your portal.
When you issue a credit note in FreshBooks to refund a paid invoice, the integration posts a matching ReturnInvoice to Avalara so your filings net out correctly. Without this, your filings would show overstated tax until you manually corrected them.
credit_note.create. The integration looks up the original invoice's Avalara record.CN-{credit_note_id}, referencing the original.If the original invoice never made it to Avalara (e.g., calculation failed at the time, or it pre-dated the integration), the credit note can't link back to a parent transaction. In that case the integration:
You can resolve this by either creating the matching ReturnInvoice manually in Avalara, or leaving the refund out of Avalara if the original sale was never recorded there.
The integration listens for credit_note.delete and voids the matching CN- ReturnInvoice in Avalara automatically. If the ReturnInvoice was already committed to a closed filing period, it's marked as DocDeleted instead.
Avalara assigns different tax rates based on what's being sold. By default, every line item is treated as tangible personal property (code P0000000). For products that have a different treatment (services, software, food, etc.), map your FreshBooks Items to the right Avalara tax code in the portal.
From the portal, go to Item Tax Code Mapping. The page lists all the Items you've defined in FreshBooks (under Settings → Items & Services). Next to each Item, choose the Avalara tax code that best fits.
| Tax Code | Description | When to use |
|---|---|---|
P0000000 | General Tangible Personal Property | Default for unmapped items; physical goods with no special rules |
SW054000 | Software as a Service (SaaS) | Cloud-hosted software with no download |
SW052000 | Pre-written software, electronically delivered | Downloadable software |
SP000000 | Services (general) | Generic professional services |
FR020100 | Shipping - taxable | Shipping line items where shipping is taxable |
NT | Non-taxable | Items that are never taxable |
If you don't map an item, the integration uses Avalara's general tangible personal property code (P0000000). For most generic physical-goods sellers this is fine. For services or software, mapping is strongly recommended.
You can browse the full Avalara tax code catalog at taxcode.avatax.avalara.com.
You have two ways to handle tax-exempt customers. The first method is strongly recommended because it lets Avalara verify the exemption certificate at calculation time. The second is a manual override — use it only when the first method isn't an option.
The integration automatically passes the FreshBooks client's ID to Avalara as the customer code on every transaction. That means if you upload exemption certificates in Avalara against that same customer code, Avalara's tax engine will check the certificate's validity on every calculation and apply the exemption automatically — only when the certificate is current and applicable to the jurisdiction.
The flow:
This is the better path because Avalara owns the certificate validation — it tracks expirations, jurisdictional applicability, and produces an audit trail that holds up under exam.
If you have a high volume of certificates to manage (uploads, expirations, multi-jurisdiction tracking, customer self-service), Avalara's full Exemption Certificate Management product or ExemptHQ from Taxiom add purpose-built tooling on top of the same matching mechanism.
If you don't have certificate management set up in Avalara yet, or you need a quick manual override, flag the FreshBooks client as exempt in the portal and assign an entity use code (Avalara's standard exemption categories: A = Federal government, B = State/local government, C = Tribal government, D = Foreign diplomat, E = Charitable, F = Religious/educational, G = Resale, etc.). Once flagged, every invoice for that client will be calculated as exempt.
Why this is the fallback, not the recommended path: Setting an entity use code tells Avalara "trust me, this customer is exempt" — Avalara will mark the transaction as exempt without ever checking whether a valid certificate is actually on file. That's faster to set up, but it leaves you exposed in an audit if you don't have the backing documentation. Whenever possible, upload the actual certificate in Avalara (Method 1) and let the tax engine do the verification.
If you ship from more than one location, you can register each warehouse in the portal's Ship-From Locations page and route specific clients or items to specific origins. Avalara uses the ship-from address to determine origin-based tax in states where that matters.
In the portal, go to Ship-From Locations, then add each location with a code (e.g., TX01), name, and full address. If no location is selected for a particular invoice, the default ship-from address from FreshBooks (or the portal's Company Settings fallback) is used.
FreshBooks Recurring Templates define a schedule that generates new invoices on a recurring cadence (weekly, monthly, annually). The integration handles both the template itself and the invoices it generates — differently for each.
Each time the schedule fires, FreshBooks creates a brand new invoice. That invoice fires invoice.create and runs through the standard tax flow:
If you change the line items, price, or client on the recurring template, future generated invoices will reflect those changes and the integration will recalculate tax against the new state.
The integration also listens for recurring.create and recurring.update — events that fire when you create or edit the template itself, not when an invoice generates from it. We never calculate tax on the template directly (it's a schedule, not a document), but we do check the linked client's ship-to address.
If the client is missing any of city, state, ZIP, or country, the integration writes an entry to the Errors Logs page and emails you a warning. This catches the problem before the schedule fires and starts generating a string of tax-less invoices. Common scenario:
For subscription businesses, make sure the customer's billing address matches the shipping address — or that the shipping address is correct on every renewal. A stale shipping address is the #1 cause of "we moved but tax didn't change" issues.
Avalara's tax accuracy depends entirely on the quality of the address you pass it. A wrong ZIP code can mean a wrong rate. Here's how to keep addresses clean:
78704-5301) is even better — Avalara routes to the right special district based on the +4 suffix.A1A 1A1.If you have a large list of FreshBooks clients with addresses to clean up — or you want a one-time scrub before going live — we recommend Validate and Fix Addresses in Excel. Export your client addresses from FreshBooks, run them through the tool to catch missing ZIPs, wrong states, and unverifiable street numbers, then re-import the corrected addresses back into FreshBooks. This is separate from the AvaTax for FreshBooks integration and is a one-time data-cleanup step, not something the integration calls into.
The integration logs a warning when it detects an incomplete address, but it will still attempt calculation using whatever it has. Bad addresses lead to wrong tax — and wrong tax leads to filing problems.
In rare cases, you may need to override Avalara's calculation — for example, when re-issuing an old invoice for a closed tax period, or when you've already paid tax on a transaction outside the system.
FreshBooks lets you manually edit the taxName1 / taxAmount1 fields on a line directly after the integration writes them. However: any subsequent update to the invoice will trigger a recalculation that overwrites your manual edit.
For permanent overrides, email avataxforfreshbooks@taxiom.com. We can configure your portal to skip calculation for specific invoices, specific date ranges, or specific clients.
Self-serve per-invoice override: open Invoice Tax Overrides in the portal sidebar. Enter the FreshBooks invoice ID (visible in the invoice URL, e.g. my.freshbooks.com/.../invoices/176935), the override tax dollar amount, and an optional reason note. On the next sync of that invoice the integration sends taxOverride { type: TaxAmount } to Avalara so the supplied amount becomes the recorded tax. Avalara still requires active nexus in the destination jurisdiction or the override is rejected with TaxOverrideError. Removing the row on that page restores Avalara’s calculated value on the next sync.
The portal includes a Transactions page that shows every interaction between FreshBooks, the integration, and Avalara. For each invoice you can see:
The full audit trail for failures lives in Errors Logs in the portal. Every failed calculation logs the exception type, message, FreshBooks invoice ID, and timestamp.
The most common error categories:
The Account Settings page in the portal sidebar is where you manage your account details and find your billing receipts.
Three things — and all three live in your Avalara account, not in this integration:
The integration's job is to send the right transaction details to Avalara — what's being sold, where it's shipping to, who the buyer is. Avalara then applies all three rules above and tells us the tax amount. If you're seeing $0 tax when you expected a charge (or a tax amount you didn't expect), the answer is almost always in those three Avalara settings, not in the integration.
FreshBooks calculates the invoice's total tax by summing each line's tax. The integration writes a tax rate onto each line (taxName1 / taxAmount1), and FreshBooks rolls those line-level taxes into the invoice total automatically. You'll see the per-line tax on each line and the sum at the bottom of the invoice.
A few seconds for the typical case. The clock starts when FreshBooks fires the invoice webhook and ends when the tax is written back to each line. If you don't see the tax after 30 seconds, check the Transactions or Errors log in the portal.
This happens if the same invoice gets re-sent to Avalara. The integration uses the FreshBooks invoice ID as the document code, so duplicates are usually safe to ignore. If you intentionally re-created an invoice in FreshBooks (different invoice number, same content), Avalara will treat it as a new transaction.
Yes — the integration listens for FreshBooks invoice.delete events and voids the matching Avalara transaction automatically. If the transaction was already committed and locked in a closed filing period, it's marked as DocDeleted in Avalara instead.
Yes. The integration writes the value of taxName1 on each line. By default this is "Sales Tax"; for VAT-style markets, email avataxforfreshbooks@taxiom.com and we'll change the label on your portal to "VAT", "GST", or whatever fits.
Before an invoice is paid, the integration records the transaction in Avalara as uncommitted so you can see and review it without it counting toward your filings. When the invoice is marked paid in FreshBooks, the integration commits the transaction automatically so it's eligible for reporting and filing.
If something isn't working, here's the order to check:
If you've checked all of the above and tax still isn't calculating, email avataxforfreshbooks@taxiom.com with the FreshBooks invoice ID and a brief description of what you expected vs. what happened. We respond same-day, usually within a couple of hours.