{"id":537,"date":"2009-08-11T20:05:39","date_gmt":"2009-08-12T02:05:39","guid":{"rendered":"http:\/\/www.mooreds.com\/wordpress\/archives\/000537"},"modified":"2009-08-11T20:07:52","modified_gmt":"2009-08-12T02:07:52","slug":"using-apis-to-move-time-entries-from-freshbooks-to-harvest","status":"publish","type":"post","link":"https:\/\/www.mooreds.com\/wordpress\/archives\/537","title":{"rendered":"Using APIs to move time entries from FreshBooks to Harvest"},"content":{"rendered":"<p>I recently was working for a client who has their own time tracking system&#8211;they use <a href=\"http:\/\/www.getharvest.com\/\">Harvest<\/a>.\u00a0 They want me to enter time that I work for them into that system&#8211;they want more insight into my time use than monthly invoice. However, I still use my own invoicing system, <a href=\"http:\/\/www.freshbooks.com\/?ref=7c28734f96649-1\">FreshBooks<\/a> (more <a href=\"\/wordpress\/archives\/000517\">on that choice here<\/a>) and will need to invoice them as well.\u00a0 Before the days when APIs were common, or if either of these sites did not have an API, I would have had three, equally unsavory, choices:<\/p>\n<ul>\n<li>Convince the client to use my system or at least access it for whatever data they needed<\/li>\n<li>Send reports (spreadsheets) to the client from my system and let them process it<\/li>\n<li>Enter my time in both places.\u00a0 This option would have won, as I don&#8217;t like to inconvenience people who write me checks.<\/li>\n<\/ul>\n<p>Luckily, both Harvest and FreshBooks provide APIs for time tracking (<a href=\"http:\/\/www.getharvest.com\/api\/time_tracking\">Harvest doco here<\/a>, <a href=\"http:\/\/developers.freshbooks.com\/api\/view\/time_entries\/\">FreshBooks doco here<\/a>). I was surprised at how similar the time tracking data formats were.\u00a0 With the combination of curl, gnu date, sed, Perl and bash, I was able to write a small script (~80 lines) that<\/p>\n<ul>\n<li>pulled down my time data for this client, for this week, from FreshBooks (note you have to enable API access to your account for this to work)<\/li>\n<li>mapped it it from the FreshBooks format to the Harvest format<\/li>\n<li>then posted it to Harvest.<\/li>\n<\/ul>\n<p>A couple of caveats:<\/p>\n<ul>\n<li>I still log in to Harvest to submit my time (I didn&#8217;t see a way to submit my time in the API documentation), but it&#8217;s a heck a lot easier to press one button and submit a weeks worth of time than to do double entry.<\/li>\n<li>I used similar project and task codes in both systems (or, more accurately, I set up the FreshBooks tasks and projects to map to the Harvest ones, since FreshBooks is what I had control over).\u00a0 That mapping was probably the most tedious part of writing the script.<\/li>\n<\/ul>\n<p>You can view <a href=\"\/files\/fb-to-harvest.txt\">my script here<\/a>, or at least a sanitized version thereof.\u00a0 it took about an hour and a half to do this. Double entry might have been quicker in the short term, but now I&#8217;m not worried about entry mistakes, and submitting my time every week is easy!\u00a0 I could also have used XSLT to transform from one data format to the other, but they were so similar it was easier just parse text.<\/p>\n<p>[tags]getharvest,freshbooks,time tracking, process automation[\/tags]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently was working for a client who has their own time tracking system&#8211;they use Harvest.\u00a0 They want me to enter time that I work for them into that system&#8211;they [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[35,10,6,20],"tags":[],"class_list":["post-537","post","type-post","status-publish","format-standard","hentry","category-business","category-dynamic-languages","category-programming","category-web-applications"],"_links":{"self":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/537","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/comments?post=537"}],"version-history":[{"count":0,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/537\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/media?parent=537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/categories?post=537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/tags?post=537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}