×
Freshbooks
Official App
Free – Google Play
Get it

Authentication

Industry Standard

The new FreshBooks uses OAuth2 for authentication. OAuth2 is an authorization framework that enables applications to obtain limited access to user accounts over HTTP, and is used by services like Google, Facebook, Stripe, and Slack. This method creates a token that lasts for 12 hours to keep your account secure and connected. For more details about how OAuth2 itself, check out: the official documentation.

Use a Library!

If you’re a developer of a web application using Python, Ruby, or Javascript, it’s recommended that you use a popular library written in your language of choice to manage the details of connecting via OAuth2. Such libraries typically provide configuration options for you to include your client_id, client_secret, and redirect_uri, then allow you to make higher level calls in your program to initiate or refresh authorization.

If you wish to manage that complexity yourself, you can request a Bearer and Refresh token pair from our auth/token endpoint using the process descibed in the code pane on this page.

Basic Flow

  1. A user visits your Authorization link, which you supply on your website, and which we supply clickable versions of on your app management page.
  2. They are sent to an Authorization page we host.
  3. The user logs in and clicks 'Authorize'.
  4. They are redirected back to your website with a code parameter in the URL.
  5. You send us a request from your server containing the code, your client id, client secret, and the redirect uri the user followed, as seen in the code pane on this page.
  6. We return to you a Bearer and Refresh token pair.
  7. You make successful calls on that user's behalf. Congrats!

Redirect URI Limitations

For security reasons, redirect URIs must specify HTTPS as their protocol. While testing/develping your application, if you are unable to set up a self signed certificate to use or to work in a secured public test environment, you may manually change the URL to HTTP in your browser to complete the connection.

Redirect URIs also cannot contain query string parameters. Your application may instead url-encode arbitrary data and pass into an Authorize link via an additional state parameter. That state parameter and its value will be inserted into the Redirect URI when the client is sent there after granting permission to your application to continue.

Multiple Redirect URIs are allowed per application, specified on separate lines of the Redirect URI field on the developer page.

Refresh Tokens and Token Lifespans

Bearer Tokens are not long lived. They last for 12 hours, after which they are no longer able to authenticate requests, and may produce different errors depending upon the service being called. The remedy to use in these situations is a Refresh Token.

Refresh Tokens live forever, but are one-time-use, and only one Refresh Token can be alive at any time per user per application. A new Refresh Token is generated every time a Bearer Token is issued for a given user of a given application, and all old Refresh Tokens immediately become invalid. Make sure that whenever you receive a new Bearer Token, you write its companion Refresh token down somewhere safe to refresh your access, or you'll have to re-authorize your application again manually.

Bearer Tokens don't interfere with each other's lives the same way, so you could have several valid Bearer Tokens at any given point in time. They only expire when you manually POST to the token/revoke endpoint or when their time runs out.

Making a Refresh Token Call

Make a Refresh call by following the same template shown in the code pane on this page, but supply a grant type of 'refresh' instead of 'authorization', and instead of a 'code' argument, supply a 'refresh_token' argument with the most recent Refresh Token you were granted.

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!

Authorizing with OAuth2

Request to api.freshbooks.com/auth/oauth/token:

curl -X POST -H "Api-Version: alpha" -H "Content-Type: application/json" -d '{
  "grant_type": "authorization_code",
  "client_secret": "<insert your secret>",
  "code": "<insert your authorization code>",
  "client_id": "<insert your client id>",
  "redirect_uri": "https://localhost:3000/just_an_example"
}' "https://api.freshbooks.com/auth/oauth/token"

Response:

{
  "access_token": "lots_of_letters_and_numbers",
  "token_type": "bearer",
  "expires_in": 43200,
  "refresh_token": "same_as_the_bearer_token",
  "created_at": 1424471407
}

Authorizing with OAuth2

Request to api.freshbooks.com/auth/oauth/token:

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.freshbooks.com/auth/oauth/token",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\n    \"grant_type\": \"authorization_code\",\n    \"client_secret\": \"<insert your secret>\",\n    \"code\": \"<insert your authorization code>\",\n    \"client_id\": \"<insert your client id>\",\n    \"redirect_uri\": \"https://localhost:3000/just_an_example\"\n}",
  CURLOPT_HTTPHEADER => array(
    "api-version: alpha",
    "cache-control: no-cache",
    "content-type: application/json",
    "postman-token: 471a0741-8466-2e3f-0006-8b9c3794ef9d"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

$response should be:

{
  "access_token" => "lots_of_letters_and_numbers",
  "token_type" => "bearer",
  "expires_in" => 43200,
  "refresh_token" => "same_as_the_bearer_token",
  "created_at" => 1472471407
}