ml-connector
FreshBooksHubSpot

FreshBooks and HubSpot integration

FreshBooks handles your accounting - invoices, clients, payments, and expenses. HubSpot handles your customer relationships - deals, contacts, and order data. Connecting them lets your sales team see the customer's invoice history and payment status without leaving HubSpot, and keeps client and company records aligned across both systems. ml-connector bridges the auth differences and keeps the two in sync on a schedule that matches your business.

How FreshBooks works

FreshBooks is a cloud accounting and invoicing platform that exposes clients, invoices, bills, bill vendors, payments, expenses, and chart of accounts through REST JSON APIs. Clients use OAuth 2.0 Authorization Code grant (user-delegated, not Client Credentials) to authorize access, and each token is scoped per resource. FreshBooks publishes webhook events for create, update, and delete actions on invoices, payments, clients, bills, bill vendors, expenses, items, and other accounting objects, delivered as application/x-www-form-urlencoded payloads signed with HMAC-SHA256. Webhook delivery can range from seconds to several minutes, and non-2xx responses or timeouts trigger retries until the callback is disabled after persistent failures. FreshBooks uses distinct API path patterns: accounting data lives under /accounting/account/<accountId>, while chart of accounts uses /accounting/businesses/<business_uuid>.

How HubSpot works

HubSpot is a CRM platform offering REST APIs for contacts, companies, deals, invoices, line items, products, payments, orders, and tickets. Server-to-server integrations authenticate via Private App Access Token (Bearer token, format pat-na1-) issued per hub, along with a numeric hub_id portal identifier. HubSpot supports webhooks via Public App registration (separate from the Private App token) with signature verification, or polling via list and search endpoints capped at 10,000 records (use Lists API for larger datasets). Batch operations are capped at 100 records per request. Rate limits vary by tier from 100 to 190 requests per 10 seconds. Invoices are in public beta write support as of January 2026, and commerce objects require associations to contacts and line items to be valid.

What moves between them

Data flows primarily from FreshBooks into HubSpot. Client records from FreshBooks sync to HubSpot contacts, and company records (bill vendors and clients with company attributes) sync to HubSpot companies. FreshBooks invoices map to HubSpot invoice objects, and payments map to HubSpot payment objects, each associated to the corresponding contact and company. The sync is triggered by FreshBooks webhook events for invoice.create, invoice.update, payment.create, payment.update, client.create, and client.update; ml-connector receives these events, translates them to HubSpot semantics, and writes or updates the corresponding HubSpot records. Reference data such as chart of accounts and item categories are readable from FreshBooks but not pushed to HubSpot unless mapped to custom properties on contacts or companies.

How ml-connector handles it

ml-connector stores the FreshBooks OAuth 2.0 credentials encrypted and refreshes the authorization token when a call returns 401, using the user-delegated token grant to request a fresh access token. It validates the FreshBooks webhook signature using HMAC-SHA256 on each incoming event and discards unsigned or invalid payloads. On the HubSpot side, ml-connector uses the Private App Access Token as a Bearer token on every REST call, and it batches writes (up to 100 records per request) when syncing multiple clients or invoices from a large FreshBooks account. When a FreshBooks client maps to an existing HubSpot contact, the sync updates the contact's properties and company association rather than creating a duplicate. Invoices created in FreshBooks are written to HubSpot as invoice objects with line items derived from the FreshBooks line data; however, HubSpot invoice write support is in public beta as of January 2026, so ml-connector tracks that API state and warns if the feature is disabled in the target hub. If a contact or company does not exist in HubSpot yet, ml-connector creates it before writing an invoice or payment. FreshBooks webhook timeouts and failures are retried by FreshBooks itself, not by ml-connector, since FreshBooks controls the callback persistence.

A real-world example

A B2B service firm uses FreshBooks to manage client invoicing and payment tracking, and HubSpot to manage their sales pipeline and customer data. Before the integration, the sales team had to check FreshBooks separately to see whether a prospect had paid their last invoice or how much they owed in outstanding amounts. Account executives spent time copying client data between systems, and invoices created in FreshBooks were never visible in HubSpot's deal or contact records. With FreshBooks and HubSpot connected, each time an invoice is sent or a payment is received in FreshBooks, the change appears automatically in the contact and deal records in HubSpot. The sales team now sees the customer's invoice history and payment status without leaving HubSpot, reducing manual lookups and keeping customer data in sync.

What you can do

  • Sync FreshBooks clients to HubSpot contacts and companies, mapping each FreshBooks client to a HubSpot contact with company association.
  • Mirror FreshBooks invoices and payments into HubSpot invoice and payment objects, associating them to the correct contact and company.
  • Validate incoming FreshBooks webhook signatures using HMAC-SHA256 and ignore unsigned or tampered events.
  • Refresh the FreshBooks OAuth 2.0 user-delegated token automatically when it expires, without requiring re-authorization.
  • Batch write up to 100 FreshBooks clients or invoices per request to HubSpot, respecting HubSpot's rate limits and batch operation caps.

Questions

Does ml-connector require setting up a FreshBooks webhook, or does it poll instead?
ml-connector relies on FreshBooks webhooks. You register ml-connector's endpoint URL as a webhook callback in your FreshBooks settings, and FreshBooks pushes events (invoice.create, invoice.update, payment.create, client.update, etc.) to that URL. ml-connector validates each webhook signature using HMAC-SHA256 and processes the event. FreshBooks handles retry logic for failed deliveries, not ml-connector.
Why does ml-connector need the FreshBooks user's OAuth credentials instead of Client Credentials?
FreshBooks does not support Client Credentials OAuth flow - only Authorization Code grant (user-delegated). ml-connector stores the authorized user's refresh token encrypted and uses it to obtain new access tokens when the current one expires. This is a FreshBooks design constraint, not a limitation of ml-connector.
What happens if HubSpot invoice write support is disabled or in beta?
ml-connector checks the HubSpot API status and logs a warning if invoice write is unavailable. The sync continues for contacts, companies, and payments, but invoice records are not written until HubSpot enables full invoice write support. Once available, simply re-run the sync to backfill missing invoices.

Related integrations

Connect FreshBooks and HubSpot

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

Get started