ml-connector
FreshBooksZuora

FreshBooks and Zuora integration

FreshBooks manages accounting, invoicing, and bill tracking for small businesses. Zuora handles subscription billing, invoicing, and revenue recognition for recurring-revenue models. Connecting the two lets you issue invoices in FreshBooks and have them flow into Zuora's billing system as Accounts and Invoices, keeping both systems synchronized without re-entry. This integration is especially valuable when your accounting and billing operations need to stay in step: invoice totals, payment status, and client records reflect the same truth in both places.

How FreshBooks works

FreshBooks is a cloud accounting platform that exposes clients, invoices, bills, payments, expenses, and chart of accounts through REST APIs. Authentication uses OAuth 2.0 Authorization Code grant with user-delegated credentials, scoped per resource. FreshBooks operates two API namespaces: accounting under /accounting/account/<accountId> and time tracking under /timetracking/business/<businessId>. For real-time notifications, FreshBooks sends webhooks to a customer-supplied endpoint with HMAC-SHA256 signatures on events such as invoice.create, invoice.update, payment.create, and bill.create. Webhook delivery can range from seconds to several minutes, and the platform applies a 10-second timeout per attempt. FreshBooks does not support Client Credentials OAuth, making it user-delegated only, and purchase orders and employees as standalone resources are not available.

How Zuora works

Zuora is a subscription billing and revenue management platform that handles product catalogs, subscriptions, invoices, payments, credit memos, and orders through REST APIs. All requests require OAuth 2.0 Client Credentials with a bearer token, and tokens expire in 1 hour so they must be refreshed periodically. Zuora operates across multiple regions with region-specific base URLs such as rest.zuora.com, rest.apisandbox.zuora.com, and rest.eu.zuora.com, so the correct endpoint must be captured per customer during setup. For notifications, Zuora sends Callout Notifications via HTTPS webhooks to configured endpoints with HMAC-SHA256 signature support and a fixed 25-second timeout. Webhook events fire on invoices, payments (electronic only), subscriptions, and account changes. Rate limits are 50,000 RPM in production and 2,500 RPM in sandbox, with cursor-based pagination capped at 40 records per page on most objects. Some operations like account deletion and large billing runs are asynchronous and return a job ID for polling.

What moves between them

The primary flow moves FreshBooks invoices and payments into Zuora. When an invoice is created or updated in FreshBooks, ml-connector receives the webhook, fetches the full invoice record via the FreshBooks API, maps the client to a Zuora Account or retrieves the existing one, and posts the invoice to Zuora as a new Invoice object. When a payment is created in FreshBooks, it flows into Zuora as a Payment record applied to the corresponding invoice. Reference data such as client information and invoice line items are pulled from FreshBooks on each sync to ensure accuracy. Zuora's response is primarily read-only for billing calculations and revenue recognition, so ml-connector does not write back to FreshBooks from Zuora; data flows one direction from accounting into billing.

How ml-connector handles it

ml-connector bridges the two OAuth models by storing both sets of credentials encrypted. On the FreshBooks side, it accepts the user-delegated token and account ID, and listens for incoming webhook POST requests with HMAC-SHA256 signature validation. FreshBooks webhooks deliver object IDs and account IDs, so ml-connector fetches the full record via the FreshBooks API to extract line items, client data, and payment terms. On the Zuora side, ml-connector exchanges Client Credentials for a bearer token, caches it until expiry, and detects the correct multi-region base URL from customer configuration. Each FreshBooks client is mapped to a Zuora Account by email or external ID; the mapping is stored and reused on subsequent invoice posts. When FreshBooks webhook delivery is slow or disabled, ml-connector can poll the FreshBooks API on a configurable schedule instead. Zuora's rate limits (50,000 RPM production, 2,500 RPM sandbox) are monitored, and HTTP 429 responses trigger exponential backoff and retry. Every record carries a full audit trail, including the original webhook payload, API calls made, and any transformation applied, so failed deliveries can be replayed when the issue is resolved.

A real-world example

A mid-market SaaS company uses FreshBooks to manage client invoicing and accounting for its cloud services business. As it matures, it migrates to Zuora for subscription billing and revenue recognition, which requires handling complex multi-year contracts, subscription amendments, and deferred revenue. Before the integration, the finance team manually copied invoice data from FreshBooks into Zuora every week, a process that introduced typos and timing delays. With FreshBooks and Zuora connected, each invoice created in FreshBooks automatically flows into Zuora within seconds. Clients appear as Accounts, invoice totals and payment terms match exactly, and the revenue recognition engine in Zuora operates on clean, authoritative data from day one. The finance team reclaims hours of manual work per week and gains confidence that both systems are always in sync.

What you can do

  • Post FreshBooks invoices to Zuora as Accounts and Invoice objects, mapped by client email or external ID.
  • Sync FreshBooks payments into Zuora as Payment records applied to the corresponding invoices.
  • Bridge FreshBooks user-delegated OAuth with Zuora Client Credentials, refreshing tokens as needed.
  • Route requests to the correct Zuora region, detect multi-region endpoints, and handle rate limits with exponential backoff.
  • Deliver a complete audit trail of every record, webhook payload, API call, and transformation for troubleshooting and replay on failure.

Questions

How does ml-connector handle the different OAuth models between FreshBooks and Zuora?
FreshBooks uses user-delegated OAuth 2.0, so ml-connector stores the user's authorization token and account ID. Zuora uses Client Credentials, so ml-connector stores the client ID and secret, exchanges them for a bearer token, and caches the token until it expires in 1 hour. Both credential sets are encrypted at rest. When a webhook arrives from FreshBooks, ml-connector validates the HMAC-SHA256 signature with the customer's FreshBooks account; when posting to Zuora, it adds the Zuora bearer token to the Authorization header.
What happens if FreshBooks webhooks are slow or disabled?
FreshBooks webhook delivery can range from seconds to several minutes. If webhooks are disabled or unreliable, ml-connector can poll the FreshBooks API on a configurable schedule to fetch new invoices and payments. Both modes support the same audit trail and error replay, so switching between webhook and polling does not require reconfiguration.
How are FreshBooks clients matched to Zuora Accounts?
ml-connector maps FreshBooks clients to Zuora Accounts by email address or external ID. The first time a client appears in an invoice, ml-connector either creates a new Zuora Account or retrieves the existing one by matching email. Subsequent invoices from the same client reuse the existing Zuora Account, so each client appears once in Zuora even if FreshBooks invoices arrive at different times.

Related integrations

Connect FreshBooks and Zuora

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

Get started