User- The FreshBooks account, whose information we are trying to access via OAuthConsumer- The FreshBooks account, who we authorize to access the user's informationConsumer key- The consumer's subdomain,consumer_key.freshbooks.comConsumer Secret- The consumer's secret, that we will use to make OAuth requests.Request Token- A value used by the consumer to obtain authorization and an access token from the user.Access Token- A value used by the consumer to access the user's information.Access Token Secret- A secret used by the consumer to establish ownership of a given Token.Callback URL- URL you want the user to be redirected to, after the user authorization step.Nonce- A nonce is a random string, uniquely generated for each request.Timestamp- The current number of seconds since January 1, 1970 00:00:00 GMT.
- On your FreshBooks account, go to "My Account", then "FreshBooks API".
- Enable OAuth under the "OAuth Developer Access" section:
- Fill out the authorization form:
- Once you've gained access, you'll see your
Consumer Secret.
This can be any FreshBooks account, even the consumer account.
- Make sure the following parameters are set on the Authorization header:
- OAuth realm=""
- oauth_version="1.0"
- oauth_consumer_key="<
CONSUMER_SUBDOMAIN>" - oauth_timestamp="
<TIMESTAMP>" - oauth_nonce="
<NONCE>" - oauth_signature_method="PLAINTEXT"
- oauth_signature="
<CONSUMER SECRET>%2526" - oauth_callback="
<CALLBACK URL>"
- Make a POST to the following URL:
https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_request.php - You'll receive a response from the server with both an
oauth_tokenand anoauth_token_secret. Make sure you store those two values somewhere.
- The
userhas to now authorize theconsumerto access their data, so theuserhas to open up the following url in a browser:https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_authorize.php?oauth_token=<oauth_token> - If the oauth_token is valid, the
userwill be asked to sign in and allow access. - You'll receive a verifier, which you should store.
- If a
<CALLBACK_URL>was defined, theuserwill be redirected to the URL with the verifier as a query string:<CALLBACK_URL?verifier=<VERIFIER_VALUE> - If a
<CALLBACK_URL>was not defined, the<VERIFIER_VALUE>will be displayed on the page.
- You'll be making another post now, to get your Access tokens. Make sure you swap out the right values on the Authorization header:
- OAuth realm=""
- oauth_version="1.0"
- oauth_consumer_key="
<CONSUMER_SUBDOMAIN>" - oauth_timestamp="
<TIMESTAMP>" - oauth_nonce="
<NONCE>" - oauth_signature_method="PLAINTEXT"
- oauth_signature="
<CONSUMER SECRET>%2526" - oauth_token="
<OAUTH_TOKEN>" - oauth_verifier="
<VERIFIER_VALUE>"
- Make a POST to the following URL:
https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_access.php - You'll finally receive a response from the server with new
oauth_tokenand anoauth_token_secretvalues. Make sure you store those two values somewhere.
- You're now able to make API calls with OAuth! Make sure you swap out the right values in the Authorization header:
- OAuth realm=""
- oauth_version="1.0"
- oauth_consumer_key="
<CONSUMER_SUBDOMAIN>" - oauth_timestamp="
<TIMESTAMP>" - oauth_nonce="
<NONCE>" - oauth_signature_method="PLAINTEXT"
- oauth_signature="
<CONSUMER_SECRET>%2526<OAUTH_TOKEN_SECRET>" - oauth_token="
<OAUTH_TOKEN>"
- Make a POST to the following URL:
https://<USER SUBDOMAIN>.freshbooks.com/api/2.1/xml-in
Here's an example using purely curl commands. Today's consumer will be darthvader.freshbooks.com, who will be trying to access rebels.freshbooks.com's data.
- Preparing our authorization header
- oauth_consumer_key:
darthvader - oauth_timestamp:
1368630669 - oauth_nonce:
UU7gRl0HDdt - oauth_signature:
G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526
- Posting to
https://rebels.freshbooks.com/oauth/oauth_request.phpwith the following values in our Authorization header:
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_timestamp="1368630669",oauth_nonce="UU7gRl0HDdt",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526",oauth_callback=""' -X POST https://rebels.freshbooks.com/oauth/oauth_request.php
- Which gives us the following response:
oauth_token=ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2&oauth_token_secret=SSF4aRtvFEEX9wBWqebrfpskufHrLtU7V&oauth_callback_confirmed=true
-
Using the obtained oauth_token, I open up the following URL in my browser:
https://rebels.freshbooks.com/oauth_oauth_authorize.php?oauth_token=ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2 -
Since I didn't provide a callback_url, the verifier was right on the page for me:
fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu
- Preparing our authorization header
- oauth_consumer_key:
darthvader - oauth_token:
ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2 - oauth_timestamp:
1368630857 - oauth_nonce:
bDu0qrocMxD - oauth_signature:
G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526 - oauth_verifier:
fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu
- Posting to
https://rebels.freshbooks.com/oauth/oauth_access.php
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_token="ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2",oauth_timestamp="1368630857",oauth_nonce="bDu0qrocMxD",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526",oauth_verifier="fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu"' -X POST https://rebels.freshbooks.com/oauth/oauth_access.php
- Which gives us the following response:
oauth_token=KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv&oauth_token_secret=MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC
- Preparing our authorization header
- oauth_consumer_key:
darthvader - oauth_token:
KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv - oauth_timestamp:
1368631017 - oauth_nonce:
ddtCiqS5nlZ - oauth_signature:
G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC
- Making a post to
https://rebels.freshbooks.com/api/2.1/xml-in:
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_token="KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv",oauth_timestamp="1368631017",oauth_nonce="ddtCiqS5nlZ",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC"' -X POST https://rebels.freshbooks.com/api/2.1/xml-in -d '<request method="invoice.list" />'
- Which gives us the following response:
<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="ok">
<invoices page="1" per_page="25" pages="1" total="1">
<invoice>
<invoice_id>00000248946</invoice_id>
<organization>Princess Leia</organization>
<first_name>Leia</first_name>
<last_name>Organa</last_name>
<lines>
<line>
<line_id>1</line_id>
<name>Death Star Plans</name>
<unit_cost>10000000000000000.00</unit_cost>
<quantity>1</quantity>
<amount>10000000000000000.00</amount>
<type>Item</type>
</line>
</lines>
</invoice>
</invoices>
</response>

Hi Anton
I find your article more interesting.
My questions are:
1.) Under the Find a FreshBooks account(above), when I created my Account and I have setup an Accountant and Staff (under People Tab), Do they qualify as a FreshBook Account?
I think I have the same case for Robert J you'd answered from this link: https://groups.google.com/forum/#!topic/freshbooks-api/SOFTZJSb9DM
2.) I was able to successfully simulate all your steps except for the last one: Accessing User Data
I am using google's postman as a debugger... I'm trying to pull the client's list (...e.g.) I am getting
an (20010) Authentication failed error.
Your answer is very much appreciated.
Thank you
Regards;
Alfred