As an IT consultant who subcontracts from various companies, I enter my hours in at least 3 different systems on any given day.

  1. My own company’s system hosted on Freshbooks – This is the master copy since my invoicing is driven by it
  2. Quickbooks, two of my clients use it and require me to enter hours in there for accurate billing
  3. GHG’s Timesheet software – err… this abomination of an app barely functions, forget asking for an API

I want to be able to record hours on all 3 systems in one click or even from my iPhone.


Freshbooks’ API is very clean and they have an iPhone app, so this is the least of my worries.


<request method="time_entry.create">
<project_id>1</project_id>        # Associated project_id (Required)
<task_id>1</task_id>              # Associated task_id    (Required)
<hours>4.5</hours>                # (Optional)
<notes>Freshbooks Test</notes> # (Optional)
<date>2007-01-01</date>           # (Optional)


<response status="ok">

Almost too easy. :) Thank you Freshbooks.

Quickbooks (the Big Kahuna)

Quickbooks doesn’t have an API, but have exposed API-like functionality to their Outlook plugin and Vista Gadget. Since Vista Gadgets (and Apple Dashboard Widgets as well) are just html/javascript, some simple hacking revealed exactly what I needed.

“Extracting” the Quickbooks Time Tracker Vista Gadget’s protocol

I first downloaded the .gadget file from Quickbooks’ site after logging in. Since this is a CAB (Cabinet) file, you can open it natively within Windows or use File Juicer on the Mac. The CAB file reveals a directory structure with tons of images, html files, and javascript files. From here, it’s relatively easy to find the right files you need.

Of particular interest are:


After about half an hour of hacking at the javascript code and many invalid cURL requests to the QB server, this is essentially the protocol I was able to get working:

“GetLists” – Obtains the list of customers and service jobs from the Quickbooks server


POST Body:


cURL command for debugging: curl -v -d -X POST

Make sure you put the POST body above in a file named “” in the same directory where you run cURL. It’ll use the contents of the file as the POST body.

And you will receive all the Customer Names and Service Items in JSON (fake company names/IDs for confidentiality):

{"CustomerJobs":[{"Name":"Food Network","ID":"999999"},{"Name":"Food Network:Rachael Ray","ID":"7777777"},{"Name":"Cartoon Network","ID":"25252525"},{"Name":"Cartoon Network:Family Guy","ID":"2343333"},{"Name":"Vacation","ID":"888888"}],"ServiceItems":[{"Name":"Contractor-Admin work","ID":"111111"},{"Name":"Contractor-Support Work","ID":"222222"},{"Name":"Contractor-Support Work:Training","ID":"33333"},{"Name":"Support Work","ID":"444444"},{"Name":"Support Work:Maintenance Work","ID":"5555555"}]}

The easiest way for me to quickly inspect a JSON struct is to fire up the Ruby interactive console (irb) and do the following:

>> require 'rubygems'
=> false
>> require 'json' # 'sudo gem install json' if you don't have the json gem
=> true
>> a = JSON.parse('customers.json'))

… ‘a’ now has the json struct

From here, I can iterate through the hash and inspect its keys and data:

>> a.keys
=> ["ServiceItems", "CustomerJobs"]
>> a['CustomerJobs'].each do |job| puts job['Name'] end

… prints out all the customer job names

Voila! We have the first half (and arguably the easier half) of this Quickbooks API project.

In the next part, I will outline how I did the second half, the actual Time Entry piece. (After I figure it out)


  1. I had limited success :) and I started contacting the Quickbooks team to see if they’d open it up anyway, and got COMPLETELY swamped with my current client. I have to work on this in coming weeks.

    Have you had any luck?

  2. Clever sleuthing! Im envious of the resourcefulness you employed.

    So, its been a year or more and it doesnt look like Quickbooks has opened the API, so Im assuming they dont have plans. Has there been any progress on dissecting the time entry aspect of the API? Im very interested in building my own interface for TimeTracker, but need a little help with the API.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Made by Themes Kult