ml-connector
FreshBooksExpensify

FreshBooks and Expensify integration

FreshBooks runs your accounting and invoicing. Expensify runs your expense management and corporate card reconciliation. Connecting the two keeps your approved employee expenses in sync with your books. Expense reports approved in Expensify automatically become bills and expense records in FreshBooks, mapped to the right vendors, accounts, and cost codes. No more exporting reports and manually re-entering them into accounting.

How FreshBooks works

FreshBooks exposes invoices, bills, expenses, payments, vendors, chart of accounts, items, and categories through OAuth 2.0 REST APIs. Authentication is user-delegated, so you authorize via a user login at https://auth.freshbooks.com/oauth/authorize and exchange the code for a refresh token tied to that user. The API sends webhooks for invoices, bills, payments, expenses, and other financial events to a registered endpoint, though delivery is not real-time and may range from seconds to several minutes. Webhook payloads are signed with HMAC-SHA256 and include object_id, account_id, and event metadata.

How Expensify works

Expensify exposes expense reports, individual expenses, employees, policies, and corporate card transactions through a polling-only REST API. Authentication uses API key pairs (partnerUserID and partnerUserSecret) passed inline with every request to https://integrations.expensify.com/Integration-Server/ExpensifyIntegrations. Expensify has no webhooks, so data must be pulled via scheduled requests with date-range or status filters. There is no sandbox environment; all calls run against production. Expense categories have GL account codes as properties, and tags function as accounting dimensions like project, class, or cost center.

What moves between them

The flow runs from Expensify into FreshBooks. ml-connector polls Expensify for approved expense reports on a schedule you define (daily, after payroll, after report approval), extracts the expenses and corporate card transactions, maps Expensify expense categories to FreshBooks chart of accounts and vendors, and writes them into FreshBooks as bills and expense records. Employee names and cost center tags become bill vendor names and expense category references. Approved status is tracked so only finalized reports are synced, and duplicate reports are skipped via idempotency keys.

How ml-connector handles it

ml-connector stores both credential sets encrypted. FreshBooks uses OAuth 2.0 user-delegation, so a user authorizes once and ml-connector uses the refresh token to obtain new access tokens as needed; Expensify uses API key pairs passed directly with each request. ml-connector polls Expensify on your schedule because it has no webhooks, and it listens to FreshBooks webhooks when available for real-time updates to bills and payments. Before writing an expense into FreshBooks, ml-connector validates that the expense category maps to an existing GL account code and that the employee or cost center reference exists as a bill vendor or expense category in FreshBooks. If a mapped reference does not exist, the record is queued for manual reconciliation with an audit note explaining why. Expensify has no sandbox, so all testing runs against production using test reports marked with a prefix you supply. Every record carries an idempotency key to prevent duplicate bills if a sync job retries.

A real-world example

A mid-sized services firm runs FreshBooks for accounting and Expensify for employee expense management across remote teams. Before the integration, the accounting team received a spreadsheet of approved expenses from Expensify each week, cross-checked it against corporate card statements, and manually entered the expenses into FreshBooks as bills and items. This process took 3 to 4 hours per week and introduced keying errors that showed up in month-end reconciliation. With FreshBooks and Expensify connected, approved reports flow automatically into FreshBooks daily, mapped to the right cost codes and vendors. The manual entry step is gone, and the accounting team spends that time on analysis instead.

What you can do

  • Sync approved Expensify expense reports into FreshBooks as bills, expenses, and vendor records, mapped to the correct GL accounts and cost centers.
  • Authenticate FreshBooks via OAuth 2.0 user delegation and Expensify via API key pairs, bridging the two authentication models.
  • Poll Expensify on a schedule that matches your approval workflow, preventing duplicate syncs via idempotency keys.
  • Map Expensify expense categories, tags, and employee names to FreshBooks chart of accounts, expense categories, and bill vendors.
  • Track every record with full audit trails, queue mismatched references for manual review, and replay failed syncs without data loss.

Questions

How does ml-connector handle FreshBooks OAuth 2.0 user delegation?
FreshBooks requires user-delegated OAuth, so you authorize once via a login flow at https://auth.freshbooks.com/oauth/authorize. ml-connector stores the refresh token encrypted and uses it to obtain new access tokens as they expire. The user who authorizes does not need to stay involved in subsequent syncs; the token refreshes automatically.
Why does ml-connector poll Expensify instead of waiting for webhooks?
Expensify has no webhook system for real-time push notifications. ml-connector polls the API on a schedule you control (daily, weekly, after payroll, etc.) to fetch approved expense reports and transactions. This cadence is tied to when you need expenses in the books, not to when transactions occur.
What happens if an expense category or cost center reference does not exist in FreshBooks?
ml-connector validates all mapped references before writing. If a category, vendor, or cost center does not exist in FreshBooks, the record is queued with an audit note explaining the mismatch, and you can fix the mapping or create the missing reference, then replay the sync. No bad data enters your books.

Related integrations

Connect FreshBooks and Expensify

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

Get started