How To Add Time Entries For Your Employees Using The Time Entry API
Use Case
As a business owner, you offer services to your Clients that are invoiced based on the time you spent on a project. Currently, your employees keep track of their time on a third-party software, but you’d like to keep your records up-to-date, so you decide to log the time entries of each employee on FreshBooks as well. This would mean your employees would have to log in to FreshBooks to log the time entries, making it prone to human error. Let’s take a look at an example of how we can bypass this using the API.
Business Owner: Lygel
Business Name: Dev Rel FreshBooks
Employee: Tess Junior
Project: Project-102
Service: Business registry
Hours: 40
Objective: To eliminate human error, log time entries via the FreshBooks API on behalf of Tess for the project named Project-102
What do you need to get started?
- FreshBooks account with a team member on it
- Postman or know your way around a cURL request
Step-By-Step Guide:
1. Create Staff Through the FreshBooks UI
Invite your employee to join your FreshBooks account, adding them as an Employee. Learn how to do this by reading our support documentation. In our case, we have registered Tess as an employee at Dev Rel FreshBooks.
2. Create Your OAuth App
To quickly get started with the FreshBooks API, we will need to create an app on the developer page. This app will be the OAuth representation of our external app. Make sure that you select the below mentioned scopes during app creation.
- user:time_entries:write
- user:time_entries:read
- user:projects:read
- user:clients:read
- user:billable_items:read
- user:teams:read
We will then need to authenticate ourselves on the FreshBooks API. If you don’t know how how to do this, check out our OAuth authentication tutorial.
3. Find the ‘business id’
Once we are authenticated on the FreshBooks API & have the necessary scopes, we will use the FreshBooks /me
API to find the ‘business id’ for the business ‘Dev Rel FreshBooks’.
$.response.business_memberships[1].business.id : 10005870
curl -L -X GET
'https://api.freshbooks.com/auth/api/v1/users/me?exclude_groups=1' \
-H 'Authorization: Bearer <insert-bearer-token>'
#Response
{
"response":{
"id":5814555,
"profile":{
"setup_complete":true,
"first_name":"Owner",
"last_name":"101",
"phone_number":null,
"address":null,
"professions":[
{
"id":5461807,
"business_id":5802399,
"title":"Business Consulting",
"company":"SportSupport B.V",
"designation":null
}
],
"has_password":true,
"is_email_confirmed":true
},
"identity_id":5814555,
"identity_uuid":"048a5001-0001-97f6-45da-3777a24522fa",
"first_name":"Owner",
"last_name":"101",
"email":"lygel.dmello@freshbooks.com",
"language":"en",
"confirmed_at":"2020-12-10T13:29:47Z",
"created_at":"2020-12-01T13:16:47Z",
"unconfirmed_email":null,
"setup_complete":true,
"phone_numbers":[
{
"title":"",
"phone_number":null
}
],
"addresses":[
null
],
"profession":{
"id":5461807,
"business_id":5802399,
"title":"Business Consulting",
"company":"SportSupport B.V",
"designation":null
},
"links":{
"me":"/service/auth/api/v1/users?id=5814555",
"roles":"/service/auth/api/v1/users/role/5814555"
},
"subscription_statuses":{
"AQd4ZB":"active",
"LJArJ4":"active_trial"
},
"integrations":{
},
"business_memberships":[
{
"id":15740145,
"role":"owner",
"unacknowledged_change":false, "fasttrack_token":"eyJhbGciOiJIUzI1NiJ9.eyJmYXN0dHJhY2tfaWRlbnRpdHlfaWQiOiI1ODE0NTU1IiwiZmFzdHRyYWNrX3N5c3RlbV9pZCI6IjU5NjcyMjUiLCJmYXN0dHJhY2tfYnVzaW5lc3NfaWQiOiI1NzkyMTAxIiwiY3JlYXRlZF9hdCI6IjIwMjEtMDktMjRUMDk6NDU6NTYrMDA6MDAifQ.cAWIA-ZtRm3LVKI8uJzzioD8F63EXKGJ1xBfGpt324U",
"business":{
"id":5792101,
"business_uuid":"048a5001-0002-475a-32d6-c9a509f6cc5d",
"name":"SportVision B.V.",
"account_id":"AQd4ZB",
"date_format":"dd/mm/yyyy",
"active":true,
"timezone":null,
"address":{
"id":6915151,
"street":"Schoutwtjeslaan",
"city":"Haarlem",
"province":"North Holland",
"country":"Netherlands",
"postal_code":"2012KE"
},
"phone_number":{
"id":2699053,
"phone_number":"0683138539"
},
"business_clients":[
{
"id":981887,
"business_id":5792101,
"account_id":"pJp6Wr",
"userid":148345,
"client_business":{
"business_id":5792101
},
"account_business":{
"account_business_id":6026715,
"account_id":"pJp6Wr"
}
}
]
}
},
{
"id":23716544,
"role":"owner",
"unacknowledged_change":false, "fasttrack_token":"eyJhbGciOiJIUzI1NiJ9.eyJmYXN0dHJhY2tfaWRlbnRpdHlfaWQiOiI1ODE0NTU1IiwiZmFzdHRyYWNrX3N5c3RlbV9pZCI6IjY4MDEyNDYiLCJmYXN0dHJhY2tfYnVzaW5lc3NfaWQiOiIxMDAwNTg3MCIsImNyZWF0ZWRfYXQiOiIyMDIxLTA5LTI0VDA5OjQ1OjU2KzAwOjAwIn0.cNSpVYYcQILeXmyJRSUd1Vj3hyM7kIRhH4Ou5T7qxH4",
"business":{
"id":10005870,
"business_uuid":"9419d591-efcb-4cea-8e53-f9e74d9023b1",
"name":"Dev Rel FreshBooks",
"account_id":"LJArJ4",
"date_format":"mm/dd/yyyy",
"active":true,
"timezone":null,
"address":{
"id":11267165,
"street":null,
"city":null,
"province":null,
"country":"Canada",
"postal_code":null
},
"phone_number":null,
"business_clients":[
]
}
}
],
"identity_origin":"magnum",
"timezone":null,
"roles":[
{
"id":6172325,
"role":"admin",
"systemid":5967225,
"userid":1,
"created_at":"2020-12-01T13:16:47Z",
"links":{
"destroy":"/service/auth/api/v1/users/role/6172325"
},
"accountid":"AQd4ZB"
},
{
"id":10552028,
"role":"admin",
"systemid":6801246,
"userid":1,
"created_at":"2021-07-05T11:42:15Z",
"links":{
"destroy":"/service/auth/api/v1/users/role/10552028"
},
"accountid":"LJArJ4"
}
]
}
}
4. Get The List of Staff Identities
Next, we’ll need to find the ‘identity id’ by which Tess is represented in FreshBooks. For this we will use the ‘business id’ we found in the last step, to call the staff API for your business. The ‘identity id’ represents a unique user within FreshBooks.
$.response.business_group.members[?(@.role == "business_employee")].identity_id : 9333107
curl -L -X GET 'https://api.freshbooks.com/auth/api/v1/users/business/10005870' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <insert-bearer-token>'
#Response
{
"response": {
"id": 10005870,
"business_uuid": "9419d591-efcb-4cea-8e53-f9e74d9023b1",
"name": "Dev Rel FreshBooks",
"account_id": "LJArJ4",
"business_group": {
"id": 19108932,
"category": "business",
"members": [
{
"id": 23716544,
"group_id": 19108932,
"role": "owner",
"identity_id": 5814555,
"identity_uuid": "048a5001-0001-97f6-45da-3777a24522fa",
"first_name": "Owner",
"last_name": "101",
"language": "en",
"email": "lygel.dmello@freshbooks.com",
"company": "Dev Rel FreshBooks",
"business_id": 10005870,
"unacknowledged_change": false,
"active": true
},
{
"id": 25254045,
"group_id": 19108932,
"role": "business_employee",
"identity_id": 9333107,
"identity_uuid": "15f27794-514e-469a-9f97-a8eabd219efb",
"first_name": "Tess",
"last_name": "Junior",
"language": "en",
"email": "lygel.dmello+emp1@freshbooks.com",
"company": "Dev Rel FreshBooks",
"business_id": 10005870,
"unacknowledged_change": false,
"active": true
}
]
},
"date_format": "mm/dd/yyyy",
"active": true,
"timezone": null,
"address": {
"id": 11267165,
"street": null,
"city": null,
"province": null,
"country": "Canada",
"postal_code": null
},
"phone_number": null,
"business_clients": []
}
}
5. Get Details Related to Project-102
Now we need to get the ‘project id’ for Project-102 that Tess is working on. We will also need the id for the services and the client that are associated with the project. We will use the /project API for this.
$.projects[?(@.title == "Project-102")].id: 9262631
$.projects[?(@.title == "Project-102")].client_id: 213933
$.projects[?(@.title == "Project-102")].services[0].id: 21980226
curl -L -X GET 'https://api.freshbooks.com/projects/business/10005870/projects' \
-H 'Authorization: Bearer <insert-bearer-token>'
#Response
{
"meta": {
"sort": [],
"total": 2,
"per_page": 30,
"page": 1,
"pages": 1
},
"projects": [
{
"id": 9262631,
"title": "Project-102",
"description": "Scaling business",
"due_date": "2021-09-30",
"client_id": 213933,
"internal": false,
"budget": 144000,
"fixed_price": null,
"rate": "0.00",
"billing_method": "project_rate",
"project_type": "hourly_rate",
"project_manager_id": null,
"active": true,
"complete": false,
"sample": false,
"created_at": "2021-09-24T09:09:11",
"updated_at": "2021-09-24T09:09:12",
"logged_duration": null,
"services": [
{
"business_id": 10005870,
"id": 21980226,
"name": "Business registry",
"billable": true,
"vis_state": 0
},
{
"business_id": 10005870,
"id": 21980227,
"name": "Legal consultation",
"billable": true,
"vis_state": 0
},
{
"business_id": 10005870,
"id": 21980228,
"name": "Documentation service",
"billable": true,
"vis_state": 0
}
],
"billed_amount": "0.00",
"billed_status": "unbilled",
"retainer_id": null,
"expense_markup": "10",
"service_estimate_type": "total_hours",
"group_id": 19934028
},
{
"id": 9260421,
"title": "Project-101",
"description": "Setting up the foundations of business",
"due_date": "2021-09-30",
"client_id": 213933,
"internal": false,
"budget": 3240000,
"fixed_price": null,
"rate": "0.00",
"billing_method": "project_rate",
"project_type": "hourly_rate",
"project_manager_id": null,
"active": true,
"complete": false,
"sample": false,
"created_at": "2021-09-23T12:52:35",
"updated_at": "2021-09-23T12:52:39",
"logged_duration": null,
"services": [
{
"business_id": 10005870,
"id": 21980226,
"name": "Business registry",
"billable": true,
"vis_state": 0
},
{
"business_id": 10005870,
"id": 21980227,
"name": "Legal consultation",
"billable": true,
"vis_state": 0
},
{
"business_id": 10005870,
"id": 21980228,
"name": "Documentation service",
"billable": true,
"vis_state": 0
}
],
"billed_amount": "0.00",
"billed_status": "unbilled",
"retainer_id": null,
"expense_markup": "10",
"service_estimate_type": "total_hours",
"group_id": 19928951
}
]
}
6. Create a Time Entry on Behalf of the Employee
Now that we have all the details, we need to create a time entry. Let’s create a time entry on behalf of Tess using the /time_entries API.
curl -L -X POST 'https://api.freshbooks.com/timetracking/business/10005870/time_entries' \
-H 'Authorization: Bearer <insert-bearer-token>' \
-H 'Content-Type: application/json' \
--data-raw '{
"time_entry":{
"is_logged":true,
"duration": 36000,
"note":" Business registration",
"started_at":"2021-09-23T09:00:00.000Z",
"billable":true,
"billed":false,
"identity_id":"9333107",
"client_id":"213933",
"project_id":"9262631",
"service_id":"21980226"
}
}'
#Response
{
"time_entry": {
"id": 191921121,
"identity_id": 9333107,
"is_logged": true,
"local_started_at": "2021-09-27T09:00:00",
"local_timezone": "UTC",
"started_at": "2021-09-27T09:00:00Z",
"created_at": "2021-09-27T11:45:28Z",
"client_id": 213933,
"project_id": 9262631,
"pending_client": null,
"pending_project": null,
"pending_task": null,
"task_id": 12602,
"service_id": 21980228,
"note": " Business guidelines",
"active": true,
"billable": true,
"billed": false,
"internal": false,
"retainer_id": null,
"duration": 36000,
"timer": null
}
}
And that’s how you create a time entry on behalf of your employees using the FreshBooks API.
Still have questions? Something isn’t working right? Don’t hesitate to reach out to us at newapi@freshbooks.com. We’ll respond to your request as quickly as we can!