Webhooks

It’s easy to keep your application in sync with a FreshBooks account if you can publish scripts to a public web server. You can subscribe to FreshBooks Webhooks to receive real-time notifications from FreshBooks to your application.

What are Webhooks?

Webhooks are a "pattern of enabling user-defined callbacks in web applications" (1). In other words, they are a simple mechanism for sending notifications between APIs using HTTP POST callbacks. Webhooks allow you to specify a URI that you would like FreshBooks to POST information to any time certain events happen in a system. For instance, if you would like to receive a notification every time one of your users creates an invoice in FreshBooks, you can register a callback for the invoice.create method. There are over a dozen events you can register a callback against. One particularly exciting implication is that together with recent changes to our API, Webhooks allow you to do automated subscription billing with FreshBooks.

Using WebHooks

Webhooks can be created in your FreshBooks account by clicking on “My Account” and then “FreshBooks API” and then scrolling down to the “Customize” link in the Webhooks section, or with the FreshBooks API by calling the callback.create method.

In order to ensure that you are the true owner of a callback URI being registered, we’ve implemented a very simple verification mechanism. When a callback is first registered, we will automatically (and immediately) send an HTTP POST request containing a unique verification code as well as a unique id for the callback record being verified. Simply send the verification code and the callback id back to us by calling the callback.verify API method and notifications will begin being sent to your registered callback URI.

The transaction looks something like this:

Step One: Create a callback using the callback.create API method:

<request method="callback.create">
  <callback>
    <event>estimate.create</event>
    <uri>http://example.com/webhooks/ready</uri>
  </callback>
</request>

FreshBooks will immediately POST to the URI specified in the callback.create request with the following form-urlencoded parameters:

name: callback.verify
object_id: An integer identifying the callback
verifier: A unique verification code
system: The login URI of the system that generated the event
user_id: The id of the user who initiated the event

Step Two: Verify the callback using the callback.verify API method:

<request method="callback.verify">
 <callback>
   <callback_id>45</callback_id>
   <verifier>3awmbZMdPtf7vMZGvmJeRB2mYRC9D3UKE</verifier>
 </callback>
</request>

That’s it! Your callback is ready to go. Now, when a user in this system creates an estimate, FreshBooks will send a POST request to http://example.com/webhooks/ready with the following form-urlencoded parameters:

name: estimate.create
object_id: 30
system: https://2ndsite.freshbooks.com/
user_id: 1

This means that the user with the id ’1′ in the system ‘https://2ndsite.freshbooks.com/’ created an estimate with the id ’30′. You can then call the FreshBooks API method estimate.get, passing in estimate id 30 in order to get details about the estimate.

You can also list and delete callbacks using the callback.list and callback.delete API methods.

NOTE: If you create a callback record before your script is ready to receive the verification code, you can resend the verification code with a call to callback.resendToken.

Failed Callbacks

Once your Webhooks are set up and verified, you will start receiving events. If FreshBooks receives anything other than a 2xx HTTP response code (likely meaning that your web script has moved, is non-existent, or misconfigured) we will retry the HTTP POST request periodically. After several failures, the message will be dropped and no further delivery attempts will be made.

Example Conversation

The following is an example of the HTTP requests and responses involved in creating a Webhook.

1. Creating the callback using the FreshBooks API.

Request:

POST /api/2.1/xml-in HTTP/1.1
Authorization: OAuth ...
User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8k zlib/1.2.3
Host: 2ndsite.freshbooks.com
Accept: */*
Content-Length: 124
Content-Type: application/x-www-form-urlencoded

<request method="callback.create">
  <callback>
    <event>invoice.create</event>
    <uri>http://www.example.com/webhook</uri>
  </callback>
</request>

Response:

HTTP/1.1 200 OK
Date: Wed, 02 Dec 2009 18:26:59 GMT
Server: Apache/2.2.8 (EL)
X-Powered-By: PHP/5.2.6
Cache-control: private
Content-Length: 144
Connection: close
Content-Type: application/xml

<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="ok">
  <callback_id>1</callback_id>
</response>

2. Verification information is sent to the callback URI.

Request:

POST /webhook HTTP/1.1
Host: www.example.com
Accept-Encoding: identity
Content-Length: 130
content-type: application/x-www-form-urlencoded
user-agent: FreshHooks/0.4 (http://developers.freshbooks.com/api/webhooks)

name=callback.verify&object_id=1&system=https%3A%2F%2F2ndsite.freshbooks.com&user_id=1&verifier=3bPTNcPgbN76QLgKLSR9XdgQJWvhhN4xrT

3. Verifying the callback using the FreshBooks API.

Request:

POST /api/2.1/xml-in HTTP/1.1
Authorization: OAuth ...
User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8k zlib/1.2.3
Host: 2ndsite.freshbooks.com
Accept: */*
Content-Length: 148
Content-Type: application/x-www-form-urlencoded

<request method="callback.verify">
  <callback>
    <callback_id>1</callback_id>
    <verifier>3bPTNcPgbN76QLgKLSR9XdgQJWvhhN4xrT</verifier>
  </callback>
</request>

Response:

HTTP/1.1 200 OK
Date: Wed, 02 Dec 2009 20:09:07 GMT
Server: Apache/2.2.8 (EL)
X-Powered-By: PHP/5.2.6
Cache-control: private
Content-Length: 102
Connection: close
Content-Type: application/xml

<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="ok"/>

4. Your first Webhook.

Request:

POST /webhook HTTP/1.1
Host: www.example.com
Accept-Encoding: identity
Content-Length: 86
content-type: application/x-www-form-urlencoded
user-agent: FreshHooks/0.4 (http://developers.freshbooks.com/api/webhooks)

user_id=1&system=https%3A%2F%2F2ndsite.freshbooks.com&object_id=49&name=invoice.delete

Response:

Entirely up to you! Just send us back an HTTP 2xx response code if everything worked out alright.

1. http://www.slideshare.net/progrium/using-web-hooks (Slide # 21)

Search