Skip to main content
FreshBooks

Overview

Supported resources

Connect setup

FreshBooks uses OAuth 2.0. You need an app registered in the FreshBooks Developer Portal.
1

Create a FreshBooks app

Sign in at my.freshbooks.com/#/developer and click Create an App. Copy the Client ID and Client Secret.
2

Add the redirect URL

In your app’s Redirect URIs list, add:
3

Configure required scopes

Enable the following scopes on your app:
  • user:profile:read
  • user:account:read
  • user:account:write
  • user:clients:read
  • user:clients:write
  • user:invoices:read
  • user:invoices:write
  • user:payments:read
  • user:payments:write
  • user:expenses:read
  • user:expenses:write
  • user:taxes:read
  • user:taxes:write
  • user:billable_items:read
  • user:billable_items:write
  • user:credit_notes:read
  • user:credit_notes:write
  • user:bills:read
  • user:bills:write
  • user:bill_vendors:read
  • user:bill_vendors:write
  • user:bill_payments:read
  • user:bill_payments:write
  • user:journal_entries:read
  • user:journal_entries:write
  • user:projects:read
  • user:projects:write
  • user:teams:read
  • user:reports:read
  • user:estimates:read
4

Connect via the widget

When your end user opens the Connect widget, they will enter the Client ID and Client Secret, then be redirected to FreshBooks to authorize the connection.

Usage

Notes

  • Pass type: "ACCOUNTS_PAYABLE" on invoice and payment create to dispatch to FreshBooks’s /bills/bills and /bill_payments/bill_payments endpoints. For vendor contacts, set is_supplier: true. AR / AP routing is encoded in the URN (urn:freshbooks:invoice:ar:<id> vs urn:freshbooks:invoice:ap:<id>).
  • Canonical DELETE translates to a soft delete (PUT with vis_state: 1) on most resources. project is the exception — it uses a true hard DELETE.
  • Pass canonical status: "SUBMITTED" on invoice create to land it as Sent (the adapter chains an action_mark_as_sent PUT after the initial POST). Omit status to leave it as Draft.
  • address and phone_number ids are discoverable inline on contact.addresses[].id and contact.phone_numbers[].id. Listing them at the top level returns 405 — read them inline from the parent or use GET /address/{urn}.