10,000ft API Tutorial: Time Entries In Depth

Curious about the 10,000ft API? Unsure about how to start exploring the potential of the API? This tutorial will guide you through the basics of a fundamental part of the API, and the 10,000ft app in general: time entries. After reading this article, you’ll have a solid understanding of the time entries API resource, and you’ll be well-equipped to continue exploring the 10,000ft API.

In this tutorial we will:

  • Learn basic concepts about time entries
  • Review some standard requests
  • Introduce code samples illustrating different ways to use the Time Entries resource

Key Concepts

1. Time entries data model: First, let’s take a look at the time entries data model, which is simply a description of the various properties that each time entry contains. Here is an example time entry response from the API:

As the illustration shows, time entries have multiple properties, including an id, assignable_id, assignable_type, and so on. The assignable_id refers to the id of the assignable (which can be a project, project phase, or leave type) to which the time entry belongs. Similarly, the user_id refers to the id of the user to whom the entry belongs. The hours and date properties contain the number of hours a person logged on a certain date. The other properties contain information about bill rates, notes, whether or not the time entry is a suggested time entry (see Concept #3 below), and info about when the time entry was created or updated in the database.

2. Time entries are a top-level resource and a subresource: Time entries are associated with both a user and an assignable (a project, phase, or leave type). As such, we can access time entries through both the User endpoint and the Project endpoint. In this regard, the time entries resource is a subresource of both users and projects.

For example, issuing the API request /api/v1/users/<user_id>/time_entries will return the time entries associated with that particular user. Note, however, that time entries are also a top-level resource and you can use the API request /api/v1/time_entries to get all time entries for your organization’s account.

3. The two types of time entries: There are two types of time entries: suggested and confirmed.

Suggested time entries are created when an assignment is created for a particular person. They appear as slightly translucent suggestions on an individual’s profile page:

By contrast, confirmed time entries are created when someone explicitly tracks time n a project, either via the 10,000ft app or the API. In the 10,000ft app, they appear as opaque time entries on a person’s profile page:

When using the API, there’s a slight difference between suggested and confirmed time entries, which we’ll explore in the next section.

Standard Requests

Throughout this section I’ll use a tool called Postman to illustrate the API requests and responses. If you’re not familiar with this tool, here is a quick tutorial. Another option for exploring APIs is cURL, a command line tool, but I’ll stick with Postman because it has a nice user interface. You can follow along with me by using Postman with your own organization’s API token.

To get started, we’ll perform one of the most basic requests: getting a particular user’s time entries for all time. To do this, we’ll issue a GET request to the API endpoint /api/v1/users/<user_id>/time_entries. When we send this request to the server, the server will respond with the paging data and the user’s time entries.

These screenshots show this request-response cycle in Postman (auth token omitted):

This user has only one time entry for December 4, 2017, and the entry is for the project with assignable_id 17.

This particular user has only one time entry, but what if the user has dozens or hundreds of time entries? You may want to limit the data set in some way. For example, we can fetch a user’s time entries during a specific timeframe using the following GET request format: /api/v1/users/<user_id>/time_entries?from=<date>&to=<date>. In Postman, I’ll get a particular user’s time entries for a certain week (note that I’ve selected Postman’s Raw display format so that we can see all the data):

By default, the API returns confirmed time entries for both users and projects. You can see in both of the above examples that the property is_suggestion is false. You must attach the parameter with_suggestions=true to get suggested time entries.

The two examples above illustrate GET requests, wherein we request data from the API. But what if we want to create a new time entry via the API?

To accomplish this task, we can issue a POST to the API, along with the data it needs to create the time entry. That data must include the user_id, assignable_id, a date, and the hours tracked. Optionally, you can send other fields such as task, bill_rate_id, etc. Here is an example using Postman:

Notice that when we POST a time entry, we receive the newly-created entry back from the server. Additionally, we now see the new time entry on the user’s profile page in the 10,000ft app:

There are other ways to GET or POST data from or to the API, but we’ve covered the basics in this section. You can modify these basic requests by adding or removing parameters. Getting time entries associated with projects follows the same patterns; just change the request /api/v1/users/<user_id>/time_entries to /api/v1/projects/<project_id>/time_entries.

Code Examples

At this point, we know everything we need to start using the time entries API resource in our code. In this section, I’ll walk through three examples of different ways to use the time entries API. I’ll use JavaScript combined with jQuery (for making the server requests) in these examples, but they are easily modifiable to other languages.

Example 1: Sort Time Entries

Let’s say you want to discover the users with the most and least tracked time in your organization. We already know how to get all time entries for the entire company. Once we have those entries, we can sum all the entries for each user, sort the summed values, and finally get the first and last elements from the list. Here’s a code sample:

var API_BASE_ADDRESS = "https://api.10000ft.com/api/v1";

// Make the API call
     url: API_BASE_ADDRESS + "/time_entries",
     success: setTimeEntries

// Set the time_entries variable and perform operations (summation and sorting)
function setTimeEntries(data) {
   var time_entries = data.data;
   var summed_entries = buildUserTimeEntriesArray(time_entries)
   console.log("Min: " + summed_entries[0].hours + ", user_id: "  + summed_entries[0].user_id);
   console.log("Max: " + summed_entries[summed_entries.length - 1].hours + ", user_id:  " + summed_entries[summed_entries.length - 1].user_id);

 function buildUserTimeEntriesArray(time_entries) {
   var user_time_entries = [];
   time_entries.forEach(function(entry) {
     var te = findInArray(user_time_entries, entry.user_id);
     if (te) {
       te.hours += entry.hours;
     } else {
           user_id: entry.user_id,
           hours: entry.hours
   return user_time_entries;

 function findInArray(user_array, user_id) {
   for(var i = 0; i < user_array.length; i++) {
     if (user_array[i]["user_id"] === user_id) {
       return user_array[i];
   return null;

 function sortEntries(time_entries) {
   time_entries.sort(function(a, b) {
     return a.hours - b.hours;

Example 2: Find the mean and median

In this example, we’ll perform some basic data manipulations on time entries to find the mean and median of tracked time entries. This could be useful for reporting purposes or data visualizations. To accomplish this, we’ll fetch all the organization’s time entries from the server, and then perform the calculations. Here is a code sample:

     url: API_BASE_ADDRESS + "/time_entries",
     success: getSuggestedHours

// Set the time entries to a variable, then calculate mean and median
function setTimeEntries(data) {
   var time_entries = data.data;

   // Find and print the mean
   var mean = findMean(time_entries);
   console.log("The mean is: " + mean);

   // Find and print the median
   var median = findMedian(time_entries);
   console.log("The median is: " + median);

function findMean(time_entries) {
   var sum = 0;
   time_entries.forEach(function(element) {
     sum += element.hours;
   return sum / time_entries.length;

function findMedian(time_entries) {
    time_entries.sort(function(a, b) {
     return a.hours - b.hours;

   var mid_index = Math.floor(time_entries.length / 2);
   if (time_entries.length % 2 === 0) {
     var m = time_entries.slice(mid_index, mid_index + 2);
     mid_index = Math.floor(findMean(m));  // we can re-use our findMean function
   return time_entries[mid_index]["hours"];

Example 3: Calculate ratio of confirmed to suggested time entries

For our last example, we’ll take a look at making two API calls to fetch both confirmed and suggested time entries. After we make those calls and have the data, we can calculate the ratio of confirmed to suggested time entries. Like Example 2, this data could be useful for reporting purposes or data visualizations. Here, we’ll use jQuery’s $.when method to chain two API calls together. Here’s the code sample:

// Fetch confirmed and suggested time entries
     $.ajax(API_BASE_ADDRESS + "/time_entries"), $.ajax(API_BASE_ADDRESS + "/time_entries?with_suggestions=true")

// setTimeEntries takes two data sets as parameters
function setTimeEntries(data1, data2) {
   var confirmed_time_entries = data1[0].data;
   var suggested_time_entries = data2[0].data;

   var num_confirmed = confirmed_time_entries.length;
   var num_suggested = suggested_time_entries.length;
   var ratio = num_confirmed / num_suggested;



This article provided some insights into the time entries resource of the 10,000ft API. We learned basic concepts, reviewed standard API requests and responses, and illustrated some different ways to use the time entries API. For more information about the time entries resource - and the 10,000ft API in general - visit our API docs.

The possibilities of using the API are limitless! Feel free to reach out at support@10000ft.com with any questions about this tutorial, and let us know how you’ve used API integrations in your organization.

Kristen Webster
January 9th, 2018
Receive expert insights, tips + tricks every month
Get our newsletter