A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The FreshBooks API is how an app or AI agent works with a FreshBooks account: creating and sending an invoice, recording a payment, adding a client, logging an expense, or tracking time on a project. Access is granted through an OAuth 2.0 access token carrying granular scopes, in the form user:invoices:read or user:clients:write, that set which resources a call can read or write. A change can emit an event that FreshBooks delivers to a registered callback, and accounting calls and project or time calls are keyed by two separate identifiers for the same login.
How an app or AI agent connects to FreshBooks determines what it can reach. There is a route for making calls and a route for receiving events, and each is governed by the access token behind it and the permissions that token carries.
The REST API takes and returns JSON at https://api.freshbooks.com, with the Accounting API under /accounting/account/
FreshBooks POSTs an event to a registered callback URI when something changes, using noun.verb events like invoice.create and payment.create. A callback is registered through the events API, then confirmed by returning a verification code, and that code is the secret used to check the HMAC-SHA256 signature on each delivered event.
FreshBooks uses the OAuth 2.0 authorization-code flow. A user authorizes the app at auth.freshbooks.com, the app exchanges the returned code at the token endpoint for a Bearer access token and a refresh token, and the access token is sent on each call. The access token is short-lived; the refresh token lives until used, is single-use, and only one is valid per user per application at a time.
The FreshBooks API is split into areas an agent can act on, like invoices, clients, expenses, estimates, payments, projects, and time entries. Each area has its own methods and its own read and write permission, and a write can record money received or send a document to a client.
Methods for creating, sending, and managing invoices in the Accounting API.
Methods for working with the people and businesses an account bills.
Methods for recording and managing expenses.
Methods for quotes and proposals sent before an invoice.
Methods for recording payments applied to invoices.
Methods for reusable line items and tax rates.
Methods for projects in the Projects API, keyed by business rather than account.
Methods for logged time in the Time Tracking API, keyed by business.
Methods for registering and verifying webhook callbacks.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
InvoicesMethods for creating, sending, and managing invoices in the Accounting API.5 | ||||||
| GET | /accounting/account/ | List invoices on an account, with search, filtering, and paging. | read | user:invoices:read | Current | |
Read-only. Keyed by accountId, the account identifier from the identity endpoint. Acts oninvoice Permission (capability) user:invoices:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | Retrieve a single invoice by id. | read | user:invoices:read | Current | |
Read-only. Acts oninvoice Permission (capability) user:invoices:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Create an invoice for a client. | write | user:invoices:write | Current | |
A core write; can be set to email the invoice to the client. Acts oninvoice Permission (capability) user:invoices:writeVersionAvailable since the API’s base version Webhook event invoice.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /accounting/account/ | Update an invoice, such as its line items, status, or visibility. | write | user:invoices:write | Current | |
Deleting an invoice is done here too, by setting vis_state to 1 (a soft delete) rather than a DELETE call. Acts oninvoice Permission (capability) user:invoices:writeVersionAvailable since the API’s base version Webhook event invoice.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /accounting/account/ | Delete an invoice. | write | user:invoices:write | Current | |
FreshBooks more commonly soft-deletes by updating vis_state to 1 on the PUT call. Acts oninvoice Permission (capability) user:invoices:writeVersionAvailable since the API’s base version Webhook event invoice.deleteRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ClientsMethods for working with the people and businesses an account bills.4 | ||||||
| GET | /accounting/account/ | List clients on an account. | read | user:clients:read | Current | |
Read-only. Clients live under the users path in the Accounting API. Acts onclient Permission (capability) user:clients:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | Retrieve a single client by id. | read | user:clients:read | Current | |
Read-only. Acts onclient Permission (capability) user:clients:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Create a client to bill. | write | user:clients:write | Current | |
A core write. Acts onclient Permission (capability) user:clients:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /accounting/account/ | Update a client, or delete one by setting vis_state to 1. | write | user:clients:write | Current | |
Clients are deleted through this PUT by setting vis_state to 1, not a DELETE call. Acts onclient Permission (capability) user:clients:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ExpensesMethods for recording and managing expenses.4 | ||||||
| GET | /accounting/account/ | List expenses on an account. | read | user:expenses:read | Current | |
Read-only. Acts onexpense Permission (capability) user:expenses:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | Retrieve a single expense by id. | read | user:expenses:read | Current | |
Read-only. Acts onexpense Permission (capability) user:expenses:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Record an expense. | write | user:expenses:write | Current | |
A core write. Acts onexpense Permission (capability) user:expenses:writeVersionAvailable since the API’s base version Webhook event expense.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /accounting/account/ | Update an expense, or delete one by setting vis_state to 1. | write | user:expenses:write | Current | |
Expenses are soft-deleted through this PUT by setting vis_state to 1. Acts onexpense Permission (capability) user:expenses:writeVersionAvailable since the API’s base version Webhook event expense.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
EstimatesMethods for quotes and proposals sent before an invoice.4 | ||||||
| GET | /accounting/account/ | List estimates on an account. | read | user:estimates:read | Current | |
Read-only. Acts onestimate Permission (capability) user:estimates:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | Retrieve a single estimate by id. | read | user:estimates:read | Current | |
Read-only. Acts onestimate Permission (capability) user:estimates:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Create an estimate or quote for a client. | write | user:estimates:write | Current | |
A core write; can be sent to the client. Acts onestimate Permission (capability) user:estimates:writeVersionAvailable since the API’s base version Webhook event estimate.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /accounting/account/ | Update an estimate, or delete one by setting vis_state to 1. | write | user:estimates:write | Current | |
Estimates are soft-deleted through this PUT by setting vis_state to 1. Acts onestimate Permission (capability) user:estimates:writeVersionAvailable since the API’s base version Webhook event estimate.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
PaymentsMethods for recording payments applied to invoices.4 | ||||||
| GET | /accounting/account/ | List payments recorded on an account. | read | user:payments:read | Current | |
Read-only. Acts onpayment Permission (capability) user:payments:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | Retrieve a single payment by id. | read | user:payments:read | Current | |
Read-only. Acts onpayment Permission (capability) user:payments:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Record a payment against an invoice. | write | user:payments:write | Current | |
Marks money as received against an invoice and can change the invoice status to paid. Acts onpayment Permission (capability) user:payments:writeVersionAvailable since the API’s base version Webhook event payment.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /accounting/account/ | Update a payment, or delete one by setting vis_state to 1. | write | user:payments:write | Current | |
Payments are soft-deleted through this PUT by setting vis_state to 1. Acts onpayment Permission (capability) user:payments:writeVersionAvailable since the API’s base version Webhook event payment.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Items & TaxesMethods for reusable line items and tax rates.4 | ||||||
| GET | /accounting/account/ | List reusable line items on an account. | read | user:billable_items:read | Current | |
Read-only. Items use the billable_items scope object, not an items scope. Acts onitem Permission (capability) user:billable_items:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Create a reusable line item. | write | user:billable_items:write | Current | |
Granted by the billable_items write scope. Acts onitem Permission (capability) user:billable_items:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /accounting/account/ | List tax rates on an account. | read | user:taxes:read | Current | |
Read-only. Acts ontax Permission (capability) user:taxes:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /accounting/account/ | Create a tax rate. | write | user:taxes:write | Current | |
Taxes support a real DELETE, unlike most accounting resources. Acts ontax Permission (capability) user:taxes:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ProjectsMethods for projects in the Projects API, keyed by business rather than account.5 | ||||||
| GET | /projects/business/ | List projects, keyed by business rather than account. | read | user:projects:read | Current | |
Read-only. The Projects API is keyed by businessId, a different identifier from the accountId used by accounting endpoints. Acts onproject Permission (capability) user:projects:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /projects/business/ | Retrieve a single project by id. | read | user:projects:read | Current | |
Read-only. Acts onproject Permission (capability) user:projects:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /projects/business/ | Create a project. | write | user:projects:write | Current | |
A core write in the Projects API. Acts onproject Permission (capability) user:projects:writeVersionAvailable since the API’s base version Webhook event project.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /projects/business/ | Update a project. | write | user:projects:write | Current | |
A write in the Projects API. Acts onproject Permission (capability) user:projects:writeVersionAvailable since the API’s base version Webhook event project.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /projects/business/ | Delete a project. | write | user:projects:write | Current | |
The Projects API uses a real DELETE, unlike accounting soft deletes. Acts onproject Permission (capability) user:projects:writeVersionAvailable since the API’s base version Webhook event project.deleteRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Time TrackingMethods for logged time in the Time Tracking API, keyed by business.5 | ||||||
| GET | /timetracking/business/ | List time entries, keyed by business. | read | user:time_entries:read | Current | |
Read-only. The Time Tracking API is keyed by businessId, like the Projects API. Acts ontime_entry Permission (capability) user:time_entries:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /timetracking/business/ | Retrieve a single time entry by id. | read | user:time_entries:read | Current | |
Read-only. Acts ontime_entry Permission (capability) user:time_entries:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /timetracking/business/ | Log a time entry. | write | user:time_entries:write | Current | |
Logged time can feed billing through projects and invoices. Acts ontime_entry Permission (capability) user:time_entries:writeVersionAvailable since the API’s base version Webhook event time_entry.createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /timetracking/business/ | Update a time entry. | write | user:time_entries:write | Current | |
A write in the Time Tracking API. Acts ontime_entry Permission (capability) user:time_entries:writeVersionAvailable since the API’s base version Webhook event time_entry.updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /timetracking/business/ | Delete a time entry. | write | user:time_entries:write | Current | |
The Time Tracking API uses a real DELETE. Acts ontime_entry Permission (capability) user:time_entries:writeVersionAvailable since the API’s base version Webhook event time_entry.deleteRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Events & CallbacksMethods for registering and verifying webhook callbacks.4 | ||||||
| GET | /events/account/ | List registered webhook callbacks on an account. | read | user:events:read | Current | |
Read-only. Acts oncallback Permission (capability) user:events:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /events/account/ | Register a webhook callback for an event, like invoice.create or payment.create. | write | user:events:write | Current | |
FreshBooks then sends a verification code to the callback URI, which must be confirmed before events flow. Acts oncallback Permission (capability) user:events:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /events/account/ | Confirm a callback with its verification code, or resend the code. | write | user:events:write | Current | |
The verification code doubles as the secret used to check the HMAC-SHA256 signature on delivered events. Acts oncallback Permission (capability) user:events:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /events/account/ | Remove a registered webhook callback. | write | user:events:write | Current | |
Stops events being sent to that callback URI. Acts oncallback Permission (capability) user:events:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
FreshBooks can notify an app when something happens in an account, like an invoice being created or a payment being recorded. It registers a callback, sends a verification code to confirm the receiver, then POSTs an event so an integration learns about activity without polling.
| Event | What it signals | Triggered by |
|---|---|---|
invoice.create | An invoice was created on the account. | /accounting/account/ |
invoice.update | An invoice was changed, including being soft-deleted by a visibility-state change. | /accounting/account/ |
invoice.delete | An invoice was deleted. | /accounting/account/ |
expense.create | An expense was recorded on the account. | /accounting/account/ |
expense.update | An expense was changed. | /accounting/account/ |
estimate.create | An estimate was created on the account. | /accounting/account/ |
estimate.update | An estimate was changed. | /accounting/account/ |
payment.create | A payment was recorded against an invoice. | /accounting/account/ |
payment.update | A payment was changed. | /accounting/account/ |
project.create | A project was created. | /projects/business/ |
project.update | A project was changed. | /projects/business/ |
project.delete | A project was deleted. | /projects/business/ |
time_entry.create | A time entry was logged. | /timetracking/business/ |
time_entry.update | A time entry was changed. | /timetracking/business/ |
time_entry.delete | A time entry was deleted. | /timetracking/business/ |
FreshBooks meters how fast an app can call and returns an HTTP 429 when a caller goes too fast. It does not publish a fixed per-minute number, so an integration backs off and retries when it is told to slow down.
FreshBooks throttles callers and returns an HTTP 429 (HTTP_RATE_LIMITED) when a caller sends requests too quickly. It does not publish a fixed per-minute number in the developer docs, and the limit is enforced on the server and can vary, so an integration treats a 429 as the signal to slow down rather than relying on a stated ceiling. The response indicates the caller should pause before sending more calls.
List endpoints page with page and per_page query parameters. Requesting page 0 returns page 1, and requesting past the last page returns an empty list. Search filters cover equals, in, like, between, datetime in ISO 8601, and boolean matching, and related data is pulled in with explicit includes rather than returned by default.
per_page is silently capped at 100, so a single page returns at most 100 records and larger datasets are read across multiple pages.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 401 | Unauthorized | No authentication token was provided, or it is invalid or expired. | Send a valid Bearer access token, and refresh it with the refresh token if it has expired. |
| 403 | AccessDenied (errno 1003) | The token is valid but lacks the scope or permission the call needs. A scope error names the scopes provided and the scopes required. | Re-authorize the app with the missing scope, like user:invoices:write, then retry. |
| 404 | UnknownResource (errno 1012) | The resource in the URL does not exist or is not visible to this user, account, or business. | Check the id, and confirm the accountId or businessId in the path matches the resource. |
| 422 | RequiredField (errno 1001) | Validation failed, for example a required field is missing. The response names the errno and a message. | Read the errno and message, fix the request body, and resend. |
| 429 | HTTP_RATE_LIMITED | Too many requests arrived too quickly and the caller was throttled. | Pause and retry with backoff, honoring any Retry-After signal before sending more calls. |
| 500 | Server error | An error on the FreshBooks side. It is rare. | Retry with backoff, and contact FreshBooks support if it persists. |
FreshBooks runs a single current Accounting API with no dated version string in the path. Changes ship through release notes rather than a pinned version, so an integration tracks the changelog instead of a version header.
FreshBooks runs a single current Accounting API with no dated version string in the path, alongside separate Projects and Time Tracking APIs keyed by businessId. New features and changes ship through FreshBooks release notes rather than a pinned version, so integrations track the changelog rather than a version header.
A year of additive changes shipped through release notes, with no path version change.
There is no version to pin; track the release notes for changes.
FreshBooks changes and updates ↗Bollard AI sits between a team's AI agents and FreshBooks. Grant each agent exactly the access it needs, read or write, resource by resource, and every call is checked and logged.