FreshBooks lets you create an OAuth app directly inside the app, with no vendor approval needed. Credentials are available immediately.
Before you start
You'll need:
A FreshBooks account that can reach the Developer page
Owner or Admin access to your Caddi organization
Step 1: Create the app in FreshBooks
FreshBooks redirect URIs must use HTTPS and must not contain query-string parameters. Multiple URIs are allowed, one per line.
Sign in to FreshBooks and go to my.freshbooks.com/#/developer.
Click Create New App.
Application Name — this must be globally unique across FreshBooks and is shown to your users on their integrations page. Something like
Caddi – Acme Lawworks well.Application Type — select the web application type.
Redirect URI — enter
https://app.trycaddi.com/oauth-callback.Select the scopes your loops need (see below).
Save, then reopen the app — the Client ID and Secret appear at the bottom of the app's detail panel.
Step 2: Choose scopes
FreshBooks scopes take the form user:<object>:<action>, where the action is read or write. write covers create, edit, archive, and delete.
Select the read and write scope for each object your loops touch — for example
user:invoices:read,user:invoices:write,user:clients:read,user:clients:write,user:expenses:read,user:expenses:write,user:payments:read,user:payments:write,user:time_entries:read,user:time_entries:write.user:profile:readis added to every new app automatically and is needed for basic calls — leave it selected.Leave
user:teams:readanduser:teams:writeoff unless a loop manages team members. That's the closest thing FreshBooks has to user administration.
Scopes cannot be added to an existing token. If you widen the app's scopes later, users have to disconnect and reconnect before the new access applies.
Step 3: Configure FreshBooks in Caddi
This step must be completed by a Caddi organization owner or admin.
In Caddi, open Integrations in the left sidebar, then click the Integration Setup tab at the top of the page. This tab is only visible to organization owners and admins.
Find FreshBooks in the list and click Configure.
Enter the following values:
Client ID — from your FreshBooks app
Client Secret — from the same app
Redirect URI — enter
https://app.trycaddi.com/oauth-callback. This must match the value on the FreshBooks app exactly. FreshBooks requires it on every token call, which is why Caddi collects it explicitly rather than assuming it.Scopes — space-separated list matching what you selected on the app. Leave blank to use Caddi's defaults.
Click Save Configuration. Caddi validates the credentials immediately — if something is wrong you'll see an error right away, and nothing is stored until validation passes.
Step 4: Connect your account
Go back to the My Connections tab and find FreshBooks.
Click Connect + and sign in to FreshBooks.
Approve the request. You'll be returned to Caddi with the connection active.
How the connection behaves
Each user connects their own FreshBooks account. Tokens are tied to the authorizing user and their business. If that user is removed from the business, the connection goes with them.
Refresh tokens do not expire but are strictly single-use, and FreshBooks allows only one active refresh token per user per application. Caddi handles this, but it means the same FreshBooks user shouldn't be connected to two separate Caddi organizations through the same app.
A custom connection replaces the standard one. Members of your organization will only see the option to connect through your app.
Revoking access. Delete the app in the FreshBooks Developer page, or have the user revoke it from their FreshBooks integrations page.
Troubleshooting
Token requests fail even though the credentials are right
The Redirect URI field in Caddi is empty or doesn't match the app. FreshBooks requires redirect_uri on the token exchange and on every refresh, so this is the most common FreshBooks failure.
The app won't save because the name is taken
FreshBooks application names are globally unique across all FreshBooks accounts. Add your firm name to make it distinctive.
The connection works but a loop can't reach a record type
That object's scope wasn't selected on the app. Add it, then have the user disconnect and reconnect — scopes can't be added to an existing token.
Connections drop when two things sync at once
FreshBooks allows only one active refresh token per user per app. Check whether the same FreshBooks login is connected in more than one place.
Still stuck? Contact Caddi support with the exact error message you're seeing and the time it occurred.
Automation ideas
Law Firms
Time entry → client invoice
Caddi assembles the period's time entries and expenses by client and drafts the FreshBooks invoice for review.
Payment received → matter and ledger update
When a FreshBooks payment lands, Caddi records it against the matter and updates the client ledger.
RIAs
Fee schedule → recurring invoices
Caddi generates the period's advisory fee invoices from your fee schedule and portfolio data, ready for approval.
Expense receipt → categorized entry
Caddi reads submitted receipts, categorizes them, and creates the FreshBooks expense records.
