Skip to content
× FreshBooks App Logo
Official App
Free - Google Play
Get it
You're currently on our US site. Select your regional site here:

Get Authenticated On The FreshBooks API

You want to connect your app with FreshBooks so that you or FreshBooks customers can use your app. We’ll start this tutorial with the expectation that you already have a FreshBooks account (trial or paid), have read through the introduction and created an app with the appropriate scopes, and an https redirect uri.

FreshBooks provides OAuth 2.0 authorization code grant flow to authenticate on the FreshBooks api.

FreshBooks Oauth2.0 Flow

Before we begin, we will quickly navigate to the developer portal and select your application. Then, scroll to the bottom under ‘App Settings’ and copy your authorization url. The format of your authorization url is<REDIRECT_URL>&client_id=<CLIENT_ID>

Authentication URL

Using the FreshBooks Authorization Grant Flow

  1. Your app must redirect users to the authentication page to start the authentication process. The user reviews your app, the scopes it requests and provides consent to access their FreshBooks data on their behalf by clicking ‘Allow.’
Authorization Dialog
  1. Once the user clicks ‘Allow,’ FreshBooks redirects the user to the app redirect URI specified with a ‘code‘ query parameter, and this is your authorization code. Make sure your app server is actively listening for requests on your redirect uri.
authorization code
  1. As soon as your app receives the authorization code, your app must request a access  token using the code parameter retrieved above along with your client_id, client_secret, redirect_uri. Keep in mind the authorization code expires in 5 minutes.
curl -L -X POST '' \
-F 'grant_type="authorization_code"' \
-F 'client_id="943f08ec5a5797f579e2682103868216f2d00a64faf0fb36e8257c8acceebfc6"' \
-F 'client_secret="<APP_CLIENT_SECRET>"' \
-F 'code="6ccc545aecf51e5cbe9fc37da025281bc9e7662a1b7b1b492e67a3aa94b66021"' \
-F 'redirect_uri=""'
  1. We receive an access(bearer) token and a refresh token in the response below. Make sure to store the refresh token securely to be retrieved later
    "access_token": "eyJraWQiOiJhMTlPSlR5aVlKOXhPM3FoWnhWeE1KZE5ZNXJ4cUhpQzBSTUY0TWRheGtjIiwiYWxnIjoiUlMyNTYifQ.eyJqdGkiOiJiY2U1M2Y0NTNlMTVmNTM5MzJjYTQPwzR2-W1GOmodMQl7Nwtc3Gkc-1gXtPQYFixBrdQg",
    "token_type": "Bearer",
    "expires_in": 43200,
    "refresh_token": "f8cddb919402989a72918f55a8fe31f36f353d409e018781d0f59c44e1e59e03",
    "scope": "user:profile:read user:expenses:read user:expenses:write user:clients:read user:clients:write",
    "created_at": 1646237089,
    "direct_buy_tokens": {}
  1. Use the access token also known as a bearer token to make FreshBooks api call on behalf of the user. When making api calls you can pass the authorization by including a header in your api calls with the format Authorization : Bearer <YOUR_ACCESS_TOKEN>
  1. You can continue to keep making api calls with the access token until it expires. When the access token expires and you make an api call, you will get an http error status 401 unauthorized. This means that you need a new access token.
  1. On receiving the error message you will use the refresh token you stored earlier and request for a new pair of access & refresh tokens. This step is similar to the 4th step, the main difference here is that the grant_type is set to refresh_token and the key ‘code’ is replaced with refresh token as well, see example below.
curl -L -X POST '' \
-F 'grant_type="refresh_token"' \
-F 'client_id="943f08ec5a5797f579e2682103868216f2d00a64faf0fb36e8257c8acceebfc6"' \
-F 'client_secret="<APP_CLIENT_SECRET>"' \
-F 'refresh_token="f8cddb919402989a72918f55a8fe31f36f353d409e018781d0f59c44e1e59e03"' \
-F 'redirect_uri=""'
  1. As you see in the response below, you now have a new pair of access & refresh tokens. Replace the previous refresh token with the new one you just received and continue making api calls wih the new access token.
    "access_token": "eyJraWQiOiJhMTlPSlR5aVlKOXhPM3FoWnhWeE1KZE5ZNXJ4cUhpQzBSTUY0TWRheGtjIiwiYWxnnRsQQPFVR7TMQp9chBYe2C_xKCcWorSC9GPVr4V_kc9NJGg",
    "token_type": "Bearer",
    "expires_in": 43199,
    "refresh_token": "0ba22fec6606365569638d8d82ff99f689746e866c75fa3ff4ae55f10aac2930",
    "scope": "user:profile:read user:expenses:read user:expenses:write user:clients:read user:clients:write",
    "created_at": 1646237284,
    "direct_buy_tokens": {}

Things to keep in mind

  • The authorization code is valid for only 5 minutes
  • An access token is valid for 12 hours
  • A refresh token can only be used once to get an access token
  • You can proactively request a new access token based on the expiry time provided. Requesting a new access token via a refresh token invalidates the previous access token immediately

Ask us!

OAuth can get pretty complicated. If you’ve given this all a try and read as much documentation as you can find and you’re still running into problems, shoot us an email with information about what you’re doing, what you tried, and what went wrong, and we’ll do our best to help.

Good luck!