ml-connector
FreshBooksWise

FreshBooks and Wise integration

FreshBooks tracks your invoices, expenses, and cash flow. Wise executes the actual payments and manages multi-currency movement. Connecting them keeps your accounting records aligned with the transfers you have actually sent. When an invoice payment is recorded in FreshBooks, ml-connector can initiate the corresponding transfer in Wise; when a transfer completes, it posts back to FreshBooks as a reconciliation record. This eliminates the need to manually sync payment execution across two separate systems and reduces reconciliation errors.

How FreshBooks works

FreshBooks exposes invoices, payments, bill vendors, bills, clients, chart of accounts, expenses, and journal entries through REST APIs at https://api.freshbooks.com, split across accounting and time-tracking namespaces. Authentication is OAuth 2.0 with user delegation (not client credentials), and scopes are granular per resource. FreshBooks supports webhooks for push events including invoice.create, invoice.update, payment.create, payment.update, bill.create, bill.update, and many others, delivered via POST to a customer-supplied endpoint with HMAC-SHA256 signature verification. Webhook delivery ranges from seconds to several minutes and times out after 10 seconds per attempt. Status fields on invoices and payments are read-only and computed by the system.

How Wise works

Wise exposes profiles, balances, recipients, transfers, and activity through REST APIs at https://api.wise.com, with both production and sandbox environments. Authentication uses OAuth 2.0 (authorization_code or client_credentials grants with 12-hour token expiry and refresh tokens) or a long-lived personal API token. Wise supports webhooks for transfersstate-change, transferspayout-failure, balancesupdate, and other events, with RSA-SHA256 signature verification via X-Signature-SHA256 header. Transfer creation follows a 4-step sequence: quote, recipient, transfer order, and funding. Recipients are immutable, and quotes expire, so both must be recreated if conditions change. Rate limits are 100 requests per second or 1000 per minute for partner OAuth, and balance-to-balance transfers do not fire state-change webhooks.

What moves between them

Payments flow from FreshBooks into Wise. When a FreshBooks payment is recorded or updated, ml-connector reads the invoice, client, and payment details, maps the FreshBooks client to a Wise recipient based on stored recipient IDs, generates a fresh quote in Wise for the correct amount and currency pair, creates and funds the transfer, and records the Wise transfer ID back into FreshBooks as a custom field or journal entry for audit. Transfer state changes in Wise (completion, failure) post back to FreshBooks via webhook-triggered reconciliation. The sync is event-driven for Wise updates and polling-based or webhook-based on the FreshBooks side, depending on configuration.

How ml-connector handles it

ml-connector stores both OAuth tokens encrypted and refreshes them when calls return 401. On the FreshBooks side, it receives webhook events for payment creation and update, extracts the client and amount, and looks up the previously mapped Wise recipient ID. On the Wise side, it refreshes the quote to ensure currency rates are current, creates the transfer in the correct profile and currency pair, waits for funding to complete, and tracks transfer state. FreshBooks client IDs are paired with Wise recipient IDs via a mapping table so re-creating recipients does not break sync. Wise rate limits return HTTP 429, so ml-connector backs off and retries. The 4-step transfer sequence (quote, recipient, transfer, fund) is orchestrated atomically so a failure partway through does not leave orphaned records. Every transfer and payment sync carries a full audit trail with timestamps and state transitions.

A real-world example

A mid-sized freelance services firm uses FreshBooks to track invoices and expenses across multiple projects and geographies. Clients pay in their local currencies, and the firm pays freelancers in over a dozen countries. Before the integration, the operations team manually exported FreshBooks payment records, looked up exchange rates, created transfers in Wise, and then logged the Wise tracking numbers back into FreshBooks as notes. With FreshBooks and Wise connected, each new payment in FreshBooks automatically initiates the corresponding Wise transfer with the current exchange rate, and the operations team sees the transfer status in FreshBooks without switching apps. Month-end reconciliation is faster because transfers and payments are linked by audit ID and currency has been locked in at transfer time.

What you can do

  • Map FreshBooks clients to Wise recipients and maintain the mapping across updates and recreates.
  • Trigger Wise transfers from FreshBooks payments, generating fresh quotes with current exchange rates.
  • Execute the full 4-step Wise transfer sequence atomically and record the transfer ID in FreshBooks.
  • Sync Wise transfer state changes back to FreshBooks for payment reconciliation and audit compliance.
  • Handle OAuth 2.0 token refresh, rate limit backoff, and quote expiry with full audit trails on all records.

Questions

How does ml-connector map FreshBooks clients to Wise recipients?
ml-connector maintains a mapping table linking FreshBooks client IDs to Wise recipient IDs. On the first payment from a client, if no recipient exists in Wise, ml-connector creates one with the client's name and saved bank details. For subsequent payments, it looks up the stored recipient ID and reuses it. If a Wise recipient is deleted and recreated, the mapping is updated so transfers continue to route correctly.
What happens if a Wise quote expires or exchange rates change between payment creation and transfer execution?
Wise quotes expire after a short time, so ml-connector generates a fresh quote on every transfer to lock in the current exchange rate at the moment of funding. If the rate has moved significantly, the fresh quote will reflect the new rate, and the payment amount in Wise may differ from the FreshBooks invoice total. The actual funded amount is recorded in FreshBooks so the difference is visible and can be reconciled.
How does ml-connector handle FreshBooks status fields that are read-only?
FreshBooks computes invoice and payment status automatically based on activity, so ml-connector never attempts to write those fields. Instead, it reads status to determine eligibility for transfer (e.g., a payment must be recorded before a transfer is initiated) and logs the status in audit records. Wise transfer completions are logged in FreshBooks as separate reconciliation records, not by updating FreshBooks payment status.

Related integrations

Connect FreshBooks and Wise

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

Get started