ml-connector
FreshBooksTaxJar

FreshBooks and TaxJar integration

FreshBooks stores every invoice and expense your business creates. TaxJar calculates the correct sales tax on those transactions and tracks your tax filing obligations across states. Connecting them keeps your tax compliance current without manual re-entry. When you issue an invoice in FreshBooks, ml-connector posts it to TaxJar for tax calculation. When TaxJar finishes the calculation, the tax amount flows back into FreshBooks as a journal entry so your books are always accurate.

How FreshBooks works

FreshBooks exposes invoices, expenses, bills, bill_payments, payments, journal_entries, and clients through a REST API at https://api.freshbooks.com. Authentication uses OAuth 2.0 Authorization Code grant, which is user-delegated (not Client Credentials). FreshBooks publishes webhooks via POST to a customer-supplied endpoint for invoice, expense, payment, bill, and client events, with HMAC-SHA256 signatures. Webhook delivery is not real-time and can range from seconds to several minutes, with a 10-second timeout per attempt. FreshBooks also supports granular OAuth scopes per resource, so the integration can request only the permissions needed.

How TaxJar works

TaxJar exposes tax calculations, transaction reporting, nexus tracking, and address validation through a REST API at https://api.taxjar.com/v2/. Authentication uses token-based API Key headers (Bearer or Token formats). TaxJar does not support OAuth2 or webhooks; integration is poll-based or merchant-initiated via real-time POST calls to the /taxes endpoint at checkout or POST/PUT to report completed transactions. The Sandbox API is stateless and validates request/response format only, available on Professional plan and higher. All merchant API tokens are generated from the Account > API Access section in the TaxJar app.

What moves between them

FreshBooks invoices and expenses flow into TaxJar for tax calculation. ml-connector receives FreshBooks webhooks when invoices or expenses are created or updated, transforms them into TaxJar transaction payloads with the correct tax category and customer address, and POSTs them to TaxJar's /transactions/orders endpoint. TaxJar calculates the applicable sales tax amount and returns it in the response. ml-connector then posts that tax amount back into FreshBooks as a journal entry allocated to the correct expense or revenue account. Reference data such as tax categories and nexus regions is cached on startup and refreshed periodically. The sync is event-driven from FreshBooks and completes within the FreshBooks webhook timeout window.

How ml-connector handles it

ml-connector stores the FreshBooks OAuth credentials (refresh token) and TaxJar API token encrypted. It registers a webhook endpoint with FreshBooks to receive notifications when invoices, expenses, and payments are created or updated. On each webhook, ml-connector validates the HMAC-SHA256 signature against the X-FreshBooks-Hmac-SHA256 header, then transforms the FreshBooks transaction into a TaxJar request. For invoices, it extracts the client address and line items; for expenses, it uses the customer address if available or a default. TaxJar requires a valid address and tax category on each transaction, so ml-connector maps FreshBooks item types to TaxJar categories or uses a fallback. The transaction is POSTed to TaxJar's /transactions/orders endpoint. If TaxJar returns 422 (exists), ml-connector retries with PUT instead. The calculated tax is returned in the response and posted back to FreshBooks as a journal entry on the tax allocation account. TaxJar API token expiry is non-blocking since tokens do not expire; however, if a token is revoked, failed calls surface the error in the audit log. FreshBooks webhook delivery can range from seconds to minutes, so tax calculations lag behind invoice creation. FreshBooks status fields are read-only, so ml-connector never updates invoice or payment status directly.

A real-world example

A small e-commerce business uses FreshBooks to manage invoicing and expense tracking. They sell across the United States and have sales tax nexus in six states. Before the integration, the accounting team exported invoices from FreshBooks daily, manually categorized each one for tax purposes, uploaded them to TaxJar, and copied the tax amount back into FreshBooks by hand. The process took 30 minutes per day and introduced typos. With FreshBooks and TaxJar connected via ml-connector, every invoice and expense is automatically posted to TaxJar within minutes of creation, tax amounts are calculated in real-time, and the tax journals post back into FreshBooks without human touch. The team now focuses on customer service instead of data re-entry.

What you can do

  • Receive FreshBooks invoice and expense webhooks and post completed transactions to TaxJar for real-time tax calculation.
  • Retrieve calculated sales tax amounts from TaxJar and post them back into FreshBooks as journal entries on the tax account.
  • Map FreshBooks items and line items to TaxJar tax categories and handle address validation for customer location.
  • Validate FreshBooks webhook signatures with HMAC-SHA256 and refresh FreshBooks OAuth tokens when needed.
  • Track nexus regions in TaxJar and cache tax rates and categories on startup to minimize API calls.

Questions

Which direction does data move between FreshBooks and TaxJar?
The primary flow is FreshBooks to TaxJar. Invoices and expenses from FreshBooks are posted to TaxJar for tax calculation. The calculated tax amount flows back into FreshBooks as a journal entry. FreshBooks status fields are read-only in FreshBooks, so ml-connector never modifies invoice or payment status.
How does ml-connector handle FreshBooks OAuth and TaxJar tokens?
ml-connector stores the FreshBooks OAuth refresh token encrypted and uses it to obtain new access tokens when needed. TaxJar authentication uses a static API token stored encrypted. Both credentials are transmitted over HTTPS and never logged or exposed in audit trails.
What happens if TaxJar returns an error or the webhook times out?
If a FreshBooks webhook times out (longer than 10 seconds), FreshBooks retries the delivery. If TaxJar returns an error such as an invalid address or missing tax category, ml-connector logs the failure in the audit trail and skips the tax journal entry. The original FreshBooks transaction remains intact, and the integration operator can review the error and resubmit.

Related integrations

Connect FreshBooks and TaxJar

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started