At Fathom Data we use Clockify to keep detailed records of the time that we spend working on our clients’ projects. Up until fairly recently we manually generated timesheets at the end of each month that were sent through to the clients along with their invoices. Our experience has been that providing detailed timesheets helps foster trust and transparency. However, with a growing team and an expanding clientele, generating these timesheets has become progressively more laborious. Time to automate!
Luckily Clockify exposes an extensive API. I built a small R package, {clockify} which is a wrapper around the Clockify API, making it easy to tap into our timesheet data. We’re then using R Markdown to generate some pretty sweet automated timesheets and reports. This reporting all happens automatically courtesy of GitLab CI. But that’s a story for another day. Let’s take a look at {clockify}.
This post documents the features in {clockify}-0.0.9.
Installation
You can install the latest development version straight from GitHub.
Once you’ve installed the package, load it into R and check the version.
library(clockify)packageVersion("clockify")
[1] '0.0.9.9000'
API Key
You’re going to need to have an API key from your Clockify account. If you don’t yet have an account, create one. Then retrieve the API key from the account settings.
Get Started
Set the API key to be used for the session. I store my API key in an environment variable called CLOCKIFY_API_KEY.
Let’s turn on logging so we can see what’s happening behind the scenes.
library(logger)log_threshold(DEBUG)
Workspaces
Clockify uses workspaces to group people and projects. Every Clockify account is automatically associated with a default workspace, but may be linked to other workspaces too.
Use workspaces() to retrieve a list of available workspaces.
workspaces()
2022-03-18 05:33:28 — GET /workspaces
# A tibble: 2 × 2
workspace_id name
<chr> <chr>
1 5ef46294df73063139f60bfc Fathom Data
2 61343c45ab05e02be2c8c1fd Personal
I have two workspaces associated with my account, Personal and Work.
Select the Personal workspace. All subsequent operations will apply within this workspace.
workspace("61343c45ab05e02be2c8c1fd")
2022-03-18 05:33:28 — Set active workspace -> 61343c45ab05e02be2c8c1fd.
[1] "61343c45ab05e02be2c8c1fd"
Users
The users() function generates a table of all users linked to the workspace.
users()
2022-03-18 05:33:28 — GET /workspaces/61343c45ab05e02be2c8c1fd/users
# A tibble: 2 × 3
user_id user_name status
<chr> <chr> <chr>
1 5f227e0cd7176a0e6e754409 Andrew ACTIVE
2 5ef46293df73063139f60bf5 Emma ACTIVE
Retrieve information from your user profile.
user()
2022-03-18 05:33:28 — GET /user
# A tibble: 1 × 3
user_id user_name status
<chr> <chr> <chr>
1 5f227e0cd7176a0e6e754409 Andrew ACTIVE
Clients
Who do you work for? Let’s get a list of clients associated with the workspace.
clients()
2022-03-18 05:33:28 — GET /workspaces/61343c45ab05e02be2c8c1fd/clients
# A tibble: 2 × 3
client_id workspace_id client_name
<chr> <chr> <chr>
1 61343c6c00dc8f48962b9be9 61343c45ab05e02be2c8c1fd Community
2 61343c5d00dc8f48962b9be3 61343c45ab05e02be2c8c1fd Fathom Data
Projects
Get a table of projects. The endpoint used to retrieve projects is paginated, so there are multiple API calls to retrieve the complete list.
projects()
2022-03-18 05:33:28 — GET /workspaces/61343c45ab05e02be2c8c1fd/projects
2022-03-18 05:33:28 — Page contains 2 results.
2022-03-18 05:33:28 — GET /workspaces/61343c45ab05e02be2c8c1fd/projects
2022-03-18 05:33:28 — Page is empty.
2022-03-18 05:33:28 — API returned 2 results.
# A tibble: 8 × 3
id description duration
<chr> <chr> <dbl>
1 61343cc1777d5361dcdea70a Set up GitHub Actions 12
2 61343d06777d5361dcdea729 Make coffee 5
3 61343d27ab05e02be2c8c266 Populate README.Rmd 68
4 613448d7777d5361dcdead37 Add GET /workspaces/{workspaceId}/projects/… 12.0
5 61344bcad01d3b4a27a82310 Add GET /workspaces/{workspaceId}/projects/… 31.8
6 6134548f00dc8f48962bace7 Add GET /ticker/{symbol1}/{symbol2} 16.0
7 6134585a777d5361dcdebc5c Add GET /tickers/{symbol1}/{symbol2}/.../{s… 16.5
8 61345c45d01d3b4a27a833c7 Add GET /last_price/{symbol1}/{symbol2} 31.6
Test Coverage
I’ve started writing unit tests. You can check on the current test coverage here. Evidently there’s still work to be done!
Hex logo for the {clockify} package.
Conclusion
Exposing an API adds a lot of value to Clockify as a time tracking product. If you’re using Clockify, then you’ll find the {clockify} package convenient and useful for accessing those data. It plays particularly well in automated reporting scenarios.